diff options
Diffstat (limited to 'arch/arm/kernel/smp_twd.c')
-rw-r--r-- | arch/arm/kernel/smp_twd.c | 53 |
1 files changed, 19 insertions, 34 deletions
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 49f335d301ba..ae0c7bb39ae8 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c | |||
@@ -31,7 +31,6 @@ static void __iomem *twd_base; | |||
31 | 31 | ||
32 | static struct clk *twd_clk; | 32 | static struct clk *twd_clk; |
33 | static unsigned long twd_timer_rate; | 33 | static unsigned long twd_timer_rate; |
34 | static bool common_setup_called; | ||
35 | static DEFINE_PER_CPU(bool, percpu_setup_called); | 34 | static DEFINE_PER_CPU(bool, percpu_setup_called); |
36 | 35 | ||
37 | static struct clock_event_device __percpu **twd_evt; | 36 | static struct clock_event_device __percpu **twd_evt; |
@@ -239,25 +238,28 @@ static irqreturn_t twd_handler(int irq, void *dev_id) | |||
239 | return IRQ_NONE; | 238 | return IRQ_NONE; |
240 | } | 239 | } |
241 | 240 | ||
242 | static struct clk *twd_get_clock(void) | 241 | static void twd_get_clock(struct device_node *np) |
243 | { | 242 | { |
244 | struct clk *clk; | ||
245 | int err; | 243 | int err; |
246 | 244 | ||
247 | clk = clk_get_sys("smp_twd", NULL); | 245 | if (np) |
248 | if (IS_ERR(clk)) { | 246 | twd_clk = of_clk_get(np, 0); |
249 | pr_err("smp_twd: clock not found: %d\n", (int)PTR_ERR(clk)); | 247 | else |
250 | return clk; | 248 | twd_clk = clk_get_sys("smp_twd", NULL); |
249 | |||
250 | if (IS_ERR(twd_clk)) { | ||
251 | pr_err("smp_twd: clock not found %d\n", (int) PTR_ERR(twd_clk)); | ||
252 | return; | ||
251 | } | 253 | } |
252 | 254 | ||
253 | err = clk_prepare_enable(clk); | 255 | err = clk_prepare_enable(twd_clk); |
254 | if (err) { | 256 | if (err) { |
255 | pr_err("smp_twd: clock failed to prepare+enable: %d\n", err); | 257 | pr_err("smp_twd: clock failed to prepare+enable: %d\n", err); |
256 | clk_put(clk); | 258 | clk_put(twd_clk); |
257 | return ERR_PTR(err); | 259 | return; |
258 | } | 260 | } |
259 | 261 | ||
260 | return clk; | 262 | twd_timer_rate = clk_get_rate(twd_clk); |
261 | } | 263 | } |
262 | 264 | ||
263 | /* | 265 | /* |
@@ -280,26 +282,7 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk) | |||
280 | } | 282 | } |
281 | per_cpu(percpu_setup_called, cpu) = true; | 283 | per_cpu(percpu_setup_called, cpu) = true; |
282 | 284 | ||
283 | /* | 285 | 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 | 286 | ||
304 | /* | 287 | /* |
305 | * The following is done once per CPU the first time .setup() is | 288 | * The following is done once per CPU the first time .setup() is |
@@ -330,7 +313,7 @@ static struct local_timer_ops twd_lt_ops __cpuinitdata = { | |||
330 | .stop = twd_timer_stop, | 313 | .stop = twd_timer_stop, |
331 | }; | 314 | }; |
332 | 315 | ||
333 | static int __init twd_local_timer_common_register(void) | 316 | static int __init twd_local_timer_common_register(struct device_node *np) |
334 | { | 317 | { |
335 | int err; | 318 | int err; |
336 | 319 | ||
@@ -350,6 +333,8 @@ static int __init twd_local_timer_common_register(void) | |||
350 | if (err) | 333 | if (err) |
351 | goto out_irq; | 334 | goto out_irq; |
352 | 335 | ||
336 | twd_get_clock(np); | ||
337 | |||
353 | return 0; | 338 | return 0; |
354 | 339 | ||
355 | out_irq: | 340 | out_irq: |
@@ -373,7 +358,7 @@ int __init twd_local_timer_register(struct twd_local_timer *tlt) | |||
373 | if (!twd_base) | 358 | if (!twd_base) |
374 | return -ENOMEM; | 359 | return -ENOMEM; |
375 | 360 | ||
376 | return twd_local_timer_common_register(); | 361 | return twd_local_timer_common_register(NULL); |
377 | } | 362 | } |
378 | 363 | ||
379 | #ifdef CONFIG_OF | 364 | #ifdef CONFIG_OF |
@@ -405,7 +390,7 @@ void __init twd_local_timer_of_register(void) | |||
405 | goto out; | 390 | goto out; |
406 | } | 391 | } |
407 | 392 | ||
408 | err = twd_local_timer_common_register(); | 393 | err = twd_local_timer_common_register(np); |
409 | 394 | ||
410 | out: | 395 | out: |
411 | WARN(err, "twd_local_timer_of_register failed (%d)\n", err); | 396 | WARN(err, "twd_local_timer_of_register failed (%d)\n", err); |