From 8e3fb9b89dc628e69b6cb4ed546c76c960b08190 Mon Sep 17 00:00:00 2001 From: Tuukka Tikkanen <> Date: Mon, 9 May 2005 13:17:56 -0700 Subject: [PATCH] ARM: OMAP: Optional timer modulo code Adds support for running 32KHz timer at 100HZ using modulo code. Signed-off-by: Tuukka Tikkanen <> Signed-off-by: Tony Lindgren --- arch/arm/mach-omap/Kconfig | 4 +++- arch/arm/mach-omap/omap1/time.c | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig index ae0549a1366..c5e7776b660 100644 --- a/arch/arm/mach-omap/Kconfig +++ b/arch/arm/mach-omap/Kconfig @@ -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" diff --git a/arch/arm/mach-omap/omap1/time.c b/arch/arm/mach-omap/omap1/time.c index b5e3aa7c0d1..e54a319baa3 100644 --- a/arch/arm/mach-omap/omap1/time.c +++ b/arch/arm/mach-omap/omap1/time.c @@ -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); } -- 2.41.1