Exemplo n.º 1
0
static void
kw_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
{
	unsigned long flags;

	local_irq_save(flags);

	if (mode == CLOCK_EVT_MODE_PERIODIC) {
		/*
		 * Setup latch cycles in timer and enable reload interrupt.
		 */
		MV_REG_WRITE(CNTMR_RELOAD_REG(CLOCKEVENT), ((mvBoardTclkGet() + HZ/2) / HZ));
		MV_REG_WRITE(CNTMR_VAL_REG(CLOCKEVENT), ((mvBoardTclkGet() + HZ/2) / HZ));
		MV_REG_BIT_SET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKEVENT));
		MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKEVENT) |
					  TIMER_EN(CLOCKEVENT));
	} else {
		/*
		 * Disable timer and interrupt
		 */
		MV_REG_BIT_RESET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKEVENT));
		MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(CLOCKEVENT));
		MV_REG_BIT_RESET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKEVENT) |
					  TIMER_EN(CLOCKEVENT));
	}

	local_irq_restore(flags);
}
Exemplo n.º 2
0
static int
kw_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
{
	unsigned long flags;

	if (delta == 0)
		return -ETIME;

	local_irq_save(flags);

	/*
	 * Clear and enable timer interrupt bit
	 */
	MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(CLOCKEVENT));
	MV_REG_BIT_SET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKEVENT));

	/*
	 * Setup new timer value
	 */
	MV_REG_WRITE(CNTMR_VAL_REG(CLOCKEVENT), delta);

	/*
	 * Disable auto reload and kickoff the timer
	 */
	MV_REG_BIT_RESET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKEVENT));
	MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_EN(CLOCKEVENT));

	local_irq_restore(flags);

	return 0;
}
Exemplo n.º 3
0
int mv_enable_fc_events(void *fc_event_handler, unsigned long period_ns)
{
	unsigned long flags;
	uint64_t  clock_ticks = period_ns;

	if (fc_event_handler == 0)
		return -1;

	local_irq_save(flags);

	mv_fc_event_handler = fc_event_handler;

	clock_ticks *= kw_clkevt.mult;
	clock_ticks >>= kw_clkevt.shift;

	/* Setup timer value */
	MV_REG_WRITE(CNTMR_RELOAD_REG(FCTRLEVENT), (unsigned long)clock_ticks);
	MV_REG_WRITE(CNTMR_VAL_REG(FCTRLEVENT), (unsigned long)clock_ticks);

	/* Enable periodic timer and timer interrupt */
	MV_REG_BIT_SET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(FCTRLEVENT));
	MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(FCTRLEVENT) | TIMER_EN(FCTRLEVENT));

	fc_disabled = 0;

	local_irq_restore(flags);

	return 0;
}
Exemplo n.º 4
0
static irqreturn_t kw_timer_interrupt(int irq, void *dev_id)
{
	unsigned long irq_cause = MV_REG_READ(BRIDGE_INT_CAUSE_REG);

	/* Handle FC events if any */
	if (irq_cause & BRIDGE_INT_TIMER(FCTRLEVENT)) {
		MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(FCTRLEVENT));
		if (mv_fc_event_handler)
			mv_fc_event_handler();
	}

	/*
	 * Clear clock event cause bit and do event
	 */
	if (irq_cause & BRIDGE_INT_TIMER(CLOCKEVENT)) {
		MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(CLOCKEVENT));
		kw_clkevt.event_handler(&kw_clkevt);
		mv_leds_hearbeat();
	}

	return IRQ_HANDLED;
}
Exemplo n.º 5
0
void mv_disable_fc_events(void)
{
	unsigned long flags;

	local_irq_save(flags);

	/* Disable timer */
	MV_REG_BIT_RESET(CNTMR_CTRL_REG, TIMER_EN(FCTRLEVENT));
	MV_REG_BIT_RESET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(FCTRLEVENT));

	/* Clear and disable interrupt */
	MV_REG_WRITE(BRIDGE_INT_CAUSE_REG, ~BRIDGE_INT_TIMER(FCTRLEVENT));
	MV_REG_BIT_RESET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(FCTRLEVENT));

	fc_disabled = 1;

	local_irq_restore(flags);
}
Exemplo n.º 6
0
static void mv_init_timer(void)
{
	/*
	 * Setup clocksource free running timer (no interrupt on reload)
	 */
 	MV_REG_WRITE(CNTMR_VAL_REG(CLOCKSOURCE), 0xffffffff);
	MV_REG_WRITE(CNTMR_RELOAD_REG(CLOCKSOURCE), 0xffffffff);
	MV_REG_BIT_RESET(BRIDGE_INT_MASK_REG, BRIDGE_INT_TIMER(CLOCKSOURCE));
	MV_REG_BIT_SET(CNTMR_CTRL_REG, TIMER_RELOAD_EN(CLOCKSOURCE) |
				  TIMER_EN(CLOCKSOURCE));

	kw_clkevt.cpumask = cpumask_of(0);

	/*
	 * Register clocksource
	 */
	kw_clksrc.mult =
		clocksource_hz2mult(mvBoardTclkGet(), kw_clksrc.shift);

	clocksource_register(&kw_clksrc);

	/*
	 * Connect and enable tick handler
	 */
	setup_irq(IRQ_BRIDGE, &kw_timer_irq);

	/*
	 * Register clockevent
	 */
	kw_clkevt.mult =
		div_sc(mvBoardTclkGet(), NSEC_PER_SEC, kw_clkevt.shift);
	kw_clkevt.max_delta_ns =
		clockevent_delta2ns(0xfffffffe, &kw_clkevt);
	kw_clkevt.min_delta_ns =
		clockevent_delta2ns(1, &kw_clkevt);

	/*
	 * Setup clockevent timer (interrupt-driven.)
	 */
	clockevents_register_device(&kw_clkevt);
}