static int __init ttc_setup_clockevent()

in timer-cadence-ttc.c [403:467]


static int __init ttc_setup_clockevent(struct clk *clk,
				       void __iomem *base, u32 irq)
{
	struct ttc_timer_clockevent *ttcce;
	int err;

	ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
	if (!ttcce)
		return -ENOMEM;

	ttcce->ttc.clk = clk;

	err = clk_prepare_enable(ttcce->ttc.clk);
	if (err)
		goto out_kfree;

	ttcce->ttc.clk_rate_change_nb.notifier_call =
		ttc_rate_change_clockevent_cb;
	ttcce->ttc.clk_rate_change_nb.next = NULL;

	err = clk_notifier_register(ttcce->ttc.clk,
				    &ttcce->ttc.clk_rate_change_nb);
	if (err) {
		pr_warn("Unable to register clock notifier.\n");
		goto out_kfree;
	}

	ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk);

	ttcce->ttc.base_addr = base;
	ttcce->ce.name = "ttc_clockevent";
	ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
	ttcce->ce.set_next_event = ttc_set_next_event;
	ttcce->ce.set_state_shutdown = ttc_shutdown;
	ttcce->ce.set_state_periodic = ttc_set_periodic;
	ttcce->ce.set_state_oneshot = ttc_shutdown;
	ttcce->ce.tick_resume = ttc_resume;
	ttcce->ce.rating = 200;
	ttcce->ce.irq = irq;
	ttcce->ce.cpumask = cpu_possible_mask;

	/*
	 * Setup the clock event timer to be an interval timer which
	 * is prescaled by 32 using the interval interrupt. Leave it
	 * disabled for now.
	 */
	writel_relaxed(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET);
	writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
		     ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
	writel_relaxed(0x1,  ttcce->ttc.base_addr + TTC_IER_OFFSET);

	err = request_irq(irq, ttc_clock_event_interrupt,
			  IRQF_TIMER, ttcce->ce.name, ttcce);
	if (err)
		goto out_kfree;

	clockevents_config_and_register(&ttcce->ce,
			ttcce->ttc.freq / PRESCALE, 1, 0xfffe);

	return 0;

out_kfree:
	kfree(ttcce);
	return err;
}