diff options
author | Colin Cross <[email protected]> | 2012-10-18 12:20:08 +0300 |
---|---|---|
committer | Kevin Hilman <[email protected]> | 2012-11-05 14:26:43 -0800 |
commit | cd8ce159031813eb870a5f3d5b27c3be36cd6e3a (patch) | |
tree | deaa9a4ccac205b288aff709f39c0b622d0b91b7 /arch/arm/mach-omap2/omap-smp.c | |
parent | ff999b8a0983ee15668394ed49e38d3568fc6859 (diff) |
ARM: OMAP4: retrigger localtimers after re-enabling gic
'Workaround for ROM bug because of CA9 r2pX gic control'
register change disables the gic distributor while the secondary
cpu is being booted. If a localtimer interrupt on the primary cpu
occurs when the distributor is turned off, the interrupt is lost,
and the localtimer never fires again.
Make the primary cpu wait for the secondary cpu to reenable the
gic distributor (with interrupts off for safety), and then
check if the pending bit is set in the localtimer but not the
gic. If so, ack it in the localtimer, and reset the timer with
the minimum timeout to trigger a new timer interrupt.
Signed-off-by: Colin Cross <[email protected]>
[[email protected]: adapted to k3.4 + validated functionality]
Signed-off-by: Sebastien Jan <[email protected]>
[[email protected]: dropped generic ARM kernel exports from the code, rebased
to mainline]
Signed-off-by: Tero Kristo <[email protected]>
Signed-off-by: Kevin Hilman <[email protected]>
Diffstat (limited to 'arch/arm/mach-omap2/omap-smp.c')
-rw-r--r-- | arch/arm/mach-omap2/omap-smp.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index 7d9c0e3fedc4..49a08dfe8d88 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -134,11 +134,22 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct * * 2) CPU1 must re-enable the GIC distributor on * it's wakeup path. */ - if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) + if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) { + local_irq_disable(); gic_dist_disable(); + } clkdm_wakeup(cpu1_clkdm); clkdm_allow_idle(cpu1_clkdm); + + if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) { + while (gic_dist_disabled()) { + udelay(1); + cpu_relax(); + } + gic_timer_retrigger(); + local_irq_enable(); + } } else { dsb_sev(); booted = true; |