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 24 #include "clk.h" 25 26 #define SUPER_STATE_IDLE 0 27 #define SUPER_STATE_RUN 1 28 #define SUPER_STATE_IRQ 2 29 #define SUPER_STATE_FIQ 3 30 31 #define SUPER_STATE_SHIFT 28 32 #define SUPER_STATE_MASK ((BIT(SUPER_STATE_IDLE) | BIT(SUPER_STATE_RUN) | \ 33 BIT(SUPER_STATE_IRQ) | BIT(SUPER_STATE_FIQ)) \ 34 << SUPER_STATE_SHIFT) 35 36 #define SUPER_LP_DIV2_BYPASS (1 << 16) 37 38 #define super_state(s) (BIT(s) << SUPER_STATE_SHIFT) 39 #define super_state_to_src_shift(m, s) ((m->width * s)) 40 #define super_state_to_src_mask(m) (((1 << m->width) - 1)) 41 42 static u8 clk_super_get_parent(struct clk_hw *hw) 43 { 44 struct tegra_clk_super_mux *mux = to_clk_super_mux(hw); 45 u32 val, state; 46 u8 source, shift; 47 48 val = readl_relaxed(mux->reg); 49 50 state = val & SUPER_STATE_MASK; 51 52 BUG_ON((state != super_state(SUPER_STATE_RUN)) && 53 (state != super_state(SUPER_STATE_IDLE))); 54 shift = (state == super_state(SUPER_STATE_IDLE)) ? 55 super_state_to_src_shift(mux, SUPER_STATE_IDLE) : 56 super_state_to_src_shift(mux, SUPER_STATE_RUN); 57 58 source = (val >> shift) & super_state_to_src_mask(mux); 59 60 /* 61 * If LP_DIV2_BYPASS is not set and PLLX is current parent then 62 * PLLX/2 is the input source to CCLKLP. 63 */ 64 if ((mux->flags & TEGRA_DIVIDER_2) && !(val & SUPER_LP_DIV2_BYPASS) && 65 (source == mux->pllx_index)) 66 source = mux->div2_index; 67 68 return source; 69 } 70 71 static int clk_super_set_parent(struct clk_hw *hw, u8 index) 72 { 73 struct tegra_clk_super_mux *mux = to_clk_super_mux(hw); 74 u32 val, state; 75 int err = 0; 76 u8 parent_index, shift; 77 unsigned long flags = 0; 78 79 if (mux->lock) 80 spin_lock_irqsave(mux->lock, flags); 81 82 val = readl_relaxed(mux->reg); 83 state = val & SUPER_STATE_MASK; 84 BUG_ON((state != super_state(SUPER_STATE_RUN)) && 85 (state != super_state(SUPER_STATE_IDLE))); 86 shift = (state == super_state(SUPER_STATE_IDLE)) ? 87 super_state_to_src_shift(mux, SUPER_STATE_IDLE) : 88 super_state_to_src_shift(mux, SUPER_STATE_RUN); 89 90 /* 91 * For LP mode super-clock switch between PLLX direct 92 * and divided-by-2 outputs is allowed only when other 93 * than PLLX clock source is current parent. 94 */ 95 if ((mux->flags & TEGRA_DIVIDER_2) && ((index == mux->div2_index) || 96 (index == mux->pllx_index))) { 97 parent_index = clk_super_get_parent(hw); 98 if ((parent_index == mux->div2_index) || 99 (parent_index == mux->pllx_index)) { 100 err = -EINVAL; 101 goto out; 102 } 103 104 val ^= SUPER_LP_DIV2_BYPASS; 105 writel_relaxed(val, mux->reg); 106 udelay(2); 107 108 if (index == mux->div2_index) 109 index = mux->pllx_index; 110 } 111 val &= ~((super_state_to_src_mask(mux)) << shift); 112 val |= (index & (super_state_to_src_mask(mux))) << shift; 113 114 writel_relaxed(val, mux->reg); 115 udelay(2); 116 117 out: 118 if (mux->lock) 119 spin_unlock_irqrestore(mux->lock, flags); 120 121 return err; 122 } 123 124 const struct clk_ops tegra_clk_super_mux_ops = { 125 .get_parent = clk_super_get_parent, 126 .set_parent = clk_super_set_parent, 127 }; 128 129 static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate, 130 unsigned long *parent_rate) 131 { 132 struct tegra_clk_super_mux *super = to_clk_super_mux(hw); 133 struct clk_hw *div_hw = &super->frac_div.hw; 134 135 __clk_hw_set_clk(div_hw, hw); 136 137 return super->div_ops->round_rate(div_hw, rate, parent_rate); 138 } 139 140 static unsigned long clk_super_recalc_rate(struct clk_hw *hw, 141 unsigned long parent_rate) 142 { 143 struct tegra_clk_super_mux *super = to_clk_super_mux(hw); 144 struct clk_hw *div_hw = &super->frac_div.hw; 145 146 __clk_hw_set_clk(div_hw, hw); 147 148 return super->div_ops->recalc_rate(div_hw, parent_rate); 149 } 150 151 static int clk_super_set_rate(struct clk_hw *hw, unsigned long rate, 152 unsigned long parent_rate) 153 { 154 struct tegra_clk_super_mux *super = to_clk_super_mux(hw); 155 struct clk_hw *div_hw = &super->frac_div.hw; 156 157 __clk_hw_set_clk(div_hw, hw); 158 159 return super->div_ops->set_rate(div_hw, rate, parent_rate); 160 } 161 162 const struct clk_ops tegra_clk_super_ops = { 163 .get_parent = clk_super_get_parent, 164 .set_parent = clk_super_set_parent, 165 .set_rate = clk_super_set_rate, 166 .round_rate = clk_super_round_rate, 167 .recalc_rate = clk_super_recalc_rate, 168 }; 169 170 struct clk *tegra_clk_register_super_mux(const char *name, 171 const char **parent_names, u8 num_parents, 172 unsigned long flags, void __iomem *reg, u8 clk_super_flags, 173 u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock) 174 { 175 struct tegra_clk_super_mux *super; 176 struct clk *clk; 177 struct clk_init_data init; 178 179 super = kzalloc(sizeof(*super), GFP_KERNEL); 180 if (!super) 181 return ERR_PTR(-ENOMEM); 182 183 init.name = name; 184 init.ops = &tegra_clk_super_mux_ops; 185 init.flags = flags; 186 init.parent_names = parent_names; 187 init.num_parents = num_parents; 188 189 super->reg = reg; 190 super->pllx_index = pllx_index; 191 super->div2_index = div2_index; 192 super->lock = lock; 193 super->width = width; 194 super->flags = clk_super_flags; 195 196 /* Data in .init is copied by clk_register(), so stack variable OK */ 197 super->hw.init = &init; 198 199 clk = clk_register(NULL, &super->hw); 200 if (IS_ERR(clk)) 201 kfree(super); 202 203 return clk; 204 } 205 206 struct clk *tegra_clk_register_super_clk(const char *name, 207 const char * const *parent_names, u8 num_parents, 208 unsigned long flags, void __iomem *reg, u8 clk_super_flags, 209 spinlock_t *lock) 210 { 211 struct tegra_clk_super_mux *super; 212 struct clk *clk; 213 struct clk_init_data init; 214 215 super = kzalloc(sizeof(*super), GFP_KERNEL); 216 if (!super) 217 return ERR_PTR(-ENOMEM); 218 219 init.name = name; 220 init.ops = &tegra_clk_super_ops; 221 init.flags = flags; 222 init.parent_names = parent_names; 223 init.num_parents = num_parents; 224 225 super->reg = reg; 226 super->lock = lock; 227 super->width = 4; 228 super->flags = clk_super_flags; 229 super->frac_div.reg = reg + 4; 230 super->frac_div.shift = 16; 231 super->frac_div.width = 8; 232 super->frac_div.frac_width = 1; 233 super->frac_div.lock = lock; 234 super->div_ops = &tegra_clk_frac_div_ops; 235 236 /* Data in .init is copied by clk_register(), so stack variable OK */ 237 super->hw.init = &init; 238 239 clk = clk_register(NULL, &super->hw); 240 if (IS_ERR(clk)) 241 kfree(super); 242 243 return clk; 244 } 245