diff options
Diffstat (limited to 'arch/arm/mach-davinci/clock.c')
-rw-r--r-- | arch/arm/mach-davinci/clock.c | 93 |
1 files changed, 39 insertions, 54 deletions
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index baece65cb9c0..bf6218ee94e1 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c | |||
@@ -49,7 +49,8 @@ static void __clk_disable(struct clk *clk) | |||
49 | { | 49 | { |
50 | if (WARN_ON(clk->usecount == 0)) | 50 | if (WARN_ON(clk->usecount == 0)) |
51 | return; | 51 | return; |
52 | if (--clk->usecount == 0 && !(clk->flags & CLK_PLL)) | 52 | if (--clk->usecount == 0 && !(clk->flags & CLK_PLL) && |
53 | (clk->flags & CLK_PSC)) | ||
53 | davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0); | 54 | davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0); |
54 | if (clk->parent) | 55 | if (clk->parent) |
55 | __clk_disable(clk->parent); | 56 | __clk_disable(clk->parent); |
@@ -124,9 +125,10 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
124 | if (clk == NULL || IS_ERR(clk)) | 125 | if (clk == NULL || IS_ERR(clk)) |
125 | return ret; | 126 | return ret; |
126 | 127 | ||
127 | spin_lock_irqsave(&clockfw_lock, flags); | ||
128 | if (clk->set_rate) | 128 | if (clk->set_rate) |
129 | ret = clk->set_rate(clk, rate); | 129 | ret = clk->set_rate(clk, rate); |
130 | |||
131 | spin_lock_irqsave(&clockfw_lock, flags); | ||
130 | if (ret == 0) { | 132 | if (ret == 0) { |
131 | if (clk->recalc) | 133 | if (clk->recalc) |
132 | clk->rate = clk->recalc(clk); | 134 | clk->rate = clk->recalc(clk); |
@@ -363,6 +365,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, | |||
363 | { | 365 | { |
364 | u32 ctrl; | 366 | u32 ctrl; |
365 | unsigned int locktime; | 367 | unsigned int locktime; |
368 | unsigned long flags; | ||
366 | 369 | ||
367 | if (pll->base == NULL) | 370 | if (pll->base == NULL) |
368 | return -EINVAL; | 371 | return -EINVAL; |
@@ -376,25 +379,23 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, | |||
376 | locktime = ((2000 * prediv) / 100); | 379 | locktime = ((2000 * prediv) / 100); |
377 | prediv = (prediv - 1) | PLLDIV_EN; | 380 | prediv = (prediv - 1) | PLLDIV_EN; |
378 | } else { | 381 | } else { |
379 | locktime = 20; | 382 | locktime = PLL_LOCK_TIME; |
380 | } | 383 | } |
381 | if (postdiv) | 384 | if (postdiv) |
382 | postdiv = (postdiv - 1) | PLLDIV_EN; | 385 | postdiv = (postdiv - 1) | PLLDIV_EN; |
383 | if (mult) | 386 | if (mult) |
384 | mult = mult - 1; | 387 | mult = mult - 1; |
385 | 388 | ||
389 | /* Protect against simultaneous calls to PLL setting seqeunce */ | ||
390 | spin_lock_irqsave(&clockfw_lock, flags); | ||
391 | |||
386 | ctrl = __raw_readl(pll->base + PLLCTL); | 392 | ctrl = __raw_readl(pll->base + PLLCTL); |
387 | 393 | ||
388 | /* Switch the PLL to bypass mode */ | 394 | /* Switch the PLL to bypass mode */ |
389 | ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN); | 395 | ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN); |
390 | __raw_writel(ctrl, pll->base + PLLCTL); | 396 | __raw_writel(ctrl, pll->base + PLLCTL); |
391 | 397 | ||
392 | /* | 398 | udelay(PLL_BYPASS_TIME); |
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 | ||
399 | /* Reset and enable PLL */ | 400 | /* Reset and enable PLL */ |
400 | ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS); | 401 | ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS); |
@@ -408,11 +409,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, | |||
408 | if (pll->flags & PLL_HAS_POSTDIV) | 409 | if (pll->flags & PLL_HAS_POSTDIV) |
409 | __raw_writel(postdiv, pll->base + POSTDIV); | 410 | __raw_writel(postdiv, pll->base + POSTDIV); |
410 | 411 | ||
411 | /* | 412 | udelay(PLL_RESET_TIME); |
412 | * Wait for PLL to reset properly, OMAP-L138 datasheet says | ||
413 | * 'min' time = 125ns | ||
414 | */ | ||
415 | udelay(1); | ||
416 | 413 | ||
417 | /* Bring PLL out of reset */ | 414 | /* Bring PLL out of reset */ |
418 | ctrl |= PLLCTL_PLLRST; | 415 | ctrl |= PLLCTL_PLLRST; |
@@ -424,17 +421,20 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, | |||
424 | ctrl |= PLLCTL_PLLEN; | 421 | ctrl |= PLLCTL_PLLEN; |
425 | __raw_writel(ctrl, pll->base + PLLCTL); | 422 | __raw_writel(ctrl, pll->base + PLLCTL); |
426 | 423 | ||
424 | spin_unlock_irqrestore(&clockfw_lock, flags); | ||
425 | |||
427 | return 0; | 426 | return 0; |
428 | } | 427 | } |
429 | EXPORT_SYMBOL(davinci_set_pllrate); | 428 | EXPORT_SYMBOL(davinci_set_pllrate); |
430 | 429 | ||
431 | int __init davinci_clk_init(struct davinci_clk *clocks) | 430 | int __init davinci_clk_init(struct clk_lookup *clocks) |
432 | { | 431 | { |
433 | struct davinci_clk *c; | 432 | struct clk_lookup *c; |
434 | struct clk *clk; | 433 | struct clk *clk; |
434 | size_t num_clocks = 0; | ||
435 | 435 | ||
436 | for (c = clocks; c->lk.clk; c++) { | 436 | for (c = clocks; c->clk; c++) { |
437 | clk = c->lk.clk; | 437 | clk = c->clk; |
438 | 438 | ||
439 | if (!clk->recalc) { | 439 | if (!clk->recalc) { |
440 | 440 | ||
@@ -457,35 +457,23 @@ int __init davinci_clk_init(struct davinci_clk *clocks) | |||
457 | if (clk->lpsc) | 457 | if (clk->lpsc) |
458 | clk->flags |= CLK_PSC; | 458 | clk->flags |= CLK_PSC; |
459 | 459 | ||
460 | clkdev_add(&c->lk); | ||
461 | clk_register(clk); | 460 | clk_register(clk); |
461 | num_clocks++; | ||
462 | 462 | ||
463 | /* Turn on clocks that Linux doesn't otherwise manage */ | 463 | /* Turn on clocks that Linux doesn't otherwise manage */ |
464 | if (clk->flags & ALWAYS_ENABLED) | 464 | if (clk->flags & ALWAYS_ENABLED) |
465 | clk_enable(clk); | 465 | clk_enable(clk); |
466 | } | 466 | } |
467 | 467 | ||
468 | return 0; | 468 | clkdev_add_table(clocks, num_clocks); |
469 | } | ||
470 | |||
471 | #ifdef CONFIG_PROC_FS | ||
472 | #include <linux/proc_fs.h> | ||
473 | #include <linux/seq_file.h> | ||
474 | 469 | ||
475 | static void *davinci_ck_start(struct seq_file *m, loff_t *pos) | 470 | return 0; |
476 | { | ||
477 | return *pos < 1 ? (void *)1 : NULL; | ||
478 | } | 471 | } |
479 | 472 | ||
480 | static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos) | 473 | #ifdef CONFIG_DEBUG_FS |
481 | { | ||
482 | ++*pos; | ||
483 | return NULL; | ||
484 | } | ||
485 | 474 | ||
486 | static void davinci_ck_stop(struct seq_file *m, void *v) | 475 | #include <linux/debugfs.h> |
487 | { | 476 | #include <linux/seq_file.h> |
488 | } | ||
489 | 477 | ||
490 | #define CLKNAME_MAX 10 /* longest clock name */ | 478 | #define CLKNAME_MAX 10 /* longest clock name */ |
491 | #define NEST_DELTA 2 | 479 | #define NEST_DELTA 2 |
@@ -525,41 +513,38 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent) | |||
525 | 513 | ||
526 | static int davinci_ck_show(struct seq_file *m, void *v) | 514 | static int davinci_ck_show(struct seq_file *m, void *v) |
527 | { | 515 | { |
528 | /* Show clock tree; we know the main oscillator is first. | 516 | struct clk *clk; |
529 | * We trust nonzero usecounts equate to PSC enables... | 517 | |
518 | /* | ||
519 | * Show clock tree; We trust nonzero usecounts equate to PSC enables... | ||
530 | */ | 520 | */ |
531 | mutex_lock(&clocks_mutex); | 521 | mutex_lock(&clocks_mutex); |
532 | if (!list_empty(&clocks)) | 522 | list_for_each_entry(clk, &clocks, node) |
533 | dump_clock(m, 0, list_first_entry(&clocks, struct clk, node)); | 523 | if (!clk->parent) |
524 | dump_clock(m, 0, clk); | ||
534 | mutex_unlock(&clocks_mutex); | 525 | mutex_unlock(&clocks_mutex); |
535 | 526 | ||
536 | return 0; | 527 | return 0; |
537 | } | 528 | } |
538 | 529 | ||
539 | static const struct seq_operations davinci_ck_op = { | ||
540 | .start = davinci_ck_start, | ||
541 | .next = davinci_ck_next, | ||
542 | .stop = davinci_ck_stop, | ||
543 | .show = davinci_ck_show | ||
544 | }; | ||
545 | |||
546 | static int davinci_ck_open(struct inode *inode, struct file *file) | 530 | static int davinci_ck_open(struct inode *inode, struct file *file) |
547 | { | 531 | { |
548 | return seq_open(file, &davinci_ck_op); | 532 | return single_open(file, davinci_ck_show, NULL); |
549 | } | 533 | } |
550 | 534 | ||
551 | static const struct file_operations proc_davinci_ck_operations = { | 535 | static const struct file_operations davinci_ck_operations = { |
552 | .open = davinci_ck_open, | 536 | .open = davinci_ck_open, |
553 | .read = seq_read, | 537 | .read = seq_read, |
554 | .llseek = seq_lseek, | 538 | .llseek = seq_lseek, |
555 | .release = seq_release, | 539 | .release = single_release, |
556 | }; | 540 | }; |
557 | 541 | ||
558 | static int __init davinci_ck_proc_init(void) | 542 | static int __init davinci_clk_debugfs_init(void) |
559 | { | 543 | { |
560 | 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); | ||
561 | return 0; | 546 | return 0; |
562 | 547 | ||
563 | } | 548 | } |
564 | __initcall(davinci_ck_proc_init); | 549 | device_initcall(davinci_clk_debugfs_init); |
565 | #endif /* CONFIG_DEBUG_PROC_FS */ | 550 | #endif /* CONFIG_DEBUG_FS */ |