static irqreturn_t
mxs_nomatch_timer_interrupt(int irq, void *dev_id)
{
	struct clock_event_device *c = dev_id;

	/* timer 0 */
	if (__raw_readl(online_timer->base + HW_TIMROT_TIMCTRLn(0)) &
			BM_TIMROT_TIMCTRLn_IRQ) {

		__raw_writel(BM_TIMROT_TIMCTRLn_IRQ,
				online_timer->base + HW_TIMROT_TIMCTRLn_CLR(0));
		c->event_handler(c);
	}

	/* timer 1 */
	else if (__raw_readl(online_timer->base + HW_TIMROT_TIMCTRLn(1))
			& BM_TIMROT_TIMCTRLn_IRQ) {
		__raw_writel(BM_TIMROT_TIMCTRLn_IRQ,
				online_timer->base + HW_TIMROT_TIMCTRLn_CLR(1));
		__raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN,
				online_timer->base + HW_TIMROT_TIMCTRLn_CLR(1));
		__raw_writel(0xFFFF,
				online_timer->base + HW_TIMROT_TIMCOUNTn(1));
	}

	return IRQ_HANDLED;
}
Exemple #2
0
static void __init mxs_timer_init(struct device_node *np)
{
	struct clk *timer_clk;
	int irq;

	mxs_timrot_base = of_iomap(np, 0);
	WARN_ON(!mxs_timrot_base);

	timer_clk = of_clk_get(np, 0);
	if (IS_ERR(timer_clk)) {
		pr_err("%s: failed to get clk\n", __func__);
		return;
	}

	clk_prepare_enable(timer_clk);

	/*
	 * Initialize timers to a known state
	 */
	stmp_reset_block(mxs_timrot_base + HW_TIMROT_ROTCTRL);

	/* get timrot version */
	timrot_major_version = __raw_readl(mxs_timrot_base +
			(of_device_is_compatible(np, "fsl,imx23-timrot") ?
						MX23_TIMROT_VERSION_OFFSET :
						MX28_TIMROT_VERSION_OFFSET));
	timrot_major_version >>= BP_TIMROT_MAJOR_VERSION;

	/* one for clock_event */
	__raw_writel((timrot_is_v1() ?
			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
			BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) |
			BM_TIMROT_TIMCTRLn_UPDATE |
			BM_TIMROT_TIMCTRLn_IRQ_EN,
			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));

	/* another for clocksource */
	__raw_writel((timrot_is_v1() ?
			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
			BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) |
			BM_TIMROT_TIMCTRLn_RELOAD,
			mxs_timrot_base + HW_TIMROT_TIMCTRLn(1));

	/* set clocksource timer fixed count to the maximum */
	if (timrot_is_v1())
		__raw_writel(0xffff,
			mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
	else
		__raw_writel(0xffffffff,
			mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));

	/* init and register the timer to the framework */
	mxs_clocksource_init(timer_clk);
	mxs_clockevent_init(timer_clk);

	/* Make irqs happen */
	irq = irq_of_parse_and_map(np, 0);
	setup_irq(irq, &mxs_timer_irq);
}
Exemple #3
0
static int timrotv1_set_next_event(unsigned long evt,
					struct clock_event_device *dev)
{
	/* timrot decrements the count */
	__raw_writel(evt, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(0));

	return 0;
}
static int
mxs_nomatch_timrot_set_next_event(unsigned long delta,
		struct clock_event_device *dev)
{
	/* reload the timer */
	__raw_writel(delta, online_timer->base + HW_TIMROT_TIMCOUNTn(0));
	return 0;
}
/*
 * Set up timer interrupt, and return the current time in seconds.
 */
