OMAP2/3: DMTIMER: Clear pending interrupts when stopping a timer
authorTero Kristo <[email protected]>
Fri, 23 Oct 2009 16:03:47 +0000 (19:03 +0300)
committerTony Lindgren <[email protected]>
Fri, 22 Jan 2010 02:30:10 +0000 (18:30 -0800)
OMAP GP timers keep running for a few cycles after they are stopped,
which can cause the timer to expire and generate an interrupt. The
pending interrupt will prevent e.g. OMAP from entering suspend, thus
we ack it manually.  Only applicable on OMAP2/3/4.

Signed-off-by: Tero Kristo <[email protected]>
Signed-off-by: Kevin Hilman <[email protected]>
Signed-off-by: Tony Lindgren <[email protected]>
arch/arm/plat-omap/dmtimer.c

index 64f407ee0f4e61394cf47673abb082f3300e2d74..08ccf89225202d512de9242e5ceab12457087309 100644 (file)
@@ -551,6 +551,19 @@ void omap_dm_timer_stop(struct omap_dm_timer *timer)
        if (l & OMAP_TIMER_CTRL_ST) {
                l &= ~0x1;
                omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
+                       defined(CONFIG_ARCH_OMAP4)
+               /* Readback to make sure write has completed */
+               omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+                /*
+                 * Wait for functional clock period x 3.5 to make sure that
+                 * timer is stopped
+                 */
+               udelay(3500000 / clk_get_rate(timer->fclk) + 1);
+               /* Ack possibly pending interrupt */
+               omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
+                               OMAP_TIMER_INT_OVERFLOW);
+#endif
        }
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_stop);