]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
ARM: OMAP: Optional timer modulo code
authorTuukka Tikkanen <>
Mon, 9 May 2005 20:17:56 +0000 (13:17 -0700)
committerTony Lindgren <tony@atomide.com>
Mon, 9 May 2005 20:17:56 +0000 (13:17 -0700)
Adds support for running 32KHz timer at 100HZ using modulo code.

Signed-off-by: Tuukka Tikkanen <>
Signed-off-by: Tony Lindgren <tony@atomide.com>
arch/arm/mach-omap/Kconfig
arch/arm/mach-omap/omap1/time.c

index ae0549a1366725de13577be477d71b2437cd1d93..c5e7776b660f1ec8160d7fb03592d15d47713fca 100644 (file)
@@ -117,7 +117,9 @@ config OMAP_32K_TIMER_HZ
        default "128"
        help
          Kernel internal timer frequency should be a divisor of 32768,
-         such as 64 or 128.
+         such as 64 or 128. If ARM Linux default HZ=100 is used, the system
+         will still work, but the timer interrupt will use less efficient
+         modulo code.
 
 config OMAP_DM_TIMER
        bool "Use dual-mode timer"
index b5e3aa7c0d1c2f0424128d29eb27e037017834d6..e54a319baa3ec9734496ec63a51f81c183e973f7 100644 (file)
@@ -247,6 +247,13 @@ unsigned long long sched_clock(void)
 #define OMAP_32K_TIMER_TCR             0x04
 
 #define OMAP_32K_TICKS_PER_HZ          (32768 / HZ)
+#if (32768 % HZ) != 0
+/* We cannot ignore modulo.
+ * Potential error can be as high as several percent.
+ */
+#define OMAP_32K_TICK_MODULO           (32768 % HZ)
+static unsigned modulo_count = 0; /* Counts 1/HZ units */
+#endif
 
 /*
  * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
@@ -324,6 +331,19 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
        now = omap_32k_sync_timer_read();
 
        while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
+#ifdef OMAP_32K_TICK_MODULO
+               /* Modulo addition may put omap_32k_last_tick ahead of now
+                * and cause unwanted repetition of the while loop.
+                */
+               if (unlikely(now - omap_32k_last_tick == ~0))
+                       break;
+
+               modulo_count += OMAP_32K_TICK_MODULO;
+               if (modulo_count > HZ) {
+                       ++omap_32k_last_tick;
+                       modulo_count -= HZ;
+               }
+#endif
                omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
                timer_tick(regs);
        }