void mxs_nomatch_timer_init(struct mxs_sys_timer *timer)
{

	if (online_timer)
		return;

	online_timer = timer;

	cksrc_mxs_nomatch.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
				cksrc_mxs_nomatch.shift);
	ckevt_timrot.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
				ckevt_timrot.shift);
	ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot);
	ckevt_timrot.max_delta_ns = clockevent_delta2ns(0xFFF, &ckevt_timrot);
	ckevt_timrot.cpumask = cpumask_of(0);

	/* clear two timers */
	__raw_writel(0, online_timer->base + HW_TIMROT_TIMCOUNTn(0));
	__raw_writel(0, online_timer->base + HW_TIMROT_TIMCOUNTn(1));

	/* configure them */
	__raw_writel(
		(8 << BP_TIMROT_TIMCTRLn_SELECT) |  /* 32 kHz */
		BM_TIMROT_TIMCTRLn_RELOAD |
		BM_TIMROT_TIMCTRLn_UPDATE |
		BM_TIMROT_TIMCTRLn_IRQ_EN,
			online_timer->base + HW_TIMROT_TIMCTRLn(0));
	__raw_writel(
		(8 << BP_TIMROT_TIMCTRLn_SELECT) |  /* 32 kHz */
		BM_TIMROT_TIMCTRLn_RELOAD |
		BM_TIMROT_TIMCTRLn_UPDATE |
		BM_TIMROT_TIMCTRLn_IRQ_EN,
			online_timer->base + HW_TIMROT_TIMCTRLn(1));

	__raw_writel(CLOCK_TICK_RATE / HZ - 1,
			online_timer->base + HW_TIMROT_TIMCOUNTn(0));
	__raw_writel(0xFFFF, online_timer->base + HW_TIMROT_TIMCOUNTn(1));

	setup_irq(IRQ_TIMER0, &mxs_nomatch_timer_irq);

	clocksource_register(&cksrc_mxs_nomatch);
	clockevents_register_device(&ckevt_timrot);
}
void mxs_nomatch_resume_timer(void)
{
	__raw_writel(BM_TIMROT_ROTCTRL_SFTRST | BM_TIMROT_ROTCTRL_CLKGATE,
			online_timer->base  + HW_TIMROT_ROTCTRL_CLR);
	__raw_writel(
		8 << BP_TIMROT_TIMCTRLn_SELECT |  /* 32 kHz */
		BM_TIMROT_TIMCTRLn_RELOAD |
		BM_TIMROT_TIMCTRLn_UPDATE |
		BM_TIMROT_TIMCTRLn_IRQ_EN,
			online_timer->base  + HW_TIMROT_TIMCTRLn(0));
	__raw_writel(
		8 << BP_TIMROT_TIMCTRLn_SELECT |  /* 32 kHz */
		BM_TIMROT_TIMCTRLn_RELOAD |
		BM_TIMROT_TIMCTRLn_UPDATE |
		BM_TIMROT_TIMCTRLn_IRQ_EN,
			online_timer->base  + HW_TIMROT_TIMCTRLn(1));
	__raw_writel(CLOCK_TICK_RATE / HZ - 1,
			online_timer->base  + HW_TIMROT_TIMCOUNTn(0));
	__raw_writel(0xFFFF, online_timer->base  + HW_TIMROT_TIMCOUNTn(1));
}
Exemple #7
0
void __init mxs_timer_init(int irq)
{
	struct clk *timer_clk;

	timer_clk = clk_get_sys("timrot", NULL);
	if (IS_ERR(timer_clk)) {
		pr_err("%s: failed to get clk\n", __func__);
		return;
	}

	clk_prepare_enable(timer_clk);

	/*
	 * Initialize timers to a known state
	 */
	mxs_reset_block(mxs_timrot_base + HW_TIMROT_ROTCTRL);

	/* get timrot version */
	timrot_major_version = __raw_readl(mxs_timrot_base +
				(cpu_is_mx23() ? MX23_TIMROT_VERSION_OFFSET :
						MX28_TIMROT_VERSION_OFFSET));
	timrot_major_version >>= BP_TIMROT_MAJOR_VERSION;

	/* one for clock_event */
	__raw_writel((timrot_is_v1() ?
			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
			BV_TIMROTv2_TIMCTRLn_SELECT__32KHZ_XTAL) |
			BM_TIMROT_TIMCTRLn_UPDATE |
			BM_TIMROT_TIMCTRLn_IRQ_EN,
			mxs_timrot_base + HW_TIMROT_TIMCTRLn(0));

	/* another for clocksource */
	__raw_writel((timrot_is_v1() ?
			BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL :
			BV_TIMROTv2_TIMCTRLn_SELECT__32KHZ_XTAL) |
			BM_TIMROT_TIMCTRLn_RELOAD,
			mxs_timrot_base + HW_TIMROT_TIMCTRLn(1));

	/* set clocksource timer fixed count to the maximum */
	if (timrot_is_v1())
		__raw_writel(0xffff,
			mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
	else
		__raw_writel(0xffffffff,
			mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));

	/* init and register the timer to the framework */
	mxs_clocksource_init(timer_clk);
	mxs_clockevent_init(timer_clk);

	/* Make irqs happen */
	setup_irq(irq, &mxs_timer_irq);
}
Exemple #8
0
static void mxs_set_mode(enum clock_event_mode mode,
				struct clock_event_device *evt)
{
	/* Disable interrupt in timer module */
	timrot_irq_disable();

