/* * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16) */ static void pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { unsigned long flags; switch (mode) { case CLOCK_EVT_MODE_PERIODIC: case CLOCK_EVT_MODE_RESUME: /* update clocksource counter, then enable the IRQ */ raw_local_irq_save(flags); pit_cnt += pit_cycle * PIT_PICNT(at91_sys_read(AT91_PIT_PIVR)); at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN); raw_local_irq_restore(flags); break; case CLOCK_EVT_MODE_ONESHOT: BUG(); /* FALLTHROUGH */ case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: /* disable irq, leaving the clocksource active */ at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN); break; } }
/* * IRQ handler for the timer. */ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id) { /* * irqs should be disabled here, but as the irq is shared they are only * guaranteed to be off if the timer irq is registered first. */ WARN_ON_ONCE(!irqs_disabled()); /* The PIT interrupt may be disabled, and is shared */ if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC) && (pit_read(AT91_PIT_SR) & AT91_PIT_PITS)) { unsigned nr_ticks; /* Get number of ticks performed before irq, and ack it */ nr_ticks = PIT_PICNT(pit_read(AT91_PIT_PIVR)); do { pit_cnt += pit_cycle; pit_clkevt.event_handler(&pit_clkevt); nr_ticks--; } while (nr_ticks); return IRQ_HANDLED; } return IRQ_NONE; }
/* * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16) */ static void pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: /* Set up irq handler */ setup_irq(AT91_ID_SYS, &at91sam926x_pit_irq); /* update clocksource counter */ pit_cnt += pit_cycle * PIT_PICNT(at91_sys_read(AT91_PIT_PIVR)); at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN); break; case CLOCK_EVT_MODE_ONESHOT: BUG(); /* FALLTHROUGH */ case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: /* disable irq, leaving the clocksource active */ at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN); remove_irq(AT91_ID_SYS, &at91sam926x_pit_irq); break; case CLOCK_EVT_MODE_RESUME: break; } }
/* * Clocksource: just a monotonic counter of MCK/16 cycles. * We don't care whether or not PIT irqs are enabled. */ static cycle_t read_pit_clk(void) { unsigned long flags; u32 elapsed; u32 t; raw_local_irq_save(flags); elapsed = pit_cnt; t = at91_sys_read(AT91_PIT_PIIR); raw_local_irq_restore(flags); elapsed += PIT_PICNT(t) * pit_cycle; elapsed += PIT_CPIV(t); return elapsed; }
/* * Clocksource: just a monotonic counter of MCK/16 cycles. * We don't care whether or not PIT irqs are enabled. */ static cycle_t read_pit_clk(struct clocksource *cs) { unsigned long flags; u32 elapsed; u32 t; raw_local_irq_save(flags); elapsed = pit_cnt; t = pit_read(AT91_PIT_PIIR); raw_local_irq_restore(flags); elapsed += PIT_PICNT(t) * pit_cycle; elapsed += PIT_CPIV(t); return elapsed; }
static void at91sam926x_pit_reset(void) { /* Disable timer and irqs */ at91_sys_write(AT91_PIT_MR, 0); /* Clear any pending interrupts, wait for PIT to stop counting */ while (PIT_CPIV(at91_sys_read(AT91_PIT_PIVR)) != 0) ; /* Start PIT but don't enable IRQ */ //at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN); pit_cnt += pit_cycle * PIT_PICNT(at91_sys_read(AT91_PIT_PIVR)); at91_sys_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN | AT91_PIT_PITIEN); rt_kprintf("PIT_MR=0x%08x\n", at91_sys_read(AT91_PIT_MR)); }
/** * This function will handle rtos timer */ void rt_timer_handler(int vector) { #ifdef USE_DBGU if (at91_sys_read(AT91_DBGU + AT91_US_CSR) & 0x1) { //rt_kprintf("DBGU interrupt occur\n"); rt_serial_handler(1); } #endif if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) { unsigned nr_ticks; /* Get number of ticks performed before irq, and ack it */ nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR)); rt_tick_increase(); } }
/* * IRQ handler for the timer. */ static irqreturn_t at91sam926x_pit_interrupt(int irq, void *dev_id) { /* The PIT interrupt may be disabled, and is shared */ if ((pit_clkevt.mode == CLOCK_EVT_MODE_PERIODIC) && (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS)) { unsigned nr_ticks; /* Get number of ticks performed before irq, and ack it */ nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR)); do { pit_cnt += pit_cycle; pit_clkevt.event_handler(&pit_clkevt); nr_ticks--; } while (nr_ticks); return IRQ_HANDLED; } return IRQ_NONE; }