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>
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 = {
#include "timer-gp.h"
+#include <plat/common.h>
+
/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
#define MAX_GPTIMER_ID 12
/*
* 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
*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";
}
return 0;
}
-arch_initcall(omap_init_clocksource_32k);
#endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
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);