aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/clock.c
diff options
context:
space:
mode:
authorSekhar Nori <nsekhar@ti.com>2009-08-31 06:18:02 -0400
committerKevin Hilman <khilman@deeprootsystems.com>2009-11-25 13:21:20 -0500
commitde381a91f544008f4f99571e2ef1f60b92d5f0cf (patch)
treef15d31d2a7de9379e3fac9300eb2a2a190eab4a4 /arch/arm/mach-davinci/clock.c
parentf02bf3b396846f3da60b4962aeaae8652e20f0dd (diff)
davinci: make clock rate re-calculation easy
Make clock rate recalculation easy by having a re-calculate function for each clock. The existing functions for calculation of output rates of PLL and PLL-derived sysclks have been convered to the new re-calculate API. A new function is introduced to take care of rate (re)calculation for leaf clocks. Signed-off-by: Sekhar Nori <nsekhar@ti.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-davinci/clock.c')
-rw-r--r--arch/arm/mach-davinci/clock.c69
1 files changed, 49 insertions, 20 deletions
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index f8c4ef08fbc2..6de1e3428f1f 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -135,8 +135,12 @@ int clk_register(struct clk *clk)
135 if (clk->rate) 135 if (clk->rate)
136 return 0; 136 return 0;
137 137
138 /* Else, see if there is a way to calculate it */
139 if (clk->recalc)
140 clk->rate = clk->recalc(clk);
141
138 /* Otherwise, default to parent rate */ 142 /* Otherwise, default to parent rate */
139 if (clk->parent) 143 else if (clk->parent)
140 clk->rate = clk->parent->rate; 144 clk->rate = clk->parent->rate;
141 145
142 return 0; 146 return 0;
@@ -184,50 +188,62 @@ static int __init clk_disable_unused(void)
184late_initcall(clk_disable_unused); 188late_initcall(clk_disable_unused);
185#endif 189#endif
186 190
187static void clk_sysclk_recalc(struct clk *clk) 191static unsigned long clk_sysclk_recalc(struct clk *clk)
188{ 192{
189 u32 v, plldiv; 193 u32 v, plldiv;
190 struct pll_data *pll; 194 struct pll_data *pll;
195 unsigned long rate = clk->rate;
191 196
192 /* If this is the PLL base clock, no more calculations needed */ 197 /* If this is the PLL base clock, no more calculations needed */
193 if (clk->pll_data) 198 if (clk->pll_data)
194 return; 199 return rate;
195 200
196 if (WARN_ON(!clk->parent)) 201 if (WARN_ON(!clk->parent))
197 return; 202 return rate;
198 203
199 clk->rate = clk->parent->rate; 204 rate = clk->parent->rate;
200 205
201 /* Otherwise, the parent must be a PLL */ 206 /* Otherwise, the parent must be a PLL */
202 if (WARN_ON(!clk->parent->pll_data)) 207 if (WARN_ON(!clk->parent->pll_data))
203 return; 208 return rate;
204 209
205 pll = clk->parent->pll_data; 210 pll = clk->parent->pll_data;
206 211
207 /* If pre-PLL, source clock is before the multiplier and divider(s) */ 212 /* If pre-PLL, source clock is before the multiplier and divider(s) */
208 if (clk->flags & PRE_PLL) 213 if (clk->flags & PRE_PLL)
209 clk->rate = pll->input_rate; 214 rate = pll->input_rate;
210 215
211 if (!clk->div_reg) 216 if (!clk->div_reg)
212 return; 217 return rate;
213 218
214 v = __raw_readl(pll->base + clk->div_reg); 219 v = __raw_readl(pll->base + clk->div_reg);
215 if (v & PLLDIV_EN) { 220 if (v & PLLDIV_EN) {
216 plldiv = (v & PLLDIV_RATIO_MASK) + 1; 221 plldiv = (v & PLLDIV_RATIO_MASK) + 1;
217 if (plldiv) 222 if (plldiv)
218 clk->rate /= plldiv; 223 rate /= plldiv;
219 } 224 }
225
226 return rate;
227}
228
229static unsigned long clk_leafclk_recalc(struct clk *clk)
230{
231 if (WARN_ON(!clk->parent))
232 return clk->rate;
233
234 return clk->parent->rate;
220} 235}
221 236
222static void __init clk_pll_init(struct clk *clk) 237static unsigned long clk_pllclk_recalc(struct clk *clk)
223{ 238{
224 u32 ctrl, mult = 1, prediv = 1, postdiv = 1; 239 u32 ctrl, mult = 1, prediv = 1, postdiv = 1;
225 u8 bypass; 240 u8 bypass;
226 struct pll_data *pll = clk->pll_data; 241 struct pll_data *pll = clk->pll_data;
242 unsigned long rate = clk->rate;
227 243
228 pll->base = IO_ADDRESS(pll->phys_base); 244 pll->base = IO_ADDRESS(pll->phys_base);
229 ctrl = __raw_readl(pll->base + PLLCTL); 245 ctrl = __raw_readl(pll->base + PLLCTL);
230 clk->rate = pll->input_rate = clk->parent->rate; 246 rate = pll->input_rate = clk->parent->rate;
231 247
232 if (ctrl & PLLCTL_PLLEN) { 248 if (ctrl & PLLCTL_PLLEN) {
233 bypass = 0; 249 bypass = 0;
@@ -260,9 +276,9 @@ static void __init clk_pll_init(struct clk *clk)
260 } 276 }
261 277
262 if (!bypass) { 278 if (!bypass) {
263 clk->rate /= prediv; 279 rate /= prediv;
264 clk->rate *= mult; 280 rate *= mult;
265 clk->rate /= postdiv; 281 rate /= postdiv;
266 } 282 }
267 283
268 pr_debug("PLL%d: input = %lu MHz [ ", 284 pr_debug("PLL%d: input = %lu MHz [ ",
@@ -275,7 +291,9 @@ static void __init clk_pll_init(struct clk *clk)
275 pr_debug("* %d ", mult); 291 pr_debug("* %d ", mult);
276 if (postdiv > 1) 292 if (postdiv > 1)
277 pr_debug("/ %d ", postdiv); 293 pr_debug("/ %d ", postdiv);
278 pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000); 294 pr_debug("] --> %lu MHz output.\n", rate / 1000000);
295
296 return rate;
279} 297}
280 298
281int __init davinci_clk_init(struct davinci_clk *clocks) 299int __init davinci_clk_init(struct davinci_clk *clocks)
@@ -286,12 +304,23 @@ int __init davinci_clk_init(struct davinci_clk *clocks)
286 for (c = clocks; c->lk.clk; c++) { 304 for (c = clocks; c->lk.clk; c++) {
287 clk = c->lk.clk; 305 clk = c->lk.clk;
288 306
289 if (clk->pll_data) 307 if (!clk->recalc) {
290 clk_pll_init(clk); 308
309 /* Check if clock is a PLL */
310 if (clk->pll_data)
311 clk->recalc = clk_pllclk_recalc;
312
313 /* Else, if it is a PLL-derived clock */
314 else if (clk->flags & CLK_PLL)
315 clk->recalc = clk_sysclk_recalc;
316
317 /* Otherwise, it is a leaf clock (PSC clock) */
318 else if (clk->parent)
319 clk->recalc = clk_leafclk_recalc;
320 }
291 321
292 /* Calculate rates for PLL-derived clocks */ 322 if (clk->recalc)
293 else if (clk->flags & CLK_PLL) 323 clk->rate = clk->recalc(clk);
294 clk_sysclk_recalc(clk);
295 324
296 if (clk->lpsc) 325 if (clk->lpsc)
297 clk->flags |= CLK_PSC; 326 clk->flags |= CLK_PSC;