[PATCH] ARM: OMAP: Fix reprogramming of dpll1 rate

Aaro Koskinen aaro.koskinen at iki.fi
Fri Nov 11 18:22:20 EST 2011


Hi,

On 11.11.2011, at 21.16, Tony Lindgren wrote:
> 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 at iki.fi>
> Signed-off-by: Tony Lindgren <tony at atomide.com>
>
> ---
> This seems to work when forced on OSK5912 at least. Moving the dpll1
> reprogramming to happen later should not mess up drivers as it's still
> before driver inits. Also the system timer should not change as the
> source is ck_ref.

Cheers mate, this fixes the 3.2-rc1 boot issue on Amstrad E3.

Tested-by: Aaro Koskinen <aaro.koskinen at iki.fi>

A.

> ---
> diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/ 
> omap1_defconfig
> index 7b63462..a7e7775 100644
> --- a/arch/arm/configs/omap1_defconfig
> +++ b/arch/arm/configs/omap1_defconfig
> @@ -48,7 +48,6 @@ CONFIG_MACH_SX1=y
>  CONFIG_MACH_NOKIA770=y
>  CONFIG_MACH_AMS_DELTA=y
>  CONFIG_MACH_OMAP_GENERIC=y
> -CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER=y
>  CONFIG_OMAP_ARM_216MHZ=y
>  CONFIG_OMAP_ARM_195MHZ=y
>  CONFIG_OMAP_ARM_192MHZ=y
> diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig
> index e0a0281..73f287d 100644
> --- a/arch/arm/mach-omap1/Kconfig
> +++ b/arch/arm/mach-omap1/Kconfig
> @@ -171,14 +171,6 @@ config MACH_OMAP_GENERIC
>  comment "OMAP CPU Speed"
>  	depends on ARCH_OMAP1
>
> -config OMAP_CLOCKS_SET_BY_BOOTLOADER
> -	bool "OMAP clocks set by bootloader"
> -	depends on ARCH_OMAP1
> -	help
> -	  Enable this option to prevent the kernel from overriding the clock
> -	  frequencies programmed by bootloader for MPU, DSP, MMUs, TC,
> -	  internal LCD controller and MPU peripherals.
> -
>  config OMAP_ARM_216MHZ
>  	bool "OMAP ARM 216 MHz CPU (1710 only)"
>          depends on ARCH_OMAP1 && ARCH_OMAP16XX
> diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
> index eaf09ef..16b1423 100644
> --- a/arch/arm/mach-omap1/clock.h
> +++ b/arch/arm/mach-omap1/clock.h
> @@ -17,7 +17,8 @@
>
>  #include <plat/clock.h>
>
> -extern int __init omap1_clk_init(void);
> +int omap1_clk_init(void);
> +void omap1_clk_late_init(void);
>  extern int omap1_clk_enable(struct clk *clk);
>  extern void omap1_clk_disable(struct clk *clk);
>  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 92400b9..1297bb5 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 = {
>  	.clk_disable_unused	= omap1_clk_disable_unused,
>  };
>
> +static void __init omap1_show_rates(void)
> +{
> +	pr_notice("Clocking rate (xtal/DPLL1/MPU): "
> +			"%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
> +		ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
> +		ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
> +		arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
> +}
> +
>  int __init omap1_clk_init(void)
>  {
>  	struct omap_clk *c;
> @@ -835,9 +844,12 @@ int __init omap1_clk_init(void)
>  	/* We want to be in syncronous scalable mode */
>  	omap_writew(0x1000, ARM_SYSST);
>
> -#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER
> -	/* Use values set by bootloader. Determine PLL rate and recalculate
> -	 * dependent clocks as if kernel had changed PLL or divisors.
> +
> +	/*
> +	 * Initially use the values set by bootloader. Determine PLL rate  
> and
> +	 * recalculate dependent clocks as if kernel had changed PLL or
> +	 * divisors. See also omap1_clk_late_init() that can reprogram dpll1
> +	 * after the SRAM is initialized.
>  	 */
>  	{
>  		unsigned pll_ctl_val = omap_readw(DPLL_CTL);
> @@ -862,25 +874,10 @@ int __init omap1_clk_init(void)
>  			}
>  		}
>  	}
> -#else
> -	/* Find the highest supported frequency and enable it */
> -	if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
> -		printk(KERN_ERR "System frequencies not set. Check your config. 
> \n");
> -		/* Guess sane values (60MHz) */
> -		omap_writew(0x2290, DPLL_CTL);
> -		omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL);
> -		ck_dpll1.rate = 60000000;
> -	}
> -#endif
>  	propagate_rate(&ck_dpll1);
>  	/* Cache rates for clocks connected to ck_ref (not dpll1) */
>  	propagate_rate(&ck_ref);
> -	printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
> -		"%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
> -	       ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
> -	       ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
> -	       arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
> -
> +	omap1_show_rates();
>  	if (machine_is_omap_perseus2() || machine_is_omap_fsample()) {
>  		/* Select slicer output as OMAP input clock */
>  		omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1,
> @@ -925,3 +922,21 @@ int __init omap1_clk_init(void)
>
>  	return 0;
>  }
> +
> +#define OMAP1_DPLL1_SANE_VALUE	60000000
> +
> +void __init omap1_clk_late_init(void)
> +{
> +	if (ck_dpll1.rate >= OMAP1_DPLL1_SANE_VALUE)
> +		return;
> +
> +	/* Find the highest supported frequency and enable it */
> +	if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
> +		pr_err("System frequencies not set, using default. Check your  
> config.\n");
> +		omap_writew(0x2290, DPLL_CTL);
> +		omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL);
> +		ck_dpll1.rate = OMAP1_DPLL1_SANE_VALUE;
> +	}
> +	propagate_rate(&ck_dpll1);
> +	omap1_show_rates();
> +}
> diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/ 
> devices.c
> index 48ef988..475cb2f 100644
> --- a/arch/arm/mach-omap1/devices.c
> +++ b/arch/arm/mach-omap1/devices.c
> @@ -30,6 +30,8 @@
>  #include <plat/omap7xx.h>
>  #include <plat/mcbsp.h>
>
> +#include "clock.h"
> +
>  / 
> *--------------------------------------------------------------------- 
> ----*/
>
>  #if defined(CONFIG_RTC_DRV_OMAP) || defined 
> (CONFIG_RTC_DRV_OMAP_MODULE)
> @@ -293,6 +295,7 @@ static int __init omap1_init_devices(void)
>  		return -ENODEV;
>
>  	omap_sram_init();
> +	omap1_clk_late_init();
>
>  	/* please keep these calls, and their implementations above,
>  	 * in alphabetical order so they're easier to sort through.




More information about the linux-arm-kernel mailing list