	if (mode != mxs_clockevent_mode) {
		/* Set event time into the furthest future */
		if (timrot_is_v1())
			__raw_writel(0xffff,
				mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1));
		else
			__raw_writel(0xffffffff,
				mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1));

		/* Clear pending interrupt */
		timrot_irq_acknowledge();
	}

#ifdef DEBUG
	pr_info("%s: changing mode from %s to %s\n", __func__,
		clock_event_mode_label[mxs_clockevent_mode],
		clock_event_mode_label[mode]);
#endif /* DEBUG */

	/* Remember timer mode */
	mxs_clockevent_mode = mode;

	switch (mode) {
	case CLOCK_EVT_MODE_PERIODIC:
		pr_err("%s: Periodic mode is not implemented\n", __func__);
		break;
	case CLOCK_EVT_MODE_ONESHOT:
		timrot_irq_enable();
		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;
	}
}
Exemple #9
0
void imx233_timrot_setup(unsigned timer_nr, bool reload, unsigned count,
    unsigned src, unsigned prescale, bool polarity, imx233_timer_fn_t fn)
{
    int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
    /* only enable interrupt if function is set */
    bool irq = fn != NULL;
    timer_fns[timer_nr] = fn;

    /* make sure we start from stop state */
    HW_TIMROT_TIMCTRLn(timer_nr) = BF_OR2(TIMROT_TIMCTRLn,
        SELECT(BV_TIMROT_TIMCTRLn_SELECT__NEVER_TICK), UPDATE(1));
    /* write count and take effect immediately with UPDATE
     * manual says count-1 for reload timers */
    HW_TIMROT_TIMCOUNTn(timer_nr) = reload ? count - 1 : count;
    /* start timer */
    HW_TIMROT_TIMCTRLn(timer_nr) = BF_OR6(TIMROT_TIMCTRLn, SELECT(src),
        PRESCALE(prescale), POLARITY(polarity), RELOAD(reload), IRQ(irq),
        IRQ_EN(irq));
    imx233_icoll_enable_interrupt(INT_SRC_TIMER(timer_nr), irq);

    restore_interrupt(oldstatus);
}
Exemple #10
0
static cycle_t timrotv1_get_cycles(struct clocksource *cs)
{
	return ~((__raw_readl(mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1))
			& 0xffff0000) >> 16);
}
static cycle_t mxs_nomatch_clock_read(struct clocksource *cs)
{
	return ~((__raw_readl(online_timer->base + HW_TIMROT_TIMCOUNTn(1))
				& 0xFFFF0000) >> 16);
}