diff options
author | Heiko Stuebner <heiko@sntech.de> | 2013-06-04 05:37:36 -0400 |
---|---|---|
committer | Heiko Stuebner <heiko@sntech.de> | 2013-06-12 07:47:22 -0400 |
commit | a8b447f2bbbba737ff4478f498d7f83c75a9461b (patch) | |
tree | b68792f27524250d1a9d3267ef3cf80f7a3cc946 | |
parent | a1198f83407ae3421f3f58355a0f296d5ea6249c (diff) |
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>
-rw-r--r-- | Documentation/devicetree/bindings/rtc/dw-apb.txt | 19 | ||||
-rw-r--r-- | drivers/clocksource/dw_apb_timer_of.c | 26 |
2 files changed, 44 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/rtc/dw-apb.txt b/Documentation/devicetree/bindings/rtc/dw-apb.txt index 93e2b0f048e6..eb2327b2bdb3 100644 --- a/Documentation/devicetree/bindings/rtc/dw-apb.txt +++ b/Documentation/devicetree/bindings/rtc/dw-apb.txt | |||
@@ -5,9 +5,20 @@ Required properties: | |||
5 | - reg: physical base address of the controller and length of memory mapped | 5 | - reg: physical base address of the controller and length of memory mapped |
6 | region. | 6 | region. |
7 | - interrupts: IRQ line for the timer. | 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 | - clock-frequency: The frequency in HZ of the timer. | 15 | - clock-frequency: The frequency in HZ of the timer. |
9 | - clock-freq: For backwards compatibility with picoxcell | 16 | - clock-freq: For backwards compatibility with picoxcell |
10 | 17 | ||
18 | If using the clock specifiers, the pclk clock is optional, as not all | ||
19 | systems may use one. | ||
20 | |||
21 | |||
11 | Example: | 22 | Example: |
12 | 23 | ||
13 | timer1: timer@ffc09000 { | 24 | timer1: timer@ffc09000 { |
@@ -23,3 +34,11 @@ Example: | |||
23 | clock-frequency = <200000000>; | 34 | clock-frequency = <200000000>; |
24 | reg = <0xffd00000 0x1000>; | 35 | reg = <0xffd00000 0x1000>; |
25 | }; | 36 | }; |
37 | |||
38 | timer3: timer@ffe00000 { | ||
39 | compatible = "snps,dw-apb-timer-osc"; | ||
40 | interrupts = <0 170 4>; | ||
41 | reg = <0xffe00000 0x1000>; | ||
42 | clocks = <&timer_clk>, <&timer_pclk>; | ||
43 | clock-names = "timer", "pclk"; | ||
44 | }; | ||
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index d6c0fda76a7e..1964f8716966 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/of_address.h> | 21 | #include <linux/of_address.h> |
22 | #include <linux/of_irq.h> | 22 | #include <linux/of_irq.h> |
23 | #include <linux/clk.h> | ||
23 | 24 | ||
24 | #include <asm/mach/time.h> | 25 | #include <asm/mach/time.h> |
25 | #include <asm/sched_clock.h> | 26 | #include <asm/sched_clock.h> |
@@ -27,14 +28,37 @@ | |||
27 | static void timer_get_base_and_rate(struct device_node *np, | 28 | static void timer_get_base_and_rate(struct device_node *np, |
28 | void __iomem **base, u32 *rate) | 29 | void __iomem **base, u32 *rate) |
29 | { | 30 | { |
31 | struct clk *timer_clk; | ||
32 | struct clk *pclk; | ||
33 | |||
30 | *base = of_iomap(np, 0); | 34 | *base = of_iomap(np, 0); |
31 | 35 | ||
32 | if (!*base) | 36 | if (!*base) |
33 | panic("Unable to map regs for %s", np->name); | 37 | panic("Unable to map regs for %s", np->name); |
34 | 38 | ||
39 | /* | ||
40 | * Not all implementations use a periphal clock, so don't panic | ||
41 | * if it's not present | ||
42 | */ | ||
43 | pclk = of_clk_get_by_name(np, "pclk"); | ||
44 | if (!IS_ERR(pclk)) | ||
45 | if (clk_prepare_enable(pclk)) | ||
46 | pr_warn("pclk for %s is present, but could not be activated\n", | ||
47 | np->name); | ||
48 | |||
49 | timer_clk = of_clk_get_by_name(np, "timer"); | ||
50 | if (IS_ERR(timer_clk)) | ||
51 | goto try_clock_freq; | ||
52 | |||
53 | if (!clk_prepare_enable(timer_clk)) { | ||
54 | *rate = clk_get_rate(timer_clk); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | try_clock_freq: | ||
35 | if (of_property_read_u32(np, "clock-freq", rate) && | 59 | if (of_property_read_u32(np, "clock-freq", rate) && |
36 | of_property_read_u32(np, "clock-frequency", rate)) | 60 | of_property_read_u32(np, "clock-frequency", rate)) |
37 | panic("No clock-frequency property for %s", np->name); | 61 | panic("No clock nor clock-frequency property for %s", np->name); |
38 | } | 62 | } |
39 | 63 | ||
40 | static void add_clockevent(struct device_node *event_timer) | 64 | static void add_clockevent(struct device_node *event_timer) |