in timer-integrator-ap.c [158:222]
static int __init integrator_ap_timer_init_of(struct device_node *node)
{
const char *path;
void __iomem *base;
int err;
int irq;
struct clk *clk;
unsigned long rate;
struct device_node *alias_node;
base = of_io_request_and_map(node, 0, "integrator-timer");
if (IS_ERR(base))
return PTR_ERR(base);
clk = of_clk_get(node, 0);
if (IS_ERR(clk)) {
pr_err("No clock for %pOFn\n", node);
return PTR_ERR(clk);
}
clk_prepare_enable(clk);
rate = clk_get_rate(clk);
writel(0, base + TIMER_CTRL);
err = of_property_read_string(of_aliases,
"arm,timer-primary", &path);
if (err) {
pr_warn("Failed to read property\n");
return err;
}
alias_node = of_find_node_by_path(path);
/*
* The pointer is used as an identifier not as a pointer, we
* can drop the refcount on the of__node immediately after
* getting it.
*/
of_node_put(alias_node);
if (node == alias_node)
/* The primary timer lacks IRQ, use as clocksource */
return integrator_clocksource_init(rate, base);
err = of_property_read_string(of_aliases,
"arm,timer-secondary", &path);
if (err) {
pr_warn("Failed to read property\n");
return err;
}
alias_node = of_find_node_by_path(path);
of_node_put(alias_node);
if (node == alias_node) {
/* The secondary timer will drive the clock event */
irq = irq_of_parse_and_map(node, 0);
return integrator_clockevent_init(rate, base, irq);
}
pr_info("Timer @%p unused\n", base);
clk_disable_unprepare(clk);
return 0;
}