static int __init lpc32xx_clockevent_init()

in timer-lpc32xx.c [220:285]


static int __init lpc32xx_clockevent_init(struct device_node *np)
{
	void __iomem *base;
	unsigned long rate;
	struct clk *clk;
	int ret, irq;

	clk = of_clk_get_by_name(np, "timerclk");
	if (IS_ERR(clk)) {
		pr_err("clock get failed (%ld)\n", PTR_ERR(clk));
		return PTR_ERR(clk);
	}

	ret = clk_prepare_enable(clk);
	if (ret) {
		pr_err("clock enable failed (%d)\n", ret);
		goto err_clk_enable;
	}

	base = of_iomap(np, 0);
	if (!base) {
		pr_err("unable to map registers\n");
		ret = -EADDRNOTAVAIL;
		goto err_iomap;
	}

	irq = irq_of_parse_and_map(np, 0);
	if (!irq) {
		pr_err("get irq failed\n");
		ret = -ENOENT;
		goto err_irq;
	}

	/*
	 * Disable timer and clear any pending interrupt (IR) on match
	 * channel 0 (MR0). Clear the prescaler as it's not used.
	 */
	writel_relaxed(0, base + LPC32XX_TIMER_TCR);
	writel_relaxed(0, base + LPC32XX_TIMER_PR);
	writel_relaxed(0, base + LPC32XX_TIMER_CTCR);
	writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR);

	rate = clk_get_rate(clk);
	lpc32xx_clk_event_ddata.base = base;
	lpc32xx_clk_event_ddata.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
	clockevents_config_and_register(&lpc32xx_clk_event_ddata.evtdev,
					rate, 1, -1);

	ret = request_irq(irq, lpc32xx_clock_event_handler,
			  IRQF_TIMER | IRQF_IRQPOLL, "lpc3220 clockevent",
			  &lpc32xx_clk_event_ddata);
	if (ret) {
		pr_err("request irq failed\n");
		goto err_irq;
	}

	return 0;

err_irq:
	iounmap(base);
err_iomap:
	clk_disable_unprepare(clk);
err_clk_enable:
	clk_put(clk);
	return ret;
}