diff options
author | Sekhar Nori <nsekhar@ti.com> | 2009-08-31 06:18:02 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2009-11-25 13:21:20 -0500 |
commit | de381a91f544008f4f99571e2ef1f60b92d5f0cf (patch) | |
tree | f15d31d2a7de9379e3fac9300eb2a2a190eab4a4 /arch/arm/mach-davinci/clock.c | |
parent | f02bf3b396846f3da60b4962aeaae8652e20f0dd (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.c | 69 |
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) | |||
184 | late_initcall(clk_disable_unused); | 188 | late_initcall(clk_disable_unused); |
185 | #endif | 189 | #endif |
186 | 190 | ||
187 | static void clk_sysclk_recalc(struct clk *clk) | 191 | static 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 | |||
229 | static 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 | ||
222 | static void __init clk_pll_init(struct clk *clk) | 237 | static 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 | ||
281 | int __init davinci_clk_init(struct davinci_clk *clocks) | 299 | int __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; |