static int __init mps2_clockevent_init()

in mps2-timer.c [98:181]


static int __init mps2_clockevent_init(struct device_node *np)
{
	void __iomem *base;
	struct clk *clk = NULL;
	struct clockevent_mps2 *ce;
	u32 rate;
	int irq, ret;
	const char *name = "mps2-clkevt";

	ret = of_property_read_u32(np, "clock-frequency", &rate);
	if (ret) {
		clk = of_clk_get(np, 0);
		if (IS_ERR(clk)) {
			ret = PTR_ERR(clk);
			pr_err("failed to get clock for clockevent: %d\n", ret);
			goto out;
		}

		ret = clk_prepare_enable(clk);
		if (ret) {
			pr_err("failed to enable clock for clockevent: %d\n", ret);
			goto out_clk_put;
		}

		rate = clk_get_rate(clk);
	}

	base = of_iomap(np, 0);
	if (!base) {
		ret = -EADDRNOTAVAIL;
		pr_err("failed to map register for clockevent: %d\n", ret);
		goto out_clk_disable;
	}

	irq = irq_of_parse_and_map(np, 0);
	if (!irq) {
		ret = -ENOENT;
		pr_err("failed to get irq for clockevent: %d\n", ret);
		goto out_iounmap;
	}

	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
	if (!ce) {
		ret = -ENOMEM;
		goto out_iounmap;
	}

	ce->reg = base;
	ce->clock_count_per_tick = DIV_ROUND_CLOSEST(rate, HZ);
	ce->clkevt.irq = irq;
	ce->clkevt.name = name;
	ce->clkevt.rating = 200;
	ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
	ce->clkevt.cpumask = cpu_possible_mask;
	ce->clkevt.set_state_shutdown	= mps2_timer_shutdown;
	ce->clkevt.set_state_periodic	= mps2_timer_set_periodic;
	ce->clkevt.set_state_oneshot	= mps2_timer_shutdown;
	ce->clkevt.set_next_event	= mps2_timer_set_next_event;

	/* Ensure timer is disabled */
	writel_relaxed(0, base + TIMER_CTRL);

	ret = request_irq(irq, mps2_timer_interrupt, IRQF_TIMER, name, ce);
	if (ret) {
		pr_err("failed to request irq for clockevent: %d\n", ret);
		goto out_kfree;
	}

	clockevents_config_and_register(&ce->clkevt, rate, 0xf, 0xffffffff);

	return 0;

out_kfree:
	kfree(ce);
out_iounmap:
	iounmap(base);
out_clk_disable:
	/* clk_{disable, unprepare, put}() can handle NULL as a parameter */
	clk_disable_unprepare(clk);
out_clk_put:
	clk_put(clk);
out:
	return ret;
}