static int __init mchp_pit64b_dt_init_timer()

in timer-microchip-pit64b.c [418:489]


static int __init mchp_pit64b_dt_init_timer(struct device_node *node,
					    bool clkevt)
{
	u32 freq = clkevt ? MCHP_PIT64B_DEF_CE_FREQ : MCHP_PIT64B_DEF_CS_FREQ;
	struct mchp_pit64b_timer timer;
	unsigned long clk_rate;
	u32 irq = 0;
	int ret;

	/* Parse DT node. */
	timer.pclk = of_clk_get_by_name(node, "pclk");
	if (IS_ERR(timer.pclk))
		return PTR_ERR(timer.pclk);

	timer.gclk = of_clk_get_by_name(node, "gclk");
	if (IS_ERR(timer.gclk))
		return PTR_ERR(timer.gclk);

	timer.base = of_iomap(node, 0);
	if (!timer.base)
		return -ENXIO;

	if (clkevt) {
		irq = irq_of_parse_and_map(node, 0);
		if (!irq) {
			ret = -ENODEV;
			goto io_unmap;
		}
	}

	/* Initialize mode (prescaler + SGCK bit). To be used at runtime. */
	ret = mchp_pit64b_init_mode(&timer, freq);
	if (ret)
		goto irq_unmap;

	ret = clk_prepare_enable(timer.pclk);
	if (ret)
		goto irq_unmap;

	if (timer.mode & MCHP_PIT64B_MR_SGCLK) {
		ret = clk_prepare_enable(timer.gclk);
		if (ret)
			goto pclk_unprepare;

		clk_rate = clk_get_rate(timer.gclk);
	} else {
		clk_rate = clk_get_rate(timer.pclk);
	}
	clk_rate = clk_rate / (MCHP_PIT64B_MODE_TO_PRES(timer.mode) + 1);

	if (clkevt)
		ret = mchp_pit64b_init_clkevt(&timer, clk_rate, irq);
	else
		ret = mchp_pit64b_init_clksrc(&timer, clk_rate);

	if (ret)
		goto gclk_unprepare;

	return 0;

gclk_unprepare:
	if (timer.mode & MCHP_PIT64B_MR_SGCLK)
		clk_disable_unprepare(timer.gclk);
pclk_unprepare:
	clk_disable_unprepare(timer.pclk);
irq_unmap:
	irq_dispose_mapping(irq);
io_unmap:
	iounmap(timer.base);

	return ret;
}