/** * 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; } }
/** * 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; }
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; } }