diff options
Diffstat (limited to 'arch/arm/mach-davinci/clock.c')
-rw-r--r-- | arch/arm/mach-davinci/clock.c | 231 |
1 files changed, 198 insertions, 33 deletions
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 83d54d50b5ea..baece65cb9c0 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c | |||
@@ -17,8 +17,8 @@ | |||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/mutex.h> | 19 | #include <linux/mutex.h> |
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/delay.h> | ||
22 | 22 | ||
23 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
24 | 24 | ||
@@ -42,8 +42,7 @@ static void __clk_enable(struct clk *clk) | |||
42 | if (clk->parent) | 42 | if (clk->parent) |
43 | __clk_enable(clk->parent); | 43 | __clk_enable(clk->parent); |
44 | if (clk->usecount++ == 0 && (clk->flags & CLK_PSC)) | 44 | if (clk->usecount++ == 0 && (clk->flags & CLK_PSC)) |
45 | davinci_psc_config(psc_domain(clk), clk->psc_ctlr, | 45 | davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 1); |
46 | clk->lpsc, 1); | ||
47 | } | 46 | } |
48 | 47 | ||
49 | static void __clk_disable(struct clk *clk) | 48 | static void __clk_disable(struct clk *clk) |
@@ -51,8 +50,7 @@ static void __clk_disable(struct clk *clk) | |||
51 | if (WARN_ON(clk->usecount == 0)) | 50 | if (WARN_ON(clk->usecount == 0)) |
52 | return; | 51 | return; |
53 | if (--clk->usecount == 0 && !(clk->flags & CLK_PLL)) | 52 | if (--clk->usecount == 0 && !(clk->flags & CLK_PLL)) |
54 | davinci_psc_config(psc_domain(clk), clk->psc_ctlr, | 53 | davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0); |
55 | clk->lpsc, 0); | ||
56 | if (clk->parent) | 54 | if (clk->parent) |
57 | __clk_disable(clk->parent); | 55 | __clk_disable(clk->parent); |
58 | } | 56 | } |
@@ -99,20 +97,74 @@ long clk_round_rate(struct clk *clk, unsigned long rate) | |||
99 | if (clk == NULL || IS_ERR(clk)) | 97 | if (clk == NULL || IS_ERR(clk)) |
100 | return -EINVAL; | 98 | return -EINVAL; |
101 | 99 | ||
100 | if (clk->round_rate) | ||
101 | return clk->round_rate(clk, rate); | ||
102 | |||
102 | return clk->rate; | 103 | return clk->rate; |
103 | } | 104 | } |
104 | EXPORT_SYMBOL(clk_round_rate); | 105 | EXPORT_SYMBOL(clk_round_rate); |
105 | 106 | ||
107 | /* Propagate rate to children */ | ||
108 | static void propagate_rate(struct clk *root) | ||
109 | { | ||
110 | struct clk *clk; | ||
111 | |||
112 | list_for_each_entry(clk, &root->children, childnode) { | ||
113 | if (clk->recalc) | ||
114 | clk->rate = clk->recalc(clk); | ||
115 | propagate_rate(clk); | ||
116 | } | ||
117 | } | ||
118 | |||
106 | int clk_set_rate(struct clk *clk, unsigned long rate) | 119 | int clk_set_rate(struct clk *clk, unsigned long rate) |
107 | { | 120 | { |
121 | unsigned long flags; | ||
122 | int ret = -EINVAL; | ||
123 | |||
108 | if (clk == NULL || IS_ERR(clk)) | 124 | if (clk == NULL || IS_ERR(clk)) |
109 | return -EINVAL; | 125 | return ret; |
110 | 126 | ||
111 | /* changing the clk rate is not supported */ | 127 | spin_lock_irqsave(&clockfw_lock, flags); |
112 | return -EINVAL; | 128 | if (clk->set_rate) |
129 | ret = clk->set_rate(clk, rate); | ||
130 | if (ret == 0) { | ||
131 | if (clk->recalc) | ||
132 | clk->rate = clk->recalc(clk); | ||
133 | propagate_rate(clk); | ||
134 | } | ||
135 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
136 | |||
137 | return ret; | ||
113 | } | 138 | } |
114 | EXPORT_SYMBOL(clk_set_rate); | 139 | EXPORT_SYMBOL(clk_set_rate); |
115 | 140 | ||
141 | int clk_set_parent(struct clk *clk, struct clk *parent) | ||
142 | { | ||
143 | unsigned long flags; | ||
144 | |||
145 | if (clk == NULL || IS_ERR(clk)) | ||
146 | return -EINVAL; | ||
147 | |||
148 | /* Cannot change parent on enabled clock */ | ||
149 | if (WARN_ON(clk->usecount)) | ||
150 | return -EINVAL; | ||
151 | |||
152 | mutex_lock(&clocks_mutex); | ||
153 | clk->parent = parent; | ||
154 | list_del_init(&clk->childnode); | ||
155 | list_add(&clk->childnode, &clk->parent->children); | ||
156 | mutex_unlock(&clocks_mutex); | ||
157 | |||
158 | spin_lock_irqsave(&clockfw_lock, flags); | ||
159 | if (clk->recalc) | ||
160 | clk->rate = clk->recalc(clk); | ||
161 | propagate_rate(clk); | ||
162 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | EXPORT_SYMBOL(clk_set_parent); | ||
167 | |||
116 | int clk_register(struct clk *clk) | 168 | int clk_register(struct clk *clk) |
117 | { | 169 | { |
118 | if (clk == NULL || IS_ERR(clk)) | 170 | if (clk == NULL || IS_ERR(clk)) |
@@ -123,16 +175,24 @@ int clk_register(struct clk *clk) | |||
123 | clk->name, clk->parent->name)) | 175 | clk->name, clk->parent->name)) |
124 | return -EINVAL; | 176 | return -EINVAL; |
125 | 177 | ||
178 | INIT_LIST_HEAD(&clk->children); | ||
179 | |||
126 | mutex_lock(&clocks_mutex); | 180 | mutex_lock(&clocks_mutex); |
127 | list_add_tail(&clk->node, &clocks); | 181 | list_add_tail(&clk->node, &clocks); |
182 | if (clk->parent) | ||
183 | list_add_tail(&clk->childnode, &clk->parent->children); | ||
128 | mutex_unlock(&clocks_mutex); | 184 | mutex_unlock(&clocks_mutex); |
129 | 185 | ||
130 | /* If rate is already set, use it */ | 186 | /* If rate is already set, use it */ |
131 | if (clk->rate) | 187 | if (clk->rate) |
132 | return 0; | 188 | return 0; |
133 | 189 | ||
190 | /* Else, see if there is a way to calculate it */ | ||
191 | if (clk->recalc) | ||
192 | clk->rate = clk->recalc(clk); | ||
193 | |||
134 | /* Otherwise, default to parent rate */ | 194 | /* Otherwise, default to parent rate */ |
135 | if (clk->parent) | 195 | else if (clk->parent) |
136 | clk->rate = clk->parent->rate; | 196 | clk->rate = clk->parent->rate; |
137 | 197 | ||
138 | return 0; | 198 | return 0; |
@@ -146,6 +206,7 @@ void clk_unregister(struct clk *clk) | |||
146 | 206 | ||
147 | mutex_lock(&clocks_mutex); | 207 | mutex_lock(&clocks_mutex); |
148 | list_del(&clk->node); | 208 | list_del(&clk->node); |
209 | list_del(&clk->childnode); | ||
149 | mutex_unlock(&clocks_mutex); | 210 | mutex_unlock(&clocks_mutex); |
150 | } | 211 | } |
151 | EXPORT_SYMBOL(clk_unregister); | 212 | EXPORT_SYMBOL(clk_unregister); |
@@ -166,11 +227,11 @@ static int __init clk_disable_unused(void) | |||
166 | continue; | 227 | continue; |
167 | 228 | ||
168 | /* ignore if in Disabled or SwRstDisable states */ | 229 | /* ignore if in Disabled or SwRstDisable states */ |
169 | if (!davinci_psc_is_clk_active(ck->psc_ctlr, ck->lpsc)) | 230 | if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc)) |
170 | continue; | 231 | continue; |
171 | 232 | ||
172 | pr_info("Clocks: disable unused %s\n", ck->name); | 233 | pr_info("Clocks: disable unused %s\n", ck->name); |
173 | davinci_psc_config(psc_domain(ck), ck->psc_ctlr, ck->lpsc, 0); | 234 | davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, 0); |
174 | } | 235 | } |
175 | spin_unlock_irq(&clockfw_lock); | 236 | spin_unlock_irq(&clockfw_lock); |
176 | 237 | ||
@@ -179,50 +240,62 @@ static int __init clk_disable_unused(void) | |||
179 | late_initcall(clk_disable_unused); | 240 | late_initcall(clk_disable_unused); |
180 | #endif | 241 | #endif |
181 | 242 | ||
182 | static void clk_sysclk_recalc(struct clk *clk) | 243 | static unsigned long clk_sysclk_recalc(struct clk *clk) |
183 | { | 244 | { |
184 | u32 v, plldiv; | 245 | u32 v, plldiv; |
185 | struct pll_data *pll; | 246 | struct pll_data *pll; |
247 | unsigned long rate = clk->rate; | ||
186 | 248 | ||
187 | /* If this is the PLL base clock, no more calculations needed */ | 249 | /* If this is the PLL base clock, no more calculations needed */ |
188 | if (clk->pll_data) | 250 | if (clk->pll_data) |
189 | return; | 251 | return rate; |
190 | 252 | ||
191 | if (WARN_ON(!clk->parent)) | 253 | if (WARN_ON(!clk->parent)) |
192 | return; | 254 | return rate; |
193 | 255 | ||
194 | clk->rate = clk->parent->rate; | 256 | rate = clk->parent->rate; |
195 | 257 | ||
196 | /* Otherwise, the parent must be a PLL */ | 258 | /* Otherwise, the parent must be a PLL */ |
197 | if (WARN_ON(!clk->parent->pll_data)) | 259 | if (WARN_ON(!clk->parent->pll_data)) |
198 | return; | 260 | return rate; |
199 | 261 | ||
200 | pll = clk->parent->pll_data; | 262 | pll = clk->parent->pll_data; |
201 | 263 | ||
202 | /* If pre-PLL, source clock is before the multiplier and divider(s) */ | 264 | /* If pre-PLL, source clock is before the multiplier and divider(s) */ |
203 | if (clk->flags & PRE_PLL) | 265 | if (clk->flags & PRE_PLL) |
204 | clk->rate = pll->input_rate; | 266 | rate = pll->input_rate; |
205 | 267 | ||
206 | if (!clk->div_reg) | 268 | if (!clk->div_reg) |
207 | return; | 269 | return rate; |
208 | 270 | ||
209 | v = __raw_readl(pll->base + clk->div_reg); | 271 | v = __raw_readl(pll->base + clk->div_reg); |
210 | if (v & PLLDIV_EN) { | 272 | if (v & PLLDIV_EN) { |
211 | plldiv = (v & PLLDIV_RATIO_MASK) + 1; | 273 | plldiv = (v & PLLDIV_RATIO_MASK) + 1; |
212 | if (plldiv) | 274 | if (plldiv) |
213 | clk->rate /= plldiv; | 275 | rate /= plldiv; |
214 | } | 276 | } |
277 | |||
278 | return rate; | ||
279 | } | ||
280 | |||
281 | static unsigned long clk_leafclk_recalc(struct clk *clk) | ||
282 | { | ||
283 | if (WARN_ON(!clk->parent)) | ||
284 | return clk->rate; | ||
285 | |||
286 | return clk->parent->rate; | ||
215 | } | 287 | } |
216 | 288 | ||
217 | static void __init clk_pll_init(struct clk *clk) | 289 | static unsigned long clk_pllclk_recalc(struct clk *clk) |
218 | { | 290 | { |
219 | u32 ctrl, mult = 1, prediv = 1, postdiv = 1; | 291 | u32 ctrl, mult = 1, prediv = 1, postdiv = 1; |
220 | u8 bypass; | 292 | u8 bypass; |
221 | struct pll_data *pll = clk->pll_data; | 293 | struct pll_data *pll = clk->pll_data; |
294 | unsigned long rate = clk->rate; | ||
222 | 295 | ||
223 | pll->base = IO_ADDRESS(pll->phys_base); | 296 | pll->base = IO_ADDRESS(pll->phys_base); |
224 | ctrl = __raw_readl(pll->base + PLLCTL); | 297 | ctrl = __raw_readl(pll->base + PLLCTL); |
225 | clk->rate = pll->input_rate = clk->parent->rate; | 298 | rate = pll->input_rate = clk->parent->rate; |
226 | 299 | ||
227 | if (ctrl & PLLCTL_PLLEN) { | 300 | if (ctrl & PLLCTL_PLLEN) { |
228 | bypass = 0; | 301 | bypass = 0; |
@@ -255,9 +328,9 @@ static void __init clk_pll_init(struct clk *clk) | |||
255 | } | 328 | } |
256 | 329 | ||
257 | if (!bypass) { | 330 | if (!bypass) { |
258 | clk->rate /= prediv; | 331 | rate /= prediv; |
259 | clk->rate *= mult; | 332 | rate *= mult; |
260 | clk->rate /= postdiv; | 333 | rate /= postdiv; |
261 | } | 334 | } |
262 | 335 | ||
263 | pr_debug("PLL%d: input = %lu MHz [ ", | 336 | pr_debug("PLL%d: input = %lu MHz [ ", |
@@ -270,8 +343,90 @@ static void __init clk_pll_init(struct clk *clk) | |||
270 | pr_debug("* %d ", mult); | 343 | pr_debug("* %d ", mult); |
271 | if (postdiv > 1) | 344 | if (postdiv > 1) |
272 | pr_debug("/ %d ", postdiv); | 345 | pr_debug("/ %d ", postdiv); |
273 | pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000); | 346 | pr_debug("] --> %lu MHz output.\n", rate / 1000000); |
347 | |||
348 | return rate; | ||
349 | } | ||
350 | |||
351 | /** | ||
352 | * davinci_set_pllrate - set the output rate of a given PLL. | ||
353 | * | ||
354 | * Note: Currently tested to work with OMAP-L138 only. | ||
355 | * | ||
356 | * @pll: pll whose rate needs to be changed. | ||
357 | * @prediv: The pre divider value. Passing 0 disables the pre-divider. | ||
358 | * @pllm: The multiplier value. Passing 0 leads to multiply-by-one. | ||
359 | * @postdiv: The post divider value. Passing 0 disables the post-divider. | ||
360 | */ | ||
361 | int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, | ||
362 | unsigned int mult, unsigned int postdiv) | ||
363 | { | ||
364 | u32 ctrl; | ||
365 | unsigned int locktime; | ||
366 | |||
367 | if (pll->base == NULL) | ||
368 | return -EINVAL; | ||
369 | |||
370 | /* | ||
371 | * PLL lock time required per OMAP-L138 datasheet is | ||
372 | * (2000 * prediv)/sqrt(pllm) OSCIN cycles. We approximate sqrt(pllm) | ||
373 | * as 4 and OSCIN cycle as 25 MHz. | ||
374 | */ | ||
375 | if (prediv) { | ||
376 | locktime = ((2000 * prediv) / 100); | ||
377 | prediv = (prediv - 1) | PLLDIV_EN; | ||
378 | } else { | ||
379 | locktime = 20; | ||
380 | } | ||
381 | if (postdiv) | ||
382 | postdiv = (postdiv - 1) | PLLDIV_EN; | ||
383 | if (mult) | ||
384 | mult = mult - 1; | ||
385 | |||
386 | ctrl = __raw_readl(pll->base + PLLCTL); | ||
387 | |||
388 | /* Switch the PLL to bypass mode */ | ||
389 | ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN); | ||
390 | __raw_writel(ctrl, pll->base + PLLCTL); | ||
391 | |||
392 | /* | ||
393 | * Wait for 4 OSCIN/CLKIN cycles to ensure that the PLLC has switched | ||
394 | * to bypass mode. Delay of 1us ensures we are good for all > 4MHz | ||
395 | * OSCIN/CLKIN inputs. Typically the input is ~25MHz. | ||
396 | */ | ||
397 | udelay(1); | ||
398 | |||
399 | /* Reset and enable PLL */ | ||
400 | ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS); | ||
401 | __raw_writel(ctrl, pll->base + PLLCTL); | ||
402 | |||
403 | if (pll->flags & PLL_HAS_PREDIV) | ||
404 | __raw_writel(prediv, pll->base + PREDIV); | ||
405 | |||
406 | __raw_writel(mult, pll->base + PLLM); | ||
407 | |||
408 | if (pll->flags & PLL_HAS_POSTDIV) | ||
409 | __raw_writel(postdiv, pll->base + POSTDIV); | ||
410 | |||
411 | /* | ||
412 | * Wait for PLL to reset properly, OMAP-L138 datasheet says | ||
413 | * 'min' time = 125ns | ||
414 | */ | ||
415 | udelay(1); | ||
416 | |||
417 | /* Bring PLL out of reset */ | ||
418 | ctrl |= PLLCTL_PLLRST; | ||
419 | __raw_writel(ctrl, pll->base + PLLCTL); | ||
420 | |||
421 | udelay(locktime); | ||
422 | |||
423 | /* Remove PLL from bypass mode */ | ||
424 | ctrl |= PLLCTL_PLLEN; | ||
425 | __raw_writel(ctrl, pll->base + PLLCTL); | ||
426 | |||
427 | return 0; | ||
274 | } | 428 | } |
429 | EXPORT_SYMBOL(davinci_set_pllrate); | ||
275 | 430 | ||
276 | int __init davinci_clk_init(struct davinci_clk *clocks) | 431 | int __init davinci_clk_init(struct davinci_clk *clocks) |
277 | { | 432 | { |
@@ -281,12 +436,23 @@ int __init davinci_clk_init(struct davinci_clk *clocks) | |||
281 | for (c = clocks; c->lk.clk; c++) { | 436 | for (c = clocks; c->lk.clk; c++) { |
282 | clk = c->lk.clk; | 437 | clk = c->lk.clk; |
283 | 438 | ||
284 | if (clk->pll_data) | 439 | if (!clk->recalc) { |
285 | clk_pll_init(clk); | 440 | |
441 | /* Check if clock is a PLL */ | ||
442 | if (clk->pll_data) | ||
443 | clk->recalc = clk_pllclk_recalc; | ||
444 | |||
445 | /* Else, if it is a PLL-derived clock */ | ||
446 | else if (clk->flags & CLK_PLL) | ||
447 | clk->recalc = clk_sysclk_recalc; | ||
448 | |||
449 | /* Otherwise, it is a leaf clock (PSC clock) */ | ||
450 | else if (clk->parent) | ||
451 | clk->recalc = clk_leafclk_recalc; | ||
452 | } | ||
286 | 453 | ||
287 | /* Calculate rates for PLL-derived clocks */ | 454 | if (clk->recalc) |
288 | else if (clk->flags & CLK_PLL) | 455 | clk->rate = clk->recalc(clk); |
289 | clk_sysclk_recalc(clk); | ||
290 | 456 | ||
291 | if (clk->lpsc) | 457 | if (clk->lpsc) |
292 | clk->flags |= CLK_PSC; | 458 | clk->flags |= CLK_PSC; |
@@ -352,9 +518,8 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent) | |||
352 | /* REVISIT show device associations too */ | 518 | /* REVISIT show device associations too */ |
353 | 519 | ||
354 | /* cost is now small, but not linear... */ | 520 | /* cost is now small, but not linear... */ |
355 | list_for_each_entry(clk, &clocks, node) { | 521 | list_for_each_entry(clk, &parent->children, childnode) { |
356 | if (clk->parent == parent) | 522 | dump_clock(s, nest + NEST_DELTA, clk); |
357 | dump_clock(s, nest + NEST_DELTA, clk); | ||
358 | } | 523 | } |
359 | } | 524 | } |
360 | 525 | ||