clocksource: dw_apb_timer_of: add clock-handling

Add the possibility to get the clock-frequency from a timer clock instead
of specifying it as dt property. Additionally also add the possibility
to also define a controlling periphal clock for the timer block.

The clock-frequency property is kept to act as fallback if no clocks
are specified.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Jamie Iles <jamie@jamieiles.com>
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index d6c0fda..1964f87 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -20,6 +20,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/clk.h>
 
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
@@ -27,14 +28,37 @@
 static void timer_get_base_and_rate(struct device_node *np,
 				    void __iomem **base, u32 *rate)
 {
+	struct clk *timer_clk;
+	struct clk *pclk;
+
 	*base = of_iomap(np, 0);
 
 	if (!*base)
 		panic("Unable to map regs for %s", np->name);
 
+	/*
+	 * Not all implementations use a periphal clock, so don't panic
+	 * if it's not present
+	 */
+	pclk = of_clk_get_by_name(np, "pclk");
+	if (!IS_ERR(pclk))
+		if (clk_prepare_enable(pclk))
+			pr_warn("pclk for %s is present, but could not be activated\n",
+				np->name);
+
+	timer_clk = of_clk_get_by_name(np, "timer");
+	if (IS_ERR(timer_clk))
+		goto try_clock_freq;
+
+	if (!clk_prepare_enable(timer_clk)) {
+		*rate = clk_get_rate(timer_clk);
+		return;
+	}
+
+try_clock_freq:
 	if (of_property_read_u32(np, "clock-freq", rate) &&
 		of_property_read_u32(np, "clock-frequency", rate))
-		panic("No clock-frequency property for %s", np->name);
+		panic("No clock nor clock-frequency property for %s", np->name);
 }
 
 static void add_clockevent(struct device_node *event_timer)