diff options
Diffstat (limited to 'arch/arm/kernel/smp_twd.c')
-rw-r--r-- | arch/arm/kernel/smp_twd.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index f0575610b17e..a9783947c086 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c | |||
@@ -10,8 +10,10 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/clk.h> | ||
13 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
14 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/err.h> | ||
15 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
16 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
17 | #include <linux/clockchips.h> | 19 | #include <linux/clockchips.h> |
@@ -25,6 +27,7 @@ | |||
25 | /* set up by the platform code */ | 27 | /* set up by the platform code */ |
26 | void __iomem *twd_base; | 28 | void __iomem *twd_base; |
27 | 29 | ||
30 | static struct clk *twd_clk; | ||
28 | static unsigned long twd_timer_rate; | 31 | static unsigned long twd_timer_rate; |
29 | 32 | ||
30 | static struct clock_event_device __percpu **twd_evt; | 33 | static struct clock_event_device __percpu **twd_evt; |
@@ -140,6 +143,35 @@ static irqreturn_t twd_handler(int irq, void *dev_id) | |||
140 | return IRQ_NONE; | 143 | return IRQ_NONE; |
141 | } | 144 | } |
142 | 145 | ||
146 | static struct clk *twd_get_clock(void) | ||
147 | { | ||
148 | struct clk *clk; | ||
149 | int err; | ||
150 | |||
151 | clk = clk_get_sys("smp_twd", NULL); | ||
152 | if (IS_ERR(clk)) { | ||
153 | pr_err("smp_twd: clock not found: %d\n", (int)PTR_ERR(clk)); | ||
154 | return clk; | ||
155 | } | ||
156 | |||
157 | err = clk_prepare(clk); | ||
158 | if (err) { | ||
159 | pr_err("smp_twd: clock failed to prepare: %d\n", err); | ||
160 | clk_put(clk); | ||
161 | return ERR_PTR(err); | ||
162 | } | ||
163 | |||
164 | err = clk_enable(clk); | ||
165 | if (err) { | ||
166 | pr_err("smp_twd: clock failed to enable: %d\n", err); | ||
167 | clk_unprepare(clk); | ||
168 | clk_put(clk); | ||
169 | return ERR_PTR(err); | ||
170 | } | ||
171 | |||
172 | return clk; | ||
173 | } | ||
174 | |||
143 | /* | 175 | /* |
144 | * Setup the local clock events for a CPU. | 176 | * Setup the local clock events for a CPU. |
145 | */ | 177 | */ |
@@ -165,7 +197,13 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) | |||
165 | } | 197 | } |
166 | } | 198 | } |
167 | 199 | ||
168 | twd_calibrate_rate(); | 200 | if (!twd_clk) |
201 | twd_clk = twd_get_clock(); | ||
202 | |||
203 | if (!IS_ERR_OR_NULL(twd_clk)) | ||
204 | twd_timer_rate = clk_get_rate(twd_clk); | ||
205 | else | ||
206 | twd_calibrate_rate(); | ||
169 | 207 | ||
170 | clk->name = "local_timer"; | 208 | clk->name = "local_timer"; |
171 | clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | | 209 | clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | |