aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/clock.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /arch/arm/mach-davinci/clock.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'arch/arm/mach-davinci/clock.c')
-rw-r--r--arch/arm/mach-davinci/clock.c298
1 files changed, 224 insertions, 74 deletions
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 83d54d50b5ea..bf6218ee94e1 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,17 +42,16 @@ 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)
50{ 49{
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 (clk->flags & CLK_PSC))
55 clk->lpsc, 0); 54 davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0);
56 if (clk->parent) 55 if (clk->parent)
57 __clk_disable(clk->parent); 56 __clk_disable(clk->parent);
58} 57}
@@ -99,20 +98,75 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
99 if (clk == NULL || IS_ERR(clk)) 98 if (clk == NULL || IS_ERR(clk))
100 return -EINVAL; 99 return -EINVAL;
101 100
101 if (clk->round_rate)
102 return clk->round_rate(clk, rate);
103
102 return clk->rate; 104 return clk->rate;
103} 105}
104EXPORT_SYMBOL(clk_round_rate); 106EXPORT_SYMBOL(clk_round_rate);
105 107
108/* Propagate rate to children */
109static void propagate_rate(struct clk *root)
110{
111 struct clk *clk;
112
113 list_for_each_entry(clk, &root->children, childnode) {
114 if (clk->recalc)
115 clk->rate = clk->recalc(clk);
116 propagate_rate(clk);
117 }
118}
119
106int clk_set_rate(struct clk *clk, unsigned long rate) 120int clk_set_rate(struct clk *clk, unsigned long rate)
107{ 121{
122 unsigned long flags;
123 int ret = -EINVAL;
124
108 if (clk == NULL || IS_ERR(clk)) 125 if (clk == NULL || IS_ERR(clk))
109 return -EINVAL; 126 return ret;
127
128 if (clk->set_rate)
129 ret = clk->set_rate(clk, rate);
130
131 spin_lock_irqsave(&clockfw_lock, flags);
132 if (ret == 0) {
133 if (clk->recalc)
134 clk->rate = clk->recalc(clk);
135 propagate_rate(clk);
136 }
137 spin_unlock_irqrestore(&clockfw_lock, flags);
110 138
111 /* changing the clk rate is not supported */ 139 return ret;
112 return -EINVAL;
113} 140}
114EXPORT_SYMBOL(clk_set_rate); 141EXPORT_SYMBOL(clk_set_rate);
115 142
143int clk_set_parent(struct clk *clk, struct clk *parent)
144{
145 unsigned long flags;
146
147 if (clk == NULL || IS_ERR(clk))
148 return -EINVAL;
149
150 /* Cannot change parent on enabled clock */
151 if (WARN_ON(clk->usecount))
152 return -EINVAL;
153
154 mutex_lock(&clocks_mutex);
155 clk->parent = parent;
156 list_del_init(&clk->childnode);
157 list_add(&clk->childnode, &clk->parent->children);
158 mutex_unlock(&clocks_mutex);
159
160 spin_lock_irqsave(&clockfw_lock, flags);
161 if (clk->recalc)
162 clk->rate = clk->recalc(clk);
163 propagate_rate(clk);
164 spin_unlock_irqrestore(&clockfw_lock, flags);
165
166 return 0;
167}
168EXPORT_SYMBOL(clk_set_parent);
169
116int clk_register(struct clk *clk) 170int clk_register(struct clk *clk)
117{ 171{
118 if (clk == NULL || IS_ERR(clk)) 172 if (clk == NULL || IS_ERR(clk))
@@ -123,16 +177,24 @@ int clk_register(struct clk *clk)
123 clk->name, clk->parent->name)) 177 clk->name, clk->parent->name))
124 return -EINVAL; 178 return -EINVAL;
125 179
180 INIT_LIST_HEAD(&clk->children);
181
126 mutex_lock(&clocks_mutex); 182 mutex_lock(&clocks_mutex);
127 list_add_tail(&clk->node, &clocks); 183 list_add_tail(&clk->node, &clocks);
184 if (clk->parent)
185 list_add_tail(&clk->childnode, &clk->parent->children);
128 mutex_unlock(&clocks_mutex); 186 mutex_unlock(&clocks_mutex);
129 187
130 /* If rate is already set, use it */ 188 /* If rate is already set, use it */
131 if (clk->rate) 189 if (clk->rate)
132 return 0; 190 return 0;
133 191
192 /* Else, see if there is a way to calculate it */
193 if (clk->recalc)
194 clk->rate = clk->recalc(clk);
195
134 /* Otherwise, default to parent rate */ 196 /* Otherwise, default to parent rate */
135 if (clk->parent) 197 else if (clk->parent)
136 clk->rate = clk->parent->rate; 198 clk->rate = clk->parent->rate;
137 199
138 return 0; 200 return 0;
@@ -146,6 +208,7 @@ void clk_unregister(struct clk *clk)
146 208
147 mutex_lock(&clocks_mutex); 209 mutex_lock(&clocks_mutex);
148 list_del(&clk->node); 210 list_del(&clk->node);
211 list_del(&clk->childnode);
149 mutex_unlock(&clocks_mutex); 212 mutex_unlock(&clocks_mutex);
150} 213}
151EXPORT_SYMBOL(clk_unregister); 214EXPORT_SYMBOL(clk_unregister);
@@ -166,11 +229,11 @@ static int __init clk_disable_unused(void)
166 continue; 229 continue;
167 230
168 /* ignore if in Disabled or SwRstDisable states */ 231 /* ignore if in Disabled or SwRstDisable states */
169 if (!davinci_psc_is_clk_active(ck->psc_ctlr, ck->lpsc)) 232 if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc))
170 continue; 233 continue;
171 234
172 pr_info("Clocks: disable unused %s\n", ck->name); 235 pr_info("Clocks: disable unused %s\n", ck->name);
173 davinci_psc_config(psc_domain(ck), ck->psc_ctlr, ck->lpsc, 0); 236 davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, 0);
174 } 237 }
175 spin_unlock_irq(&clockfw_lock); 238 spin_unlock_irq(&clockfw_lock);
176 239
@@ -179,50 +242,62 @@ static int __init clk_disable_unused(void)
179late_initcall(clk_disable_unused); 242late_initcall(clk_disable_unused);
180#endif 243#endif
181 244
182static void clk_sysclk_recalc(struct clk *clk) 245static unsigned long clk_sysclk_recalc(struct clk *clk)
183{ 246{
184 u32 v, plldiv; 247 u32 v, plldiv;
185 struct pll_data *pll; 248 struct pll_data *pll;
249 unsigned long rate = clk->rate;
186 250
187 /* If this is the PLL base clock, no more calculations needed */ 251 /* If this is the PLL base clock, no more calculations needed */
188 if (clk->pll_data) 252 if (clk->pll_data)
189 return; 253 return rate;
190 254
191 if (WARN_ON(!clk->parent)) 255 if (WARN_ON(!clk->parent))
192 return; 256 return rate;
193 257
194 clk->rate = clk->parent->rate; 258 rate = clk->parent->rate;
195 259
196 /* Otherwise, the parent must be a PLL */ 260 /* Otherwise, the parent must be a PLL */
197 if (WARN_ON(!clk->parent->pll_data)) 261 if (WARN_ON(!clk->parent->pll_data))
198 return; 262 return rate;
199 263
200 pll = clk->parent->pll_data; 264 pll = clk->parent->pll_data;
201 265
202 /* If pre-PLL, source clock is before the multiplier and divider(s) */ 266 /* If pre-PLL, source clock is before the multiplier and divider(s) */
203 if (clk->flags & PRE_PLL) 267 if (clk->flags & PRE_PLL)
204 clk->rate = pll->input_rate; 268 rate = pll->input_rate;
205 269
206 if (!clk->div_reg) 270 if (!clk->div_reg)
207 return; 271 return rate;
208 272
209 v = __raw_readl(pll->base + clk->div_reg); 273 v = __raw_readl(pll->base + clk->div_reg);
210 if (v & PLLDIV_EN) { 274 if (v & PLLDIV_EN) {
211 plldiv = (v & PLLDIV_RATIO_MASK) + 1; 275 plldiv = (v & PLLDIV_RATIO_MASK) + 1;
212 if (plldiv) 276 if (plldiv)
213 clk->rate /= plldiv; 277 rate /= plldiv;
214 } 278 }
279
280 return rate;
281}
282
283static unsigned long clk_leafclk_recalc(struct clk *clk)
284{
285 if (WARN_ON(!clk->parent))
286 return clk->rate;
287
288 return clk->parent->rate;
215} 289}
216 290
217static void __init clk_pll_init(struct clk *clk) 291static unsigned long clk_pllclk_recalc(struct clk *clk)
218{ 292{
219 u32 ctrl, mult = 1, prediv = 1, postdiv = 1; 293 u32 ctrl, mult = 1, prediv = 1, postdiv = 1;
220 u8 bypass; 294 u8 bypass;
221 struct pll_data *pll = clk->pll_data; 295 struct pll_data *pll = clk->pll_data;
296 unsigned long rate = clk->rate;
222 297
223 pll->base = IO_ADDRESS(pll->phys_base); 298 pll->base = IO_ADDRESS(pll->phys_base);
224 ctrl = __raw_readl(pll->base + PLLCTL); 299 ctrl = __raw_readl(pll->base + PLLCTL);
225 clk->rate = pll->input_rate = clk->parent->rate; 300 rate = pll->input_rate = clk->parent->rate;
226 301
227 if (ctrl & PLLCTL_PLLEN) { 302 if (ctrl & PLLCTL_PLLEN) {
228 bypass = 0; 303 bypass = 0;
@@ -255,9 +330,9 @@ static void __init clk_pll_init(struct clk *clk)
255 } 330 }
256 331
257 if (!bypass) { 332 if (!bypass) {
258 clk->rate /= prediv; 333 rate /= prediv;
259 clk->rate *= mult; 334 rate *= mult;
260 clk->rate /= postdiv; 335 rate /= postdiv;
261 } 336 }
262 337
263 pr_debug("PLL%d: input = %lu MHz [ ", 338 pr_debug("PLL%d: input = %lu MHz [ ",
@@ -270,56 +345,135 @@ static void __init clk_pll_init(struct clk *clk)
270 pr_debug("* %d ", mult); 345 pr_debug("* %d ", mult);
271 if (postdiv > 1) 346 if (postdiv > 1)
272 pr_debug("/ %d ", postdiv); 347 pr_debug("/ %d ", postdiv);
273 pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000); 348 pr_debug("] --> %lu MHz output.\n", rate / 1000000);
349
350 return rate;
274} 351}
275 352
276int __init davinci_clk_init(struct davinci_clk *clocks) 353/**
354 * davinci_set_pllrate - set the output rate of a given PLL.
355 *
356 * Note: Currently tested to work with OMAP-L138 only.
357 *
358 * @pll: pll whose rate needs to be changed.
359 * @prediv: The pre divider value. Passing 0 disables the pre-divider.
360 * @pllm: The multiplier value. Passing 0 leads to multiply-by-one.
361 * @postdiv: The post divider value. Passing 0 disables the post-divider.
362 */
363int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
364 unsigned int mult, unsigned int postdiv)
365{
366 u32 ctrl;
367 unsigned int locktime;
368 unsigned long flags;
369
370 if (pll->base == NULL)
371 return -EINVAL;
372
373 /*
374 * PLL lock time required per OMAP-L138 datasheet is
375 * (2000 * prediv)/sqrt(pllm) OSCIN cycles. We approximate sqrt(pllm)
376 * as 4 and OSCIN cycle as 25 MHz.
377 */
378 if (prediv) {
379 locktime = ((2000 * prediv) / 100);
380 prediv = (prediv - 1) | PLLDIV_EN;
381 } else {
382 locktime = PLL_LOCK_TIME;
383 }
384 if (postdiv)
385 postdiv = (postdiv - 1) | PLLDIV_EN;
386 if (mult)
387 mult = mult - 1;
388
389 /* Protect against simultaneous calls to PLL setting seqeunce */
390 spin_lock_irqsave(&clockfw_lock, flags);
391
392 ctrl = __raw_readl(pll->base + PLLCTL);
393
394 /* Switch the PLL to bypass mode */
395 ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
396 __raw_writel(ctrl, pll->base + PLLCTL);
397
398 udelay(PLL_BYPASS_TIME);
399
400 /* Reset and enable PLL */
401 ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS);
402 __raw_writel(ctrl, pll->base + PLLCTL);
403
404 if (pll->flags & PLL_HAS_PREDIV)
405 __raw_writel(prediv, pll->base + PREDIV);
406
407 __raw_writel(mult, pll->base + PLLM);
408
409 if (pll->flags & PLL_HAS_POSTDIV)
410 __raw_writel(postdiv, pll->base + POSTDIV);
411
412 udelay(PLL_RESET_TIME);
413
414 /* Bring PLL out of reset */
415 ctrl |= PLLCTL_PLLRST;
416 __raw_writel(ctrl, pll->base + PLLCTL);
417
418 udelay(locktime);
419
420 /* Remove PLL from bypass mode */
421 ctrl |= PLLCTL_PLLEN;
422 __raw_writel(ctrl, pll->base + PLLCTL);
423
424 spin_unlock_irqrestore(&clockfw_lock, flags);
425
426 return 0;
427}
428EXPORT_SYMBOL(davinci_set_pllrate);
429
430int __init davinci_clk_init(struct clk_lookup *clocks)
277 { 431 {
278 struct davinci_clk *c; 432 struct clk_lookup *c;
279 struct clk *clk; 433 struct clk *clk;
434 size_t num_clocks = 0;
435
436 for (c = clocks; c->clk; c++) {
437 clk = c->clk;
280 438
281 for (c = clocks; c->lk.clk; c++) { 439 if (!clk->recalc) {
282 clk = c->lk.clk;
283 440
284 if (clk->pll_data) 441 /* Check if clock is a PLL */
285 clk_pll_init(clk); 442 if (clk->pll_data)
443 clk->recalc = clk_pllclk_recalc;
286 444
287 /* Calculate rates for PLL-derived clocks */ 445 /* Else, if it is a PLL-derived clock */
288 else if (clk->flags & CLK_PLL) 446 else if (clk->flags & CLK_PLL)
289 clk_sysclk_recalc(clk); 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 }
453
454 if (clk->recalc)
455 clk->rate = clk->recalc(clk);
290 456
291 if (clk->lpsc) 457 if (clk->lpsc)
292 clk->flags |= CLK_PSC; 458 clk->flags |= CLK_PSC;
293 459
294 clkdev_add(&c->lk);
295 clk_register(clk); 460 clk_register(clk);
461 num_clocks++;
296 462
297 /* Turn on clocks that Linux doesn't otherwise manage */ 463 /* Turn on clocks that Linux doesn't otherwise manage */
298 if (clk->flags & ALWAYS_ENABLED) 464 if (clk->flags & ALWAYS_ENABLED)
299 clk_enable(clk); 465 clk_enable(clk);
300 } 466 }
301 467
302 return 0; 468 clkdev_add_table(clocks, num_clocks);
303}
304
305#ifdef CONFIG_PROC_FS
306#include <linux/proc_fs.h>
307#include <linux/seq_file.h>
308 469
309static void *davinci_ck_start(struct seq_file *m, loff_t *pos) 470 return 0;
310{
311 return *pos < 1 ? (void *)1 : NULL;
312} 471}
313 472
314static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos) 473#ifdef CONFIG_DEBUG_FS
315{
316 ++*pos;
317 return NULL;
318}
319 474
320static void davinci_ck_stop(struct seq_file *m, void *v) 475#include <linux/debugfs.h>
321{ 476#include <linux/seq_file.h>
322}
323 477
324#define CLKNAME_MAX 10 /* longest clock name */ 478#define CLKNAME_MAX 10 /* longest clock name */
325#define NEST_DELTA 2 479#define NEST_DELTA 2
@@ -352,49 +506,45 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
352 /* REVISIT show device associations too */ 506 /* REVISIT show device associations too */
353 507
354 /* cost is now small, but not linear... */ 508 /* cost is now small, but not linear... */
355 list_for_each_entry(clk, &clocks, node) { 509 list_for_each_entry(clk, &parent->children, childnode) {
356 if (clk->parent == parent) 510 dump_clock(s, nest + NEST_DELTA, clk);
357 dump_clock(s, nest + NEST_DELTA, clk);
358 } 511 }
359} 512}
360 513
361static int davinci_ck_show(struct seq_file *m, void *v) 514static int davinci_ck_show(struct seq_file *m, void *v)
362{ 515{
363 /* Show clock tree; we know the main oscillator is first. 516 struct clk *clk;
364 * We trust nonzero usecounts equate to PSC enables... 517
518 /*
519 * Show clock tree; We trust nonzero usecounts equate to PSC enables...
365 */ 520 */
366 mutex_lock(&clocks_mutex); 521 mutex_lock(&clocks_mutex);
367 if (!list_empty(&clocks)) 522 list_for_each_entry(clk, &clocks, node)
368 dump_clock(m, 0, list_first_entry(&clocks, struct clk, node)); 523 if (!clk->parent)
524 dump_clock(m, 0, clk);
369 mutex_unlock(&clocks_mutex); 525 mutex_unlock(&clocks_mutex);
370 526
371 return 0; 527 return 0;
372} 528}
373 529
374static const struct seq_operations davinci_ck_op = {
375 .start = davinci_ck_start,
376 .next = davinci_ck_next,
377 .stop = davinci_ck_stop,
378 .show = davinci_ck_show
379};
380
381static int davinci_ck_open(struct inode *inode, struct file *file) 530static int davinci_ck_open(struct inode *inode, struct file *file)
382{ 531{
383 return seq_open(file, &davinci_ck_op); 532 return single_open(file, davinci_ck_show, NULL);
384} 533}
385 534
386static const struct file_operations proc_davinci_ck_operations = { 535static const struct file_operations davinci_ck_operations = {
387 .open = davinci_ck_open, 536 .open = davinci_ck_open,
388 .read = seq_read, 537 .read = seq_read,
389 .llseek = seq_lseek, 538 .llseek = seq_lseek,
390 .release = seq_release, 539 .release = single_release,
391}; 540};
392 541
393static int __init davinci_ck_proc_init(void) 542static int __init davinci_clk_debugfs_init(void)
394{ 543{
395 proc_create("davinci_clocks", 0, NULL, &proc_davinci_ck_operations); 544 debugfs_create_file("davinci_clocks", S_IFREG | S_IRUGO, NULL, NULL,
545 &davinci_ck_operations);
396 return 0; 546 return 0;
397 547
398} 548}
399__initcall(davinci_ck_proc_init); 549device_initcall(davinci_clk_debugfs_init);
400#endif /* CONFIG_DEBUG_PROC_FS */ 550#endif /* CONFIG_DEBUG_FS */