aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-davinci/clock.c')
-rw-r--r--arch/arm/mach-davinci/clock.c231
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
49static void __clk_disable(struct clk *clk) 48static 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}
104EXPORT_SYMBOL(clk_round_rate); 105EXPORT_SYMBOL(clk_round_rate);
105 106
107/* Propagate rate to children */
108static 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
106int clk_set_rate(struct clk *clk, unsigned long rate) 119int 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}
114EXPORT_SYMBOL(clk_set_rate); 139EXPORT_SYMBOL(clk_set_rate);
115 140
141int 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}
166EXPORT_SYMBOL(clk_set_parent);
167
116int clk_register(struct clk *clk) 168int 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}
151EXPORT_SYMBOL(clk_unregister); 212EXPORT_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)
179late_initcall(clk_disable_unused); 240late_initcall(clk_disable_unused);
180#endif 241#endif
181 242
182static void clk_sysclk_recalc(struct clk *clk) 243static 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
281static 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
217static void __init clk_pll_init(struct clk *clk) 289static 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 */
361int 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}
429EXPORT_SYMBOL(davinci_set_pllrate);
275 430
276int __init davinci_clk_init(struct davinci_clk *clocks) 431int __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