diff options
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 105f8ffa66a8..9338f1ad6100 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/smp.h> | 14 | #include <linux/smp.h> |
15 | #include <linux/cpu.h> | 15 | #include <linux/cpu.h> |
16 | #include <linux/cpu_pm.h> | ||
16 | #include <linux/clockchips.h> | 17 | #include <linux/clockchips.h> |
17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
18 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
@@ -475,6 +476,33 @@ static struct notifier_block arch_timer_cpu_nb = { | |||
475 | .notifier_call = arch_timer_cpu_notify, | 476 | .notifier_call = arch_timer_cpu_notify, |
476 | }; | 477 | }; |
477 | 478 | ||
479 | #ifdef CONFIG_CPU_PM | ||
480 | static unsigned int saved_cntkctl; | ||
481 | static int arch_timer_cpu_pm_notify(struct notifier_block *self, | ||
482 | unsigned long action, void *hcpu) | ||
483 | { | ||
484 | if (action == CPU_PM_ENTER) | ||
485 | saved_cntkctl = arch_timer_get_cntkctl(); | ||
486 | else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) | ||
487 | arch_timer_set_cntkctl(saved_cntkctl); | ||
488 | return NOTIFY_OK; | ||
489 | } | ||
490 | |||
491 | static struct notifier_block arch_timer_cpu_pm_notifier = { | ||
492 | .notifier_call = arch_timer_cpu_pm_notify, | ||
493 | }; | ||
494 | |||
495 | static int __init arch_timer_cpu_pm_init(void) | ||
496 | { | ||
497 | return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier); | ||
498 | } | ||
499 | #else | ||
500 | static int __init arch_timer_cpu_pm_init(void) | ||
501 | { | ||
502 | return 0; | ||
503 | } | ||
504 | #endif | ||
505 | |||
478 | static int __init arch_timer_register(void) | 506 | static int __init arch_timer_register(void) |
479 | { | 507 | { |
480 | int err; | 508 | int err; |
@@ -514,11 +542,17 @@ static int __init arch_timer_register(void) | |||
514 | if (err) | 542 | if (err) |
515 | goto out_free_irq; | 543 | goto out_free_irq; |
516 | 544 | ||
545 | err = arch_timer_cpu_pm_init(); | ||
546 | if (err) | ||
547 | goto out_unreg_notify; | ||
548 | |||
517 | /* Immediately configure the timer on the boot CPU */ | 549 | /* Immediately configure the timer on the boot CPU */ |
518 | arch_timer_setup(this_cpu_ptr(arch_timer_evt)); | 550 | arch_timer_setup(this_cpu_ptr(arch_timer_evt)); |
519 | 551 | ||
520 | return 0; | 552 | return 0; |
521 | 553 | ||
554 | out_unreg_notify: | ||
555 | unregister_cpu_notifier(&arch_timer_cpu_nb); | ||
522 | out_free_irq: | 556 | out_free_irq: |
523 | if (arch_timer_use_virtual) | 557 | if (arch_timer_use_virtual) |
524 | free_percpu_irq(arch_timer_ppi[VIRT_PPI], arch_timer_evt); | 558 | free_percpu_irq(arch_timer_ppi[VIRT_PPI], arch_timer_evt); |