Пример #1
0
/*
 * IRQ handler for the timer
 */
static irqreturn_t
imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	write_seqlock(&xtime_lock);

	/* clear the interrupt */
	if (IMX_TSTAT(TIMER_BASE))
		IMX_TSTAT(TIMER_BASE) = 0;

	timer_tick(regs);
	write_sequnlock(&xtime_lock);

	return IRQ_HANDLED;
}
Пример #2
0
/*
 * IRQ handler for the timer
 */
static irqreturn_t
imx_timer_interrupt(int irq, void *dev_id)
{
	struct clock_event_device *evt = &clockevent_imx;
	uint32_t tstat;
	irqreturn_t ret = IRQ_NONE;

	/* clear the interrupt */
	tstat = IMX_TSTAT(TIMER_BASE);
	IMX_TSTAT(TIMER_BASE) = 0;

	if (tstat & TSTAT_COMP) {
		evt->event_handler(evt);
		ret = IRQ_HANDLED;
	}

	return ret;
}
Пример #3
0
/*
 * IRQ handler for the timer
 */
static irqreturn_t
imx_timer_interrupt(int irq, void *dev_id)
{
	uint32_t tstat;

	/* clear the interrupt */
	tstat = IMX_TSTAT(TIMER_BASE);
	IMX_TSTAT(TIMER_BASE) = 0;

	if (tstat & TSTAT_COMP) {
		do {

			write_seqlock(&xtime_lock);
			timer_tick();
			write_sequnlock(&xtime_lock);
			IMX_TCMP(TIMER_BASE) += evt_diff;

		} while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE)
					- IMX_TCN(TIMER_BASE)) < 0));
	}

	return IRQ_HANDLED;
}
Пример #4
0
static void imx_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 imx_set_next_event()
	 */
	local_irq_save(flags);
	/* Disable interrupt in GPT module */
	IMX_TCTL(TIMER_BASE) &= ~TCTL_IRQEN;
	if (mode != clockevent_mode) {
		/* Set event time into far-far future */
		IMX_TCMP(TIMER_BASE) = IMX_TCN(TIMER_BASE) - 3;
		/* Clear pending interrupt */
		IMX_TSTAT(TIMER_BASE) &= ~TSTAT_COMP;
	}

#ifdef DEBUG
	printk(KERN_INFO "imx_set_mode: changing mode from %s to %s\n",
		clock_event_mode_label[clockevent_mode], clock_event_mode_label[mode]);
#endif /*DEBUG*/

	/* Remember timer mode */
	clockevent_mode = mode;
	local_irq_restore(flags);

	switch (mode) {
	case CLOCK_EVT_MODE_PERIODIC:
		printk(KERN_ERR "imx_set_mode: Periodic mode is not supported for i.MX\n");
		break;
	case CLOCK_EVT_MODE_ONESHOT:
		/*
		 * Do not put overhead of interrupt enable/disable into
		 * imx_set_next_event(), the core has about 4 minutes
		 * to call imx_set_next_event() or shutdown clock after
		 * mode switching
		 */
		local_irq_save(flags);
		IMX_TCTL(TIMER_BASE) |= TCTL_IRQEN;
		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 appears */
		break;
	}
}
Пример #5
0
/*
 * Returns number of us since last clock interrupt.  Note that interrupts
 * will have been disabled by do_gettimeoffset()
 */
static unsigned long imx_gettimeoffset(void)
{
	unsigned long ticks;

	/*
	 * Get the current number of ticks.  Note that there is a race
	 * condition between us reading the timer and checking for
	 * an interrupt.  We get around this by ensuring that the
	 * counter has not reloaded between our two reads.
	 */
	ticks = IMX_TCN(TIMER_BASE);

	/*
	 * Interrupt pending?  If so, we've reloaded once already.
	 */
	if (IMX_TSTAT(TIMER_BASE) & TSTAT_COMP)
		ticks += LATCH;

	/*
	 * Convert the ticks to usecs
	 */
	return (1000000 / CLK32) * ticks;
}