1/* 2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17#include <linux/kernel.h> 18#include <linux/io.h> 19#include <linux/delay.h> 20#include <linux/err.h> 21#include <linux/slab.h> 22#include <linux/clk-provider.h> 23#include <linux/clk.h> 24 25#include "clk.h" 26 27#define SUPER_STATE_IDLE 0 28#define SUPER_STATE_RUN 1 29#define SUPER_STATE_IRQ 2 30#define SUPER_STATE_FIQ 3 31 32#define SUPER_STATE_SHIFT 28 33#define SUPER_STATE_MASK ((BIT(SUPER_STATE_IDLE) | BIT(SUPER_STATE_RUN) | \ 34 BIT(SUPER_STATE_IRQ) | BIT(SUPER_STATE_FIQ)) \ 35 << SUPER_STATE_SHIFT) 36 37#define SUPER_LP_DIV2_BYPASS (1 << 16) 38 39#define super_state(s) (BIT(s) << SUPER_STATE_SHIFT) 40#define super_state_to_src_shift(m, s) ((m->width * s)) 41#define super_state_to_src_mask(m) (((1 << m->width) - 1)) 42 43static u8 clk_super_get_parent(struct clk_hw *hw) 44{ 45 struct tegra_clk_super_mux *mux = to_clk_super_mux(hw); 46 u32 val, state; 47 u8 source, shift; 48 49 val = readl_relaxed(mux->reg); 50 51 state = val & SUPER_STATE_MASK; 52 53 BUG_ON((state != super_state(SUPER_STATE_RUN)) && 54 (state != super_state(SUPER_STATE_IDLE))); 55 shift = (state == super_state(SUPER_STATE_IDLE)) ? 56 super_state_to_src_shift(mux, SUPER_STATE_IDLE) : 57 super_state_to_src_shift(mux, SUPER_STATE_RUN); 58 59 source = (val >> shift) & super_state_to_src_mask(mux); 60 61 /* 62 * If LP_DIV2_BYPASS is not set and PLLX is current parent then 63 * PLLX/2 is the input source to CCLKLP. 64 */ 65 if ((mux->flags & TEGRA_DIVIDER_2) && !(val & SUPER_LP_DIV2_BYPASS) && 66 (source == mux->pllx_index)) 67 source = mux->div2_index; 68 69 return source; 70} 71 72static int clk_super_set_parent(struct clk_hw *hw, u8 index) 73{ 74 struct tegra_clk_super_mux *mux = to_clk_super_mux(hw); 75 u32 val, state; 76 int err = 0; 77 u8 parent_index, shift; 78 unsigned long flags = 0; 79 80 if (mux->lock) 81 spin_lock_irqsave(mux->lock, flags); 82 83 val = readl_relaxed(mux->reg); 84 state = val & SUPER_STATE_MASK; 85 BUG_ON((state != super_state(SUPER_STATE_RUN)) && 86 (state != super_state(SUPER_STATE_IDLE))); 87 shift = (state == super_state(SUPER_STATE_IDLE)) ? 88 super_state_to_src_shift(mux, SUPER_STATE_IDLE) : 89 super_state_to_src_shift(mux, SUPER_STATE_RUN); 90 91 /* 92 * For LP mode super-clock switch between PLLX direct 93 * and divided-by-2 outputs is allowed only when other 94 * than PLLX clock source is current parent. 95 */ 96 if ((mux->flags & TEGRA_DIVIDER_2) && ((index == mux->div2_index) || 97 (index == mux->pllx_index))) { 98 parent_index = clk_super_get_parent(hw); 99 if ((parent_index == mux->div2_index) || 100 (parent_index == mux->pllx_index)) { 101 err = -EINVAL; 102 goto out; 103 } 104 105 val ^= SUPER_LP_DIV2_BYPASS; 106 writel_relaxed(val, mux->reg); 107 udelay(2); 108 109 if (index == mux->div2_index) 110 index = mux->pllx_index; 111 } 112 val &= ~((super_state_to_src_mask(mux)) << shift); 113 val |= (index & (super_state_to_src_mask(mux))) << shift; 114 115 writel_relaxed(val, mux->reg); 116 udelay(2); 117 118out: 119 if (mux->lock) 120 spin_unlock_irqrestore(mux->lock, flags); 121 122 return err; 123} 124 125const struct clk_ops tegra_clk_super_ops = { 126 .get_parent = clk_super_get_parent, 127 .set_parent = clk_super_set_parent, 128}; 129 130struct clk *tegra_clk_register_super_mux(const char *name, 131 const char **parent_names, u8 num_parents, 132 unsigned long flags, void __iomem *reg, u8 clk_super_flags, 133 u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock) 134{ 135 struct tegra_clk_super_mux *super; 136 struct clk *clk; 137 struct clk_init_data init; 138 139 super = kzalloc(sizeof(*super), GFP_KERNEL); 140 if (!super) { 141 pr_err("%s: could not allocate super clk\n", __func__); 142 return ERR_PTR(-ENOMEM); 143 } 144 145 init.name = name; 146 init.ops = &tegra_clk_super_ops; 147 init.flags = flags; 148 init.parent_names = parent_names; 149 init.num_parents = num_parents; 150 151 super->reg = reg; 152 super->pllx_index = pllx_index; 153 super->div2_index = div2_index; 154 super->lock = lock; 155 super->width = width; 156 super->flags = clk_super_flags; 157 158 /* Data in .init is copied by clk_register(), so stack variable OK */ 159 super->hw.init = &init; 160 161 clk = clk_register(NULL, &super->hw); 162 if (IS_ERR(clk)) 163 kfree(super); 164 165 return clk; 166} 167