diff options
author | Heiko Stuebner <heiko@sntech.de> | 2013-06-04 05:37:02 -0400 |
---|---|---|
committer | Heiko Stuebner <heiko@sntech.de> | 2013-06-12 07:47:13 -0400 |
commit | a1198f83407ae3421f3f58355a0f296d5ea6249c (patch) | |
tree | 6760cab93aa90b7456917923315632b81c7e0b5d /drivers/clocksource/dw_apb_timer_of.c | |
parent | e4aa937ec75df0eea0bee03bffa3303ad36c986b (diff) |
clocksource: dw_apb_timer_of: enable the use the clocksource as sched clock
Currently the dw_apb_timer always expects a separate special timer to be
availbable for the sched_clock. Some devices using dw_apb_timers do not
have this sptimer but can use the clocksource as sched_clock instead.
Therefore enable the driver to distiguish between devices with and without
sptimer based on the devicetree data and select the correct timer as
sched_clock.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Jamie Iles <jamie@jamieiles.com>
Diffstat (limited to 'drivers/clocksource/dw_apb_timer_of.c')
-rw-r--r-- | drivers/clocksource/dw_apb_timer_of.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index ab09ed3742ee..d6c0fda76a7e 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c | |||
@@ -57,6 +57,9 @@ static void add_clockevent(struct device_node *event_timer) | |||
57 | dw_apb_clockevent_register(ced); | 57 | dw_apb_clockevent_register(ced); |
58 | } | 58 | } |
59 | 59 | ||
60 | static void __iomem *sched_io_base; | ||
61 | static u32 sched_rate; | ||
62 | |||
60 | static void add_clocksource(struct device_node *source_timer) | 63 | static void add_clocksource(struct device_node *source_timer) |
61 | { | 64 | { |
62 | void __iomem *iobase; | 65 | void __iomem *iobase; |
@@ -71,9 +74,15 @@ static void add_clocksource(struct device_node *source_timer) | |||
71 | 74 | ||
72 | dw_apb_clocksource_start(cs); | 75 | dw_apb_clocksource_start(cs); |
73 | dw_apb_clocksource_register(cs); | 76 | dw_apb_clocksource_register(cs); |
74 | } | ||
75 | 77 | ||
76 | static void __iomem *sched_io_base; | 78 | /* |
79 | * Fallback to use the clocksource as sched_clock if no separate | ||
80 | * timer is found. sched_io_base then points to the current_value | ||
81 | * register of the clocksource timer. | ||
82 | */ | ||
83 | sched_io_base = iobase + 0x04; | ||
84 | sched_rate = rate; | ||
85 | } | ||
77 | 86 | ||
78 | static u32 read_sched_clock(void) | 87 | static u32 read_sched_clock(void) |
79 | { | 88 | { |
@@ -89,16 +98,15 @@ static const struct of_device_id sptimer_ids[] __initconst = { | |||
89 | static void init_sched_clock(void) | 98 | static void init_sched_clock(void) |
90 | { | 99 | { |
91 | struct device_node *sched_timer; | 100 | struct device_node *sched_timer; |
92 | u32 rate; | ||
93 | 101 | ||
94 | sched_timer = of_find_matching_node(NULL, sptimer_ids); | 102 | sched_timer = of_find_matching_node(NULL, sptimer_ids); |
95 | if (!sched_timer) | 103 | if (sched_timer) { |
96 | panic("No RTC for sched clock to use"); | 104 | timer_get_base_and_rate(sched_timer, &sched_io_base, |
97 | 105 | &sched_rate); | |
98 | timer_get_base_and_rate(sched_timer, &sched_io_base, &rate); | 106 | of_node_put(sched_timer); |
99 | of_node_put(sched_timer); | 107 | } |
100 | 108 | ||
101 | setup_sched_clock(read_sched_clock, 32, rate); | 109 | setup_sched_clock(read_sched_clock, 32, sched_rate); |
102 | } | 110 | } |
103 | 111 | ||
104 | static const struct of_device_id osctimer_ids[] __initconst = { | 112 | static const struct of_device_id osctimer_ids[] __initconst = { |