aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/arm_arch_timer.c
diff options
context:
space:
mode:
authorSudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>2013-08-23 10:53:15 -0400
committerSudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>2013-09-26 04:48:24 -0400
commit346e7480f1d4740b3d798da60f83f087ea6488b4 (patch)
tree71788df9173d240507f4d091bc63021af767929c /drivers/clocksource/arm_arch_timer.c
parent037f637767a82907efedda78d3ff405c34020075 (diff)
drivers: clocksource: add CPU PM notifier for ARM architected timer
Few control settings done in architected timer as part of initialisation can be lost when CPU enters deeper power states. They need to be restored when the CPU is (warm)reset again. This patch adds CPU PM notifiers to save the counter control register when entering low power modes and restore it when CPU exits low power. Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Reviewed-by: Will Deacon <will.deacon@arm.com> Acked-by: Olof Johansson <olof@lixom.net> Signed-off-by: Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r--drivers/clocksource/arm_arch_timer.c34
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
480static unsigned int saved_cntkctl;
481static 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
491static struct notifier_block arch_timer_cpu_pm_notifier = {
492 .notifier_call = arch_timer_cpu_pm_notify,
493};
494
495static int __init arch_timer_cpu_pm_init(void)
496{
497 return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier);
498}
499#else
500static int __init arch_timer_cpu_pm_init(void)
501{
502 return 0;
503}
504#endif
505
478static int __init arch_timer_register(void) 506static 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
554out_unreg_notify:
555 unregister_cpu_notifier(&arch_timer_cpu_nb);
522out_free_irq: 556out_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);