static int __init integrator_ap_timer_init_of()

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