diff options
author | Tony Lindgren <tony@atomide.com> | 2011-11-11 13:15:11 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2011-11-11 13:15:11 -0500 |
commit | e9b7086b80c4d9e354f4edc9e280ae85a60df408 (patch) | |
tree | 2598427ece342e0cbe34c7521f81efb6caea33bd /arch/arm/mach-omap1 | |
parent | 7be620f79714b6598275bd5c71d89bb24dfe332e (diff) |
ARM: OMAP: Fix reprogramming of dpll1 rate
Commit a66cb3454f220f49f900646ebdc76cb943319eb7 (ARM: OMAP: Map SRAM
later on with ioremap_exec()) moved the SRAM init to happen later
to remove a dependency to early SoC detection for map_io.
This broke booting on some boards not using Kconfig option for
OMAP_CLOCKS_SET_BY_BOOTLOADER as the dpll1 reprogramming would
cause the following error:
kernel BUG at arch/arm/plat-omap/sram.c:226!
Internal error: Oops - undefined instruction: 0 [#1] PREEMPT
Modules linked in:
CPU: 0 Not tainted (3.2.0-rc1-e3 #9)
PC is at omap_sram_reprogram_clock+0x28/0x30
LR is at omap1_select_table_rate+0x88/0xb4
pc : [<c001b0c4>] lr : [<c0019f54>] psr: 600000d3
sp : c035bf10 ip : c035bf20 fp : c035bf1c
r10: c035bfd4 r9 : 54029252 r8 : c03f8120
r7 : c0362b50 r6 : 00b71b00 r5 : c03873cc r4 : c0362b40
r3 : 00000000 r2 : c0362b40 r1 : 0000010a r0 : 00002cb0
Flags: nZCv IRQs off FIQs off Mode SVC_32 ISA ARM Segment kernel
Control: 0000317f Table: 10004000 DAC: 00000017
Process swapper (pid: 0, stack limit = 0xc035a270)
Stack: (0xc035bf10 to 0xc035c000)
bf00: c035bf3c c035bf20 c0019f54 c001b0ac
bf20: 00001000 00002cb3 00000004 c035ed4c c035bf74 c035bf40 c033ea24 c0019edc
bf40: c02f526c 00000002 00000015 bc058c9b 93111a16 c035335c 02000000 c035ed4c
bf60: c035ed4c c03f8120 c035bf84 c035bf78 c00194c4 c033e8ec c035bfc4 c035bf88
bf80: c033bc24 c00194a0 c035bf90 c035bf98 00000000 00000000 00000000 00000000
bfa0: 00000001 00000000 c0354678 c035ece4 10004000 103532f4 c035bff4 c035bfc8
bfc0: c0338574 c033b598 00000000 00000000 00000000 c035467c 0000317d c035c03c
bfe0: c0354678 c035ece4 00000000 c035bff8 10008040 c0338508 00000000 00000000
Backtrace:
[<c001b09c>] (omap_sram_reprogram_clock+0x0/0x30) from [<c0019f54>] (omap1_select_table_rate+0x88/0xb4)
[<c0019ecc>] (omap1_select_table_rate+0x0/0xb4) from [<c033ea24>] (omap1_clk_init+0x148/0x334)
r7:c035ed4c r6:00000004 r5:00002cb3 r4:00001000
[<c033e8dc>] (omap1_clk_init+0x0/0x334) from [<c00194c4>] (omap1_init_early+0x34/0x48)
r8:c03f8120 r7:c035ed4c r6:c035ed4c r5:02000000 r4:c035335c
[<c0019490>] (omap1_init_early+0x0/0x48) from [<c033bc24>] (setup_arch+0x69c/0x79c)
[<c033b588>] (setup_arch+0x0/0x79c) from [<c0338574>] (start_kernel+0x7c/0x2f4)
[<c03384f8>] (start_kernel+0x0/0x2f4) from [<10008040>] (0x10008040)
r7:c035ece4 r6:c0354678 r5:c035c03c r4:0000317d
Code: 0a000002 e1a0e00f e12fff13 e89da800 (e7f001f2)
Fix this by adding omap1_clk_late_init() that only reprograms dpll1
if the bootloader rate is less than 60MHz. This also allows removing
of the OMAP_CLOCKS_SET_BY_BOOTLOADER option.
Reported-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Tested-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap1')
-rw-r--r-- | arch/arm/mach-omap1/Kconfig | 8 | ||||
-rw-r--r-- | arch/arm/mach-omap1/clock.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap1/clock_data.c | 53 | ||||
-rw-r--r-- | arch/arm/mach-omap1/devices.c | 3 |
4 files changed, 39 insertions, 28 deletions
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index e0a028161dde..73f287d6429b 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig | |||
@@ -171,14 +171,6 @@ config MACH_OMAP_GENERIC | |||
171 | comment "OMAP CPU Speed" | 171 | comment "OMAP CPU Speed" |
172 | depends on ARCH_OMAP1 | 172 | depends on ARCH_OMAP1 |
173 | 173 | ||
174 | config OMAP_CLOCKS_SET_BY_BOOTLOADER | ||
175 | bool "OMAP clocks set by bootloader" | ||
176 | depends on ARCH_OMAP1 | ||
177 | help | ||
178 | Enable this option to prevent the kernel from overriding the clock | ||
179 | frequencies programmed by bootloader for MPU, DSP, MMUs, TC, | ||
180 | internal LCD controller and MPU peripherals. | ||
181 | |||
182 | config OMAP_ARM_216MHZ | 174 | config OMAP_ARM_216MHZ |
183 | bool "OMAP ARM 216 MHz CPU (1710 only)" | 175 | bool "OMAP ARM 216 MHz CPU (1710 only)" |
184 | depends on ARCH_OMAP1 && ARCH_OMAP16XX | 176 | depends on ARCH_OMAP1 && ARCH_OMAP16XX |
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index eaf09efb91ca..16b1423b454a 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h | |||
@@ -17,7 +17,8 @@ | |||
17 | 17 | ||
18 | #include <plat/clock.h> | 18 | #include <plat/clock.h> |
19 | 19 | ||
20 | extern int __init omap1_clk_init(void); | 20 | int omap1_clk_init(void); |
21 | void omap1_clk_late_init(void); | ||
21 | extern int omap1_clk_enable(struct clk *clk); | 22 | extern int omap1_clk_enable(struct clk *clk); |
22 | extern void omap1_clk_disable(struct clk *clk); | 23 | extern void omap1_clk_disable(struct clk *clk); |
23 | extern long omap1_clk_round_rate(struct clk *clk, unsigned long rate); | 24 | extern long omap1_clk_round_rate(struct clk *clk, unsigned long rate); |
diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c index 92400b9eb69f..1297bb58869c 100644 --- a/arch/arm/mach-omap1/clock_data.c +++ b/arch/arm/mach-omap1/clock_data.c | |||
@@ -767,6 +767,15 @@ static struct clk_functions omap1_clk_functions = { | |||
767 | .clk_disable_unused = omap1_clk_disable_unused, | 767 | .clk_disable_unused = omap1_clk_disable_unused, |
768 | }; | 768 | }; |
769 | 769 | ||
770 | static void __init omap1_show_rates(void) | ||
771 | { | ||
772 | pr_notice("Clocking rate (xtal/DPLL1/MPU): " | ||
773 | "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n", | ||
774 | ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10, | ||
775 | ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10, | ||
776 | arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10); | ||
777 | } | ||
778 | |||
770 | int __init omap1_clk_init(void) | 779 | int __init omap1_clk_init(void) |
771 | { | 780 | { |
772 | struct omap_clk *c; | 781 | struct omap_clk *c; |
@@ -835,9 +844,12 @@ int __init omap1_clk_init(void) | |||
835 | /* We want to be in syncronous scalable mode */ | 844 | /* We want to be in syncronous scalable mode */ |
836 | omap_writew(0x1000, ARM_SYSST); | 845 | omap_writew(0x1000, ARM_SYSST); |
837 | 846 | ||
838 | #ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER | 847 | |
839 | /* Use values set by bootloader. Determine PLL rate and recalculate | 848 | /* |
840 | * dependent clocks as if kernel had changed PLL or divisors. | 849 | * Initially use the values set by bootloader. Determine PLL rate and |
850 | * recalculate dependent clocks as if kernel had changed PLL or | ||
851 | * divisors. See also omap1_clk_late_init() that can reprogram dpll1 | ||
852 | * after the SRAM is initialized. | ||
841 | */ | 853 | */ |
842 | { | 854 | { |
843 | unsigned pll_ctl_val = omap_readw(DPLL_CTL); | 855 | unsigned pll_ctl_val = omap_readw(DPLL_CTL); |
@@ -862,25 +874,10 @@ int __init omap1_clk_init(void) | |||
862 | } | 874 | } |
863 | } | 875 | } |
864 | } | 876 | } |
865 | #else | ||
866 | /* Find the highest supported frequency and enable it */ | ||
867 | if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) { | ||
868 | printk(KERN_ERR "System frequencies not set. Check your config.\n"); | ||
869 | /* Guess sane values (60MHz) */ | ||
870 | omap_writew(0x2290, DPLL_CTL); | ||
871 | omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL); | ||
872 | ck_dpll1.rate = 60000000; | ||
873 | } | ||
874 | #endif | ||
875 | propagate_rate(&ck_dpll1); | 877 | propagate_rate(&ck_dpll1); |
876 | /* Cache rates for clocks connected to ck_ref (not dpll1) */ | 878 | /* Cache rates for clocks connected to ck_ref (not dpll1) */ |
877 | propagate_rate(&ck_ref); | 879 | propagate_rate(&ck_ref); |
878 | printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): " | 880 | omap1_show_rates(); |
879 | "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n", | ||
880 | ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10, | ||
881 | ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10, | ||
882 | arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10); | ||
883 | |||
884 | if (machine_is_omap_perseus2() || machine_is_omap_fsample()) { | 881 | if (machine_is_omap_perseus2() || machine_is_omap_fsample()) { |
885 | /* Select slicer output as OMAP input clock */ | 882 | /* Select slicer output as OMAP input clock */ |
886 | omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1, | 883 | omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1, |
@@ -925,3 +922,21 @@ int __init omap1_clk_init(void) | |||
925 | 922 | ||
926 | return 0; | 923 | return 0; |
927 | } | 924 | } |
925 | |||
926 | #define OMAP1_DPLL1_SANE_VALUE 60000000 | ||
927 | |||
928 | void __init omap1_clk_late_init(void) | ||
929 | { | ||
930 | if (ck_dpll1.rate >= OMAP1_DPLL1_SANE_VALUE) | ||
931 | return; | ||
932 | |||
933 | /* Find the highest supported frequency and enable it */ | ||
934 | if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) { | ||
935 | pr_err("System frequencies not set, using default. Check your config.\n"); | ||
936 | omap_writew(0x2290, DPLL_CTL); | ||
937 | omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL); | ||
938 | ck_dpll1.rate = OMAP1_DPLL1_SANE_VALUE; | ||
939 | } | ||
940 | propagate_rate(&ck_dpll1); | ||
941 | omap1_show_rates(); | ||
942 | } | ||
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 48ef9888e820..475cb2f50d87 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <plat/omap7xx.h> | 30 | #include <plat/omap7xx.h> |
31 | #include <plat/mcbsp.h> | 31 | #include <plat/mcbsp.h> |
32 | 32 | ||
33 | #include "clock.h" | ||
34 | |||
33 | /*-------------------------------------------------------------------------*/ | 35 | /*-------------------------------------------------------------------------*/ |
34 | 36 | ||
35 | #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE) | 37 | #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE) |
@@ -293,6 +295,7 @@ static int __init omap1_init_devices(void) | |||
293 | return -ENODEV; | 295 | return -ENODEV; |
294 | 296 | ||
295 | omap_sram_init(); | 297 | omap_sram_init(); |
298 | omap1_clk_late_init(); | ||
296 | 299 | ||
297 | /* please keep these calls, and their implementations above, | 300 | /* please keep these calls, and their implementations above, |
298 | * in alphabetical order so they're easier to sort through. | 301 | * in alphabetical order so they're easier to sort through. |