summaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/timer32k.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-28 14:40:39 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-28 14:40:39 -0700
commitebdea46fecae40c4d7effcd33f40918a37a1df4b (patch)
treee4312bf7f1f3d184738963a0ec300aa9fdfd55c1 /arch/arm/plat-omap/timer32k.c
parentfecf3404f4aba6d0edeba31eeb018cbb6326dff2 (diff)
parent250d375d1da45a5e08ab8baf5eaa7eb258afd82b (diff)
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (130 commits) [ARM] 3856/1: Add clocksource for Intel IXP4xx platforms [ARM] 3855/1: Add generic time support [ARM] 3873/1: S3C24XX: Add irq_chip names [ARM] 3872/1: S3C24XX: Apply consistant tabbing to irq_chips [ARM] 3871/1: S3C24XX: Fix ordering of EINT4..23 [ARM] nommu: confirms the CR_V bit in nommu mode [ARM] nommu: abort handler fixup for !CPU_CP15_MMU cores. [ARM] 3870/1: AT91: Start removing static memory mappings [ARM] 3869/1: AT91: NAND support for DK and KB9202 boards [ARM] 3868/1: AT91 hardware header update [ARM] 3867/1: AT91 GPIO update [ARM] 3866/1: AT91 clock update [ARM] 3865/1: AT91RM9200 header updates [ARM] 3862/2: S3C2410 - add basic power management support for AML M5900 series [ARM] kthread: switch arch/arm/kernel/apm.c [ARM] Off-by-one in arch/arm/common/icst* [ARM] 3864/1: Refactore sharpsl_pm [ARM] 3863/1: Add Locomo SPI Device [ARM] 3847/2: Convert LOMOMO to use struct device for GPIOs [ARM] Use CPU_CACHE_* where possible in asm/cacheflush.h ...
Diffstat (limited to 'arch/arm/plat-omap/timer32k.c')
-rw-r--r--arch/arm/plat-omap/timer32k.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
index 281ecc7fcdf..cf6df3378d3 100644
--- a/arch/arm/plat-omap/timer32k.c
+++ b/arch/arm/plat-omap/timer32k.c
@@ -105,6 +105,8 @@ static inline unsigned long omap_32k_timer_read(int reg)
static inline void omap_32k_timer_start(unsigned long load_val)
{
+ if (!load_val)
+ load_val = 1;
omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
}
@@ -192,14 +194,11 @@ unsigned long long sched_clock(void)
* issues with dynamic tick. In the dynamic tick case, we need to lock
* with irqsave.
*/
-static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
+static inline irqreturn_t _omap_32k_timer_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
{
- unsigned long flags;
unsigned long now;
- write_seqlock_irqsave(&xtime_lock, flags);
-
omap_32k_timer_ack_irq();
now = omap_32k_sync_timer_read();
@@ -215,6 +214,23 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
* continuous timer can be overridden from pm_idle to be longer.
*/
omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_32k_timer_handler(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ return _omap_32k_timer_interrupt(irq, dev_id, regs);
+}
+
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ unsigned long flags;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+ _omap_32k_timer_interrupt(irq, dev_id, regs);
write_sequnlock_irqrestore(&xtime_lock, flags);
return IRQ_HANDLED;
@@ -230,7 +246,15 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
*/
void omap_32k_timer_reprogram(unsigned long next_tick)
{
- omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
+ unsigned long ticks = JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1;
+ unsigned long now = omap_32k_sync_timer_read();
+ unsigned long idled = now - omap_32k_last_tick;
+
+ if (idled + 1 < ticks)
+ ticks -= idled;
+ else
+ ticks = 1;
+ omap_32k_timer_start(ticks);
}
static struct irqaction omap_32k_timer_irq;
@@ -252,7 +276,7 @@ static struct dyn_tick_timer omap_dyn_tick_timer = {
.enable = omap_32k_timer_enable_dyn_tick,
.disable = omap_32k_timer_disable_dyn_tick,
.reprogram = omap_32k_timer_reprogram,
- .handler = omap_32k_timer_interrupt,
+ .handler = omap_32k_timer_handler,
};
#endif /* CONFIG_NO_IDLE_HZ */