summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/timer-t3.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2012-02-22 20:40:58 -0800
committerSimone Willett <swillett@nvidia.com>2012-03-05 17:41:48 -0800
commit4ceba6488d041960f4d619e526c226a3e7a1cdc5 (patch)
treeaa969dbd8bb22a0541f002b9324948181436e522 /arch/arm/mach-tegra/timer-t3.c
parent1c42e0f4299952b7d8a93bc0cf1178a5d9f0329c (diff)
ARM: tegra: power: Fix LP2 timers suspend/resume
On entry/exit to suspend state remove/restore Tegra3 LP2 wake timers interrupts affinity to the respective secondary CPUs. Change-Id: I9b46c5fa446a8c6e813343f4564abda5313853da Signed-off-by: Alex Frid <afrid@nvidia.com> Reviewed-on: http://git-master/r/87541 Reviewed-by: Scott Williams <scwilliams@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/timer-t3.c')
-rw-r--r--arch/arm/mach-tegra/timer-t3.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/arch/arm/mach-tegra/timer-t3.c b/arch/arm/mach-tegra/timer-t3.c
index 7b24e7cafcbb..df964fbce154 100644
--- a/arch/arm/mach-tegra/timer-t3.c
+++ b/arch/arm/mach-tegra/timer-t3.c
@@ -1,7 +1,7 @@
/*
* arch/arch/mach-tegra/timer-t3.c
*
- * Copyright (c) 2011, NVIDIA Corporation.
+ * Copyright (c) 2011-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -158,6 +158,21 @@ static void test_lp2_wake_timer(unsigned int cpu)
static inline void test_lp2_wake_timer(unsigned int cpu) {}
#endif
+static int tegra3_resume_wake_timer(unsigned int cpu)
+{
+#ifdef CONFIG_SMP
+ int ret = irq_set_affinity(tegra_lp2wake_irq[cpu].irq, cpumask_of(cpu));
+ if (ret) {
+ pr_err("Failed to set affinity for LP2 timer IRQ to "
+ "CPU %d: irq=%d, ret=%d\n", cpu,
+ tegra_lp2wake_irq[cpu].irq, ret);
+ return ret;
+ }
+#endif
+ cpumask_set_cpu(cpu, &wake_timer_ready);
+ return 0;
+}
+
static void tegra3_register_wake_timer(unsigned int cpu)
{
int ret;
@@ -170,30 +185,29 @@ static void tegra3_register_wake_timer(unsigned int cpu)
goto fail;
}
-#ifdef CONFIG_SMP
- ret = irq_set_affinity(tegra_lp2wake_irq[cpu].irq, cpumask_of(cpu));
- if (ret) {
- pr_err("Failed to set affinity for LP2 timer IRQ to "
- "CPU %d: irq=%d, ret=%d\n", cpu,
- tegra_lp2wake_irq[cpu].irq, ret);
+ ret = tegra3_resume_wake_timer(cpu);
+ if (ret)
goto fail;
- }
-#endif
+
test_lp2_wake_timer(cpu);
- cpumask_set_cpu(cpu, &wake_timer_ready);
return;
fail:
tegra_lp2_in_idle(false);
}
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_HOTPLUG_CPU)
-static void tegra3_unregister_wake_timer(unsigned int cpu)
+static void tegra3_suspend_wake_timer(unsigned int cpu)
{
cpumask_clear_cpu(cpu, &wake_timer_ready);
#ifdef CONFIG_SMP
/* Reassign the affinity of the wake IRQ to CPU 0. */
(void)irq_set_affinity(tegra_lp2wake_irq[cpu].irq, cpumask_of(0));
#endif
+}
+
+static void tegra3_unregister_wake_timer(unsigned int cpu)
+{
+ tegra3_suspend_wake_timer(cpu);
/* Dispose of this IRQ. */
remove_irq(tegra_lp2wake_irq[cpu].irq, &tegra_lp2wake_irq[cpu]);
@@ -292,10 +306,22 @@ void __init tegra3_init_timer(u32 *offset, int *irq)
static int hotplug_notify(struct notifier_block *self,
unsigned long action, void *cpu)
{
- if (action == CPU_ONLINE)
+ switch (action) {
+ case CPU_ONLINE:
tegra3_register_wake_timer((unsigned int)cpu);
- else if (action == CPU_DOWN_PREPARE)
+ break;
+ case CPU_ONLINE_FROZEN:
+ tegra3_resume_wake_timer((unsigned int)cpu);
+ break;
+ case CPU_DOWN_PREPARE:
tegra3_unregister_wake_timer((unsigned int)cpu);
+ break;
+ case CPU_DOWN_PREPARE_FROZEN:
+ tegra3_suspend_wake_timer((unsigned int)cpu);
+ break;
+ default:
+ break;
+ }
return NOTIFY_OK;
}