/*
 * 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;
}
static void at91sam926x_pit_reset(void)
{
	/* Disable timer and irqs */
	pit_write(AT91_PIT_MR, 0);

	/* Clear any pending interrupts, wait for PIT to stop counting */
	while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0)
		cpu_relax();

	/* Start PIT but don't enable IRQ */
	pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
}
Example #3
0
int
osenv_timer_pit_read()
{
	int enb;
	int value;

	enb = osenv_intr_save_disable();
	value = pit_read(0);
	if (enb)
		osenv_intr_enable();
	return value;
}
/*
 * 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;
}
Example #5
0
unsigned int timer_read(tim_t dev)
{
    if ((unsigned int)dev >= TIMER_NUMOF) {
        /* invalid timer */
        return 0;
    }
    /* demultiplex to handle two types of hardware timers */
    switch (_timer_variant(dev)) {
        case TIMER_PIT:
            return pit_read(_pit_index(dev));
        case TIMER_LPTMR:
            return lptmr_read(_lptmr_index(dev));
        default:
            return 0;
    }
}
/*
 * 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:
		/* update clocksource counter */
		pit_cnt += pit_cycle * PIT_PICNT(pit_read(AT91_PIT_PIVR));
		pit_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 */
		pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
		break;
	case CLOCK_EVT_MODE_RESUME:
		break;
	}
}
Example #7
0
TIME ll_gettime(int mode, struct timespec *tsres)
{
	DWORD res, tc;
	BYTE isr;
	struct timespec tmp;

#if 1
	if (activeEvent) {
	  if (tsres != NULL) {
	    PITSPEC2TIMESPEC(&globalCounter, tsres);
	  } else {
	    struct timespec tmp;

	    PITSPEC2TIMESPEC(&globalCounter, &tmp);
	    return TIMESPEC2USEC(&tmp);
	  }
	  return TIMESPEC2USEC(tsres);
	}
#endif
	
	if (mode == TIME_PTICK) {
		if (timermode != LL_PERIODIC) {
			return 0;
		}
		res = TIMESPEC2USEC(&actTime);
		if (tsres != NULL) {
			memcpy(tsres, &actTime, sizeof(struct timespec));
		}
		return res;
	}

	if (mode == TIME_NEW) {
	  WORD tmp;
	  
	  tmp = pit_read(frc);
	  ADDPITSPEC((WORD)(lastTime - tmp), &globalCounter);
	  lastTime = tmp;
	  if (tsres != NULL) {
	    PITSPEC2TIMESPEC(&globalCounter, tsres);
	  }
	  return (PITSPEC2USEC(&globalCounter));
	}

	if (mode == TIME_EXACT) {
		if (timermode == LL_PERIODIC) {
			memcpy(&tmp, &actTime, sizeof(struct timespec));
			/* How much time has elapsed
			 * from the last Tick Boundary?
			 */
			tc = pit_read(0);
			if (tc > pit_time_const) {
			    error("LL Time Panic!!!\n");
			    ll_abort(1);
			}
			res = pit_time_const - tc;
			res *= ticksize;
			res /= pit_time_const;

			/* Detect tick boundary and adjust the time... */
			outp(0x20, 0x0A);
			isr = inp(0x20);
			if ((isr & 1) && res < ((8*ticksize)/10)){
			      /*
				res += ticksize;
				ADDNANO2TIMESPEC(ticksize * 1000, &tmp);
			      */
			      res = ticksize;
			}

			/* Sum the Tick time... */
			ADDNANO2TIMESPEC(res * 1000, &tmp);
			res += TIMESPEC2USEC(&actTime);

			if (tsres != NULL) {
				memcpy(tsres, &tmp, sizeof(struct timespec));
			}
			return res;
		} else {
			return 0;
		}
	}
	return 0;
}