示例#1
0
/**
 * ttc_set_mode - Sets the mode of timer
 *
 * @mode:	Mode to be set
 * @evt:	Address of clock event instance
 **/
static void ttc_set_mode(enum clock_event_mode mode,
					struct clock_event_device *evt)
{
	struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
	struct ttc_timer *timer = &ttce->ttc;
	u32 ctrl_reg;

	switch (mode) {
	case CLOCK_EVT_MODE_PERIODIC:
		ttc_set_interval(timer,
				DIV_ROUND_CLOSEST(clk_get_rate(ttce->ttc.clk),
					PRESCALE * HZ));
		break;
	case CLOCK_EVT_MODE_ONESHOT:
	case CLOCK_EVT_MODE_UNUSED:
	case CLOCK_EVT_MODE_SHUTDOWN:
		ctrl_reg = __raw_readl(timer->base_addr +
					TTC_CNT_CNTRL_OFFSET);
		ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK;
		__raw_writel(ctrl_reg,
				timer->base_addr + TTC_CNT_CNTRL_OFFSET);
		break;
	case CLOCK_EVT_MODE_RESUME:
		ctrl_reg = __raw_readl(timer->base_addr +
					TTC_CNT_CNTRL_OFFSET);
		ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK;
		__raw_writel(ctrl_reg,
				timer->base_addr + TTC_CNT_CNTRL_OFFSET);
		break;
	}
}
示例#2
0
/**
 * ttc_set_next_event - Sets the time interval for next event
 *
 * @cycles:	Timer interval ticks
 * @evt:	Address of clock event instance
 *
 * returns: Always 0 - success
 **/
static int ttc_set_next_event(unsigned long cycles,
					struct clock_event_device *evt)
{
	struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
	struct ttc_timer *timer = &ttce->ttc;

	ttc_set_interval(timer, cycles);
	return 0;
}
示例#3
0
static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
		unsigned long event, void *data)
{
	struct clk_notifier_data *ndata = data;
	struct ttc_timer *ttc = to_ttc_timer(nb);
	struct ttc_timer_clockevent *ttcce = container_of(ttc,
			struct ttc_timer_clockevent, ttc);

	switch (event) {
	case POST_RATE_CHANGE:
	{
		unsigned long flags;

		/*
		 * clockevents_update_freq should be called with IRQ disabled on
		 * the CPU the timer provides events for. The timer we use is
		 * common to both CPUs, not sure if we need to run on both
		 * cores.
		 */
		local_irq_save(flags);
		clockevents_update_freq(&ttcce->ce,
				ndata->new_rate / PRESCALE);
		local_irq_restore(flags);

		/* update cached frequency */
		ttc->freq = ndata->new_rate;

		if (ttcce->ce.mode == CLOCK_EVT_MODE_PERIODIC)
			ttc_set_interval(ttc, DIV_ROUND_CLOSEST(ttc->freq,
						PRESCALE * HZ));

		/* fall through */
	}
	case PRE_RATE_CHANGE:
	case ABORT_RATE_CHANGE:
	default:
		return NOTIFY_DONE;
	}
}