diff options
author | Scott Williams <scwilliams@nvidia.com> | 2011-07-21 17:44:21 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:46:51 -0800 |
commit | 9967bd0823753a0a1413a557649c2f9cc3e3a308 (patch) | |
tree | 2163e8ac68bee4543c73d293c0564e2992875825 | |
parent | 9ca84c0c18f9e0435b8e7bd241a2662484165271 (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.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpuidle.h | 9 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pm.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pm.h | 2 |
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 |