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