static int omap_32k_timer_set_next_event(unsigned long delta, struct clock_event_device *dev) { omap_32k_timer_start(delta); return 0; }
static __init void omap_init_32k_timer(void) { #ifdef CONFIG_NO_IDLE_HZ omap_timer.dyn_tick = &omap_dyn_tick_timer; #endif setup_irq(INT_OS_TIMER, &omap_32k_timer_irq); omap_timer.offset = omap_32k_timer_gettimeoffset; omap_32k_last_tick = omap_32k_sync_timer_read(); omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); }
static void omap_32k_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { omap_32k_timer_stop(); switch (mode) { case CLOCK_EVT_MODE_PERIODIC: omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); break; case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: break; case CLOCK_EVT_MODE_RESUME: break; } }
/* * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this * function is also called from other interrupts to remove latency * 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) { unsigned long flags; unsigned long now; write_seqlock_irqsave(&xtime_lock, flags); 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); } /* Restart timer so we don't drift off due to modulo or dynamic tick. * By default we program the next timer to be continuous to avoid * latencies during high system load. During dynamic tick operation the * 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); write_sequnlock_irqrestore(&xtime_lock, flags); return IRQ_HANDLED; }
static int omap_32k_timer_disable_dyn_tick(void) { omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD); return 0; }
/* * Programs the next timer interrupt needed. Called when dynamic tick is * enabled, and to reprogram the ticks to skip from pm_idle. Note that * we can keep the timer continuous, and don't need to set it to run in * one-shot mode. This is because the timer will get reprogrammed again * after next interrupt. */ void omap_32k_timer_reprogram(unsigned long next_tick) { omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1); }