summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Williams <scwilliams@nvidia.com>2011-07-21 17:44:21 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:46:51 -0800
commit9967bd0823753a0a1413a557649c2f9cc3e3a308 (patch)
tree2163e8ac68bee4543c73d293c0564e2992875825
parent9ca84c0c18f9e0435b8e7bd241a2662484165271 (diff)
ARM: tegra: Catch early LP2 exits
Change-Id: I107d301ec8e8cd3b69ea293faab15b8d766e38f4 Signed-off-by: Scott Williams <scwilliams@nvidia.com> DW: Split into logical changes Signed-off-by: Dan Willemsen <dwillemsen@nvidia.com> Rebase-Id: R9f8f016c1850e2c65f30f2f67241a94acf8a7755
-rw-r--r--arch/arm/mach-tegra/cpuidle-t2.c13
-rw-r--r--arch/arm/mach-tegra/cpuidle.h9
-rw-r--r--arch/arm/mach-tegra/pm.c5
-rw-r--r--arch/arm/mach-tegra/pm.h2
4 files changed, 26 insertions, 3 deletions
diff --git a/arch/arm/mach-tegra/cpuidle-t2.c b/arch/arm/mach-tegra/cpuidle-t2.c
index 446dea09479e..0fccb335e1cb 100644
--- a/arch/arm/mach-tegra/cpuidle-t2.c
+++ b/arch/arm/mach-tegra/cpuidle-t2.c
@@ -151,6 +151,7 @@ bool tegra2_lp2_is_allowed(struct cpuidle_device *dev,
static int tegra2_idle_lp2_last(struct cpuidle_device *dev,
struct cpuidle_state *state, s64 request)
{
+ bool sleep_completed = false;
int i;
while (tegra2_cpu_is_resettable_soon())
@@ -165,7 +166,10 @@ static int tegra2_idle_lp2_last(struct cpuidle_device *dev,
return -EBUSY;
}
- tegra_idle_lp2_last(request, 0);
+ if (tegra_idle_lp2_last(request, 0) == 0)
+ sleep_completed = true;
+ else
+ idle_stats.lp2_int_count[tegra_pending_interrupt()]++;
for_each_online_cpu(i) {
if (i != dev->cpu) {
@@ -174,6 +178,13 @@ static int tegra2_idle_lp2_last(struct cpuidle_device *dev,
}
}
+ if (sleep_completed) {
+ /*
+ * Stayed in LP2 for the full time until the next tick
+ */
+ pr_debug("%lld\n", request);
+ }
+
return 0;
}
diff --git a/arch/arm/mach-tegra/cpuidle.h b/arch/arm/mach-tegra/cpuidle.h
index 8f17ba66aa85..35c3360a6e17 100644
--- a/arch/arm/mach-tegra/cpuidle.h
+++ b/arch/arm/mach-tegra/cpuidle.h
@@ -73,6 +73,15 @@ static inline int tegra_lp2_debug_show(struct seq_file *s, void *data)
}
#endif
+static inline int tegra_pending_interrupt(void)
+{
+ void __iomem *gic_cpu = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100);
+ u32 reg = readl(gic_cpu + 0x18);
+ reg &= 0x3FF;
+
+ return reg;
+}
+
#ifdef CONFIG_CPU_IDLE
void tegra_lp2_in_idle(bool enable);
#else
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 5775208e67d9..c13b17a993ad 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -425,9 +425,10 @@ bool tegra_set_cpu_in_lp2(int cpu)
return last_cpu;
}
-void tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
+unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
{
u32 reg;
+ unsigned int remain;
/* Only the last cpu down does the final suspend steps */
reg = readl(pmc + PMC_CTRL);
@@ -469,6 +470,7 @@ void tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
restore_cpu_complex();
cpu_complex_pm_exit();
+ remain = tegra_lp2_timer_remain();
if (sleep_time)
tegra_lp2_set_trigger(0);
@@ -491,6 +493,7 @@ void tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
tegra_cluster_switch_times[tegra_cluster_switch_time_id_start]);
}
#endif
+ return remain;
}
static int tegra_common_suspend(void)
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index 9a689a857ebb..cb9c9fc306e6 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -102,7 +102,7 @@ u64 tegra_rtc_read_ms(void);
*/
extern void (*tegra_deep_sleep)(int);
-void tegra_idle_lp2_last(unsigned int us, unsigned int flags);
+unsigned int tegra_idle_lp2_last(unsigned int us, unsigned int flags);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC