diff options
Diffstat (limited to 'arch/arm/kernel/smp_twd.c')
-rw-r--r-- | arch/arm/kernel/smp_twd.c | 54 |
1 files changed, 19 insertions, 35 deletions
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 49f335d301ba..c092115d903a 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c | |||
@@ -24,14 +24,12 @@ | |||
24 | 24 | ||
25 | #include <asm/smp_twd.h> | 25 | #include <asm/smp_twd.h> |
26 | #include <asm/localtimer.h> | 26 | #include <asm/localtimer.h> |
27 | #include <asm/hardware/gic.h> | ||
28 | 27 | ||
29 | /* set up by the platform code */ | 28 | /* set up by the platform code */ |
30 | static void __iomem *twd_base; | 29 | static void __iomem *twd_base; |
31 | 30 | ||
32 | static struct clk *twd_clk; | 31 | static struct clk *twd_clk; |
33 | static unsigned long twd_timer_rate; | 32 | static unsigned long twd_timer_rate; |
34 | static bool common_setup_called; | ||
35 | static DEFINE_PER_CPU(bool, percpu_setup_called); | 33 | static DEFINE_PER_CPU(bool, percpu_setup_called); |
36 | 34 | ||
37 | static struct clock_event_device __percpu **twd_evt; | 35 | static struct clock_event_device __percpu **twd_evt; |
@@ -239,25 +237,28 @@ static irqreturn_t twd_handler(int irq, void *dev_id) | |||
239 | return IRQ_NONE; | 237 | return IRQ_NONE; |
240 | } | 238 | } |
241 | 239 | ||
242 | static struct clk *twd_get_clock(void) | 240 | static void twd_get_clock(struct device_node *np) |
243 | { | 241 | { |
244 | struct clk *clk; | ||
245 | int err; | 242 | int err; |
246 | 243 | ||
247 | clk = clk_get_sys("smp_twd", NULL); | 244 | if (np) |
248 | if (IS_ERR(clk)) { | 245 | twd_clk = of_clk_get(np, 0); |
249 | pr_err("smp_twd: clock not found: %d\n", (int)PTR_ERR(clk)); | 246 | else |
250 | return clk; | 247 | twd_clk = clk_get_sys("smp_twd", NULL); |
248 | |||
249 | if (IS_ERR(twd_clk)) { | ||
250 | pr_err("smp_twd: clock not found %d\n", (int) PTR_ERR(twd_clk)); | ||
251 | return; | ||
251 | } | 252 | } |
252 | 253 | ||
253 | err = clk_prepare_enable(clk); | 254 | err = clk_prepare_enable(twd_clk); |
254 | if (err) { | 255 | if (err) { |
255 | pr_err("smp_twd: clock failed to prepare+enable: %d\n", err); | 256 | pr_err("smp_twd: clock failed to prepare+enable: %d\n", err); |
256 | clk_put(clk); | 257 | clk_put(twd_clk); |
257 | return ERR_PTR(err); | 258 | return; |
258 | } | 259 | } |
259 | 260 | ||
260 | return clk; | 261 | twd_timer_rate = clk_get_rate(twd_clk); |
261 | } | 262 | } |
262 | 263 | ||
263 | /* | 264 | /* |
@@ -280,26 +281,7 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk) | |||
280 | } | 281 | } |
281 | per_cpu(percpu_setup_called, cpu) = true; | 282 | per_cpu(percpu_setup_called, cpu) = true; |
282 | 283 | ||
283 | /* | 284 | twd_calibrate_rate(); |
284 | * This stuff only need to be done once for the entire TWD cluster | ||
285 | * during the runtime of the system. | ||
286 | */ | ||
287 | if (!common_setup_called) { | ||
288 | twd_clk = twd_get_clock(); | ||
289 | |||
290 | /* | ||
291 | * We use IS_ERR_OR_NULL() here, because if the clock stubs | ||
292 | * are active we will get a valid clk reference which is | ||
293 | * however NULL and will return the rate 0. In that case we | ||
294 | * need to calibrate the rate instead. | ||
295 | */ | ||
296 | if (!IS_ERR_OR_NULL(twd_clk)) | ||
297 | twd_timer_rate = clk_get_rate(twd_clk); | ||
298 | else | ||
299 | twd_calibrate_rate(); | ||
300 | |||
301 | common_setup_called = true; | ||
302 | } | ||
303 | 285 | ||
304 | /* | 286 | /* |
305 | * The following is done once per CPU the first time .setup() is | 287 | * The following is done once per CPU the first time .setup() is |
@@ -330,7 +312,7 @@ static struct local_timer_ops twd_lt_ops __cpuinitdata = { | |||
330 | .stop = twd_timer_stop, | 312 | .stop = twd_timer_stop, |
331 | }; | 313 | }; |
332 | 314 | ||
333 | static int __init twd_local_timer_common_register(void) | 315 | static int __init twd_local_timer_common_register(struct device_node *np) |
334 | { | 316 | { |
335 | int err; | 317 | int err; |
336 | 318 | ||
@@ -350,6 +332,8 @@ static int __init twd_local_timer_common_register(void) | |||
350 | if (err) | 332 | if (err) |
351 | goto out_irq; | 333 | goto out_irq; |
352 | 334 | ||
335 | twd_get_clock(np); | ||
336 | |||
353 | return 0; | 337 | return 0; |
354 | 338 | ||
355 | out_irq: | 339 | out_irq: |
@@ -373,7 +357,7 @@ int __init twd_local_timer_register(struct twd_local_timer *tlt) | |||
373 | if (!twd_base) | 357 | if (!twd_base) |
374 | return -ENOMEM; | 358 | return -ENOMEM; |
375 | 359 | ||
376 | return twd_local_timer_common_register(); | 360 | return twd_local_timer_common_register(NULL); |
377 | } | 361 | } |
378 | 362 | ||
379 | #ifdef CONFIG_OF | 363 | #ifdef CONFIG_OF |
@@ -405,7 +389,7 @@ void __init twd_local_timer_of_register(void) | |||
405 | goto out; | 389 | goto out; |
406 | } | 390 | } |
407 | 391 | ||
408 | err = twd_local_timer_common_register(); | 392 | err = twd_local_timer_common_register(np); |
409 | 393 | ||
410 | out: | 394 | out: |
411 | WARN(err, "twd_local_timer_of_register failed (%d)\n", err); | 395 | WARN(err, "twd_local_timer_of_register failed (%d)\n", err); |