Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+44 -1
+19
Documentation/devicetree/bindings/rtc/dw-apb.txt
··· 5 5 - reg: physical base address of the controller and length of memory mapped 6 6 region. 7 7 - interrupts: IRQ line for the timer. 8 + - either clocks+clock-names or clock-frequency properties 9 + 10 + Optional properties: 11 + - clocks : list of clock specifiers, corresponding to entries in 12 + the clock-names property; 13 + - clock-names : should contain "timer" and "pclk" entries, matching entries 14 + in the clocks property. 8 15 - clock-frequency: The frequency in HZ of the timer. 9 16 - clock-freq: For backwards compatibility with picoxcell 17 + 18 + If using the clock specifiers, the pclk clock is optional, as not all 19 + systems may use one. 20 + 10 21 11 22 Example: 12 23 ··· 33 22 interrupts = <0 169 4>; 34 23 clock-frequency = <200000000>; 35 24 reg = <0xffd00000 0x1000>; 25 + }; 26 + 27 + timer3: timer@ffe00000 { 28 + compatible = "snps,dw-apb-timer-osc"; 29 + interrupts = <0 170 4>; 30 + reg = <0xffe00000 0x1000>; 31 + clocks = <&timer_clk>, <&timer_pclk>; 32 + clock-names = "timer", "pclk"; 36 33 };
+25 -1
drivers/clocksource/dw_apb_timer_of.c
··· 20 20 #include <linux/of.h> 21 21 #include <linux/of_address.h> 22 22 #include <linux/of_irq.h> 23 + #include <linux/clk.h> 23 24 24 25 #include <asm/mach/time.h> 25 26 #include <asm/sched_clock.h> ··· 28 27 static void timer_get_base_and_rate(struct device_node *np, 29 28 void __iomem **base, u32 *rate) 30 29 { 30 + struct clk *timer_clk; 31 + struct clk *pclk; 32 + 31 33 *base = of_iomap(np, 0); 32 34 33 35 if (!*base) 34 36 panic("Unable to map regs for %s", np->name); 35 37 38 + /* 39 + * Not all implementations use a periphal clock, so don't panic 40 + * if it's not present 41 + */ 42 + pclk = of_clk_get_by_name(np, "pclk"); 43 + if (!IS_ERR(pclk)) 44 + if (clk_prepare_enable(pclk)) 45 + pr_warn("pclk for %s is present, but could not be activated\n", 46 + np->name); 47 + 48 + timer_clk = of_clk_get_by_name(np, "timer"); 49 + if (IS_ERR(timer_clk)) 50 + goto try_clock_freq; 51 + 52 + if (!clk_prepare_enable(timer_clk)) { 53 + *rate = clk_get_rate(timer_clk); 54 + return; 55 + } 56 + 57 + try_clock_freq: 36 58 if (of_property_read_u32(np, "clock-freq", rate) && 37 59 of_property_read_u32(np, "clock-frequency", rate)) 38 - panic("No clock-frequency property for %s", np->name); 60 + panic("No clock nor clock-frequency property for %s", np->name); 39 61 } 40 62 41 63 static void add_clockevent(struct device_node *event_timer)