static void pit_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned long flags; /* * The timer interrupt generation is disabled at least * for enough time to call epit_set_next_event() */ local_irq_save(flags); /* Disable interrupt in PIT module */ pit_irq_disable(); if (mode != clockevent_mode) { /* Set event time into far-far future */ /* Clear pending interrupt */ pit_irq_acknowledge(); } /* Remember timer mode */ clockevent_mode = mode; local_irq_restore(flags); switch (mode) { case CLOCK_EVT_MODE_PERIODIC: __raw_writel(0, timer_base + PITOFFSET + PITTCTRL); __raw_writel(pit_cycle_per_jiffy, timer_base + PITOFFSET + PITLDVAL); __raw_writel(PITTCTRL_TEN, timer_base + PITOFFSET + PITTCTRL); pit_irq_enable(); break; case CLOCK_EVT_MODE_ONESHOT: /* * Do not put overhead of interrupt enable/disable into * epit_set_next_event(), the core has about 4 minutes * to call epit_set_next_event() or shutdown clock after * mode switching */ local_irq_save(flags); pit_irq_enable(); local_irq_restore(flags); break; case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_RESUME: /* Left event sources disabled, no more interrupts appear */ break; } }
/* * IRQ handler for the timer */ static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = &clockevent_pit; pit_irq_acknowledge(); pit_cnt += pit_cycle_per_jiffy; evt->event_handler(evt); return IRQ_HANDLED; }
static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; pit_irq_acknowledge(); /* * pit hardware doesn't support oneshot, it will generate an interrupt * and reload the counter value from PITLDVAL when PITCVAL reach zero, * and start the counter again. So software need to disable the timer * to stop the counter loop in ONESHOT mode. */ if (likely(clockevent_state_oneshot(evt))) pit_timer_disable(); evt->event_handler(evt); return IRQ_HANDLED; }