diff options
| author | Paul Walmsley <paul@pwsan.com> | 2011-01-16 07:32:01 +0300 | 
|---|---|---|
| committer | Paul Walmsley <paul@pwsan.com> | 2011-01-18 22:04:12 +0300 | 
| commit | d8328f3b85f34c0dc5866f10bf6e7842fb511d62 (patch) | |
| tree | cce2477423a170a77d0ca7364fb0f2329038220c | |
| parent | e78bf5e6cbe837daa6ab628a5f679548742994d3 (diff) | |
| download | linux-d8328f3b85f34c0dc5866f10bf6e7842fb511d62.tar.xz | |
OMAP: counter_32k: init clocksource as part of machine timer init
After commit dc548fbbd2ecd0fc3b02301d551e5f8e19ae58fd ("ARM: omap: convert
sched_clock() to use new infrastructure"), OMAPs that use the 32KiHz
"synchronization timer" as their clocksource crash during boot:
[    0.000000] OMAP clockevent source: GPTIMER1 at 32768 Hz
[    0.000000] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[    0.000000] pgd = c0004000
[    0.000000] [00000000] *pgd=00000000
[    0.000000] Internal error: Oops: 80000005 [#1] SMP
[    0.000000] last sysfs file:
[    0.000000] Modules linked in:
[    0.000000] CPU: 0    Tainted: G        W    (2.6.37-07734-g2467802 #7)
[    0.000000] PC is at 0x0
[    0.000000] LR is at sched_clock_poll+0x2c/0x3c
[    0.000000] pc : [<00000000>]    lr : [<c0060b74>]    psr: 600001d3
[    0.000000] sp : c058bfd0  ip : c058a000  fp : 00000000
[    0.000000] r10: 00000000  r9 : 411fc092  r8 : 800330c8
[    0.000000] r7 : c05a08e0  r6 : c0034c48  r5 : c05ffc40  r4 : c0034c4c
[    0.000000] r3 : c05ffe6c  r2 : c05a0bc0  r1 : c059f098  r0 : 00000000
[    0.000000] Flags: nZCv  IRQs off  FIQs off  Mode SVC_32  ISA ARM  Segment kernel
[    0.000000] Control: 10c53c7f  Table: 8000404a  DAC: 00000017
This is due to the recent ARM init_sched_clock() changes and the late
initialization of the counter_32k clock source.  More information here:
   http://marc.info/?l=linux-omap&m=129513468605208&w=2
Fix by initializing the counter_32k clocksource during the machine timer
initialization.
Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Tested-by: Thomas Weber <weber@corscience.de>
Signed-off-by: Paul Walmsley <paul@pwsan.com>
| -rw-r--r-- | arch/arm/mach-omap1/time.c | 7 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/timer-gp.c | 10 | ||||
| -rw-r--r-- | arch/arm/plat-omap/counter_32k.c | 3 | ||||
| -rw-r--r-- | arch/arm/plat-omap/include/plat/common.h | 1 | 
4 files changed, 17 insertions, 4 deletions
| diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index ed7a61ff916a..6ec65e599997 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -244,6 +244,13 @@ static void __init omap_timer_init(void)  	omap_init_mpu_timer(rate);  	omap_init_clocksource(rate); +	/* +	 * XXX Since this file seems to deal mostly with the MPU timer, +	 * this doesn't seem like the correct place for the sync timer +	 * clocksource init. +	 */ +	if (!cpu_is_omap7xx() && !cpu_is_omap15xx()) +		omap_init_clocksource_32k();  }  struct sys_timer omap_timer = { diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index 4e48e786bec7..7b7c2683ae7b 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -42,6 +42,8 @@  #include "timer-gp.h" +#include <plat/common.h> +  /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */  #define MAX_GPTIMER_ID		12 @@ -176,10 +178,14 @@ static void __init omap2_gp_clockevent_init(void)  /*    * When 32k-timer is enabled, don't use GPTimer for clocksource   * instead, just leave default clocksource which uses the 32k - * sync counter.  See clocksource setup in see plat-omap/common.c.  + * sync counter.  See clocksource setup in plat-omap/counter_32k.c   */ -static inline void __init omap2_gp_clocksource_init(void) {} +static void __init omap2_gp_clocksource_init(void) +{ +	omap_init_clocksource_32k(); +} +  #else  /*   * clocksource diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index ea4644021fb9..0367998ff685 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c @@ -160,7 +160,7 @@ void read_persistent_clock(struct timespec *ts)  	*ts = *tsp;  } -static int __init omap_init_clocksource_32k(void) +int __init omap_init_clocksource_32k(void)  {  	static char err[] __initdata = KERN_ERR  			"%s: can't register clocksource!\n"; @@ -195,7 +195,6 @@ static int __init omap_init_clocksource_32k(void)  	}  	return 0;  } -arch_initcall(omap_init_clocksource_32k);  #endif	/* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */ diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index 6b8088ec74af..84c707f713b1 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h @@ -35,6 +35,7 @@ struct sys_timer;  extern void omap_map_common_io(void);  extern struct sys_timer omap_timer; +extern int __init omap_init_clocksource_32k(void);  extern void omap_reserve(void); | 
