diff options
author | Andrew Victor <andrew@sanpeople.com> | 2007-02-08 11:36:34 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-02-08 15:47:33 -0500 |
commit | c9b75d132261096ac1170354b9e27837af76a512 (patch) | |
tree | fc139d2f1becd9f289f41b7de04c0c7366f4cfbe /arch/arm/mach-at91/clock.c | |
parent | 93a3ddc201c501146c896d598deb61f3abbe4ab0 (diff) |
[ARM] 4154/1: AT91: Clock update
Unconditionally disabling the PCKs (Programmable Clocks) is not a good
idea as it breaks boards that depend on those clocks being enabled by
bootloaders.
Therefore only disable unused clocks late in the init process, giving
the board init code the chance to claim the clock.
Patch from Steven Scholz.
Since the HCK clocks on SAM9261 are already being registered as a
independent clocks, we don't need the special case for HCK0 on the
SAM9261. Platform-init code and drivers should use the clock API to
enable/disable the clock.
Patch from Nicolas Ferre.
Signed-off-by: Andrew Victor <andrew@sanpeople.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-at91/clock.c')
-rw-r--r-- | arch/arm/mach-at91/clock.c | 62 |
1 files changed, 29 insertions, 33 deletions
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 27e7279b5b39..f6cb74806043 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c | |||
@@ -525,27 +525,6 @@ fail: | |||
525 | return 0; | 525 | return 0; |
526 | } | 526 | } |
527 | 527 | ||
528 | /* | ||
529 | * Several unused clocks may be active. Turn them off. | ||
530 | */ | ||
531 | static void __init at91_periphclk_reset(void) | ||
532 | { | ||
533 | unsigned long reg; | ||
534 | struct clk *clk; | ||
535 | |||
536 | reg = at91_sys_read(AT91_PMC_PCSR); | ||
537 | |||
538 | list_for_each_entry(clk, &clocks, node) { | ||
539 | if (clk->mode != pmc_periph_mode) | ||
540 | continue; | ||
541 | |||
542 | if (clk->users > 0) | ||
543 | reg &= ~clk->pmc_mask; | ||
544 | } | ||
545 | |||
546 | at91_sys_write(AT91_PMC_PCDR, reg); | ||
547 | } | ||
548 | |||
549 | static struct clk *const standard_pmc_clocks[] __initdata = { | 528 | static struct clk *const standard_pmc_clocks[] __initdata = { |
550 | /* four primary clocks */ | 529 | /* four primary clocks */ |
551 | &clk32k, | 530 | &clk32k, |
@@ -586,7 +565,7 @@ int __init at91_clock_init(unsigned long main_clock) | |||
586 | pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); | 565 | pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); |
587 | 566 | ||
588 | /* | 567 | /* |
589 | * USB clock init: choose 48 MHz PLLB value, turn all clocks off, | 568 | * USB clock init: choose 48 MHz PLLB value, |
590 | * disable 48MHz clock during usb peripheral suspend. | 569 | * disable 48MHz clock during usb peripheral suspend. |
591 | * | 570 | * |
592 | * REVISIT: assumes MCK doesn't derive from PLLB! | 571 | * REVISIT: assumes MCK doesn't derive from PLLB! |
@@ -596,16 +575,10 @@ int __init at91_clock_init(unsigned long main_clock) | |||
596 | if (cpu_is_at91rm9200()) { | 575 | if (cpu_is_at91rm9200()) { |
597 | uhpck.pmc_mask = AT91RM9200_PMC_UHP; | 576 | uhpck.pmc_mask = AT91RM9200_PMC_UHP; |
598 | udpck.pmc_mask = AT91RM9200_PMC_UDP; | 577 | udpck.pmc_mask = AT91RM9200_PMC_UDP; |
599 | at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP); | ||
600 | at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); | 578 | at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); |
601 | } else if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) { | 579 | } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) { |
602 | uhpck.pmc_mask = AT91SAM926x_PMC_UHP; | 580 | uhpck.pmc_mask = AT91SAM926x_PMC_UHP; |
603 | udpck.pmc_mask = AT91SAM926x_PMC_UDP; | 581 | udpck.pmc_mask = AT91SAM926x_PMC_UDP; |
604 | at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP); | ||
605 | } else if (cpu_is_at91sam9261()) { | ||
606 | uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0); | ||
607 | udpck.pmc_mask = AT91SAM926x_PMC_UDP; | ||
608 | at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP); | ||
609 | } | 582 | } |
610 | at91_sys_write(AT91_CKGR_PLLBR, 0); | 583 | at91_sys_write(AT91_CKGR_PLLBR, 0); |
611 | 584 | ||
@@ -634,11 +607,34 @@ int __init at91_clock_init(unsigned long main_clock) | |||
634 | (unsigned) main_clock / 1000000, | 607 | (unsigned) main_clock / 1000000, |
635 | ((unsigned) main_clock % 1000000) / 1000); | 608 | ((unsigned) main_clock % 1000000) / 1000); |
636 | 609 | ||
637 | /* disable all programmable clocks */ | 610 | return 0; |
638 | at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); | 611 | } |
612 | |||
613 | /* | ||
614 | * Several unused clocks may be active. Turn them off. | ||
615 | */ | ||
616 | static int __init at91_clock_reset(void) | ||
617 | { | ||
618 | unsigned long pcdr = 0; | ||
619 | unsigned long scdr = 0; | ||
620 | struct clk *clk; | ||
621 | |||
622 | list_for_each_entry(clk, &clocks, node) { | ||
623 | if (clk->users > 0) | ||
624 | continue; | ||
625 | |||
626 | if (clk->mode == pmc_periph_mode) | ||
627 | pcdr |= clk->pmc_mask; | ||
628 | |||
629 | if (clk->mode == pmc_sys_mode) | ||
630 | scdr |= clk->pmc_mask; | ||
631 | |||
632 | pr_debug("Clocks: disable unused %s\n", clk->name); | ||
633 | } | ||
639 | 634 | ||
640 | /* disable all other unused peripheral clocks */ | 635 | at91_sys_write(AT91_PMC_PCDR, pcdr); |
641 | at91_periphclk_reset(); | 636 | at91_sys_write(AT91_PMC_SCDR, scdr); |
642 | 637 | ||
643 | return 0; | 638 | return 0; |
644 | } | 639 | } |
640 | late_initcall(at91_clock_reset); | ||