summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Williams <scwilliams@nvidia.com>2011-07-22 13:21:08 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:46:51 -0800
commitc2c2c2880411ffdbe7f118c5e9cd7255e3ea4472 (patch)
tree9065251186386641241da7e415bb61a0abc126e4
parente90083c3acb65b0840e7c9060e764c773b89a302 (diff)
ARM: tegra: Add LP2 exit latency correction
Change-Id: I37cb57f8674d8ddea3861fdc59543c3dfa8498db Signed-off-by: Scott Williams <scwilliams@nvidia.com> DW: Split into logical changes Signed-off-by: Dan Willemsen <dwillemsen@nvidia.com> Rebase-Id: R0a1d0c79e22f9191bde70b8b05541c5bfe26f4df
-rw-r--r--arch/arm/mach-tegra/cpuidle-t2.c12
-rw-r--r--arch/arm/mach-tegra/cpuidle.c1
-rw-r--r--arch/arm/mach-tegra/cpuidle.h2
3 files changed, 13 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/cpuidle-t2.c b/arch/arm/mach-tegra/cpuidle-t2.c
index bda6a414cc4a..e1517062d9f7 100644
--- a/arch/arm/mach-tegra/cpuidle-t2.c
+++ b/arch/arm/mach-tegra/cpuidle-t2.c
@@ -154,6 +154,7 @@ static int tegra2_idle_lp2_last(struct cpuidle_device *dev,
ktime_t entry_time;
ktime_t exit_time;
bool sleep_completed = false;
+ s64 sleep_time;
int i;
while (tegra2_cpu_is_resettable_soon())
@@ -170,7 +171,9 @@ static int tegra2_idle_lp2_last(struct cpuidle_device *dev,
entry_time = ktime_get();
- if (tegra_idle_lp2_last(request, 0) == 0)
+ sleep_time = request - tegra_lp2_exit_latency;
+
+ if (tegra_idle_lp2_last(sleep_time, 0) == 0)
sleep_completed = true;
else
idle_stats.lp2_int_count[tegra_pending_interrupt()]++;
@@ -185,10 +188,15 @@ static int tegra2_idle_lp2_last(struct cpuidle_device *dev,
exit_time = ktime_get();
if (sleep_completed) {
/*
- * Stayed in LP2 for the full time until the next tick
+ * Stayed in LP2 for the full time until the next tick,
+ * adjust the exit latency based on measurement
*/
s64 actual_time = ktime_to_us(ktime_sub(exit_time, entry_time));
long offset = (long)(actual_time - request);
+ int latency = tegra_lp2_exit_latency + offset / 16;
+ latency = clamp(latency, 0, 10000);
+ tegra_lp2_exit_latency = latency;
+ smp_wmb();
pr_debug("%lld %lld %ld\n", request, actual_time,
offset);
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
index 712ac003224f..5cd341763adc 100644
--- a/arch/arm/mach-tegra/cpuidle.c
+++ b/arch/arm/mach-tegra/cpuidle.c
@@ -49,6 +49,7 @@ static bool lp2_in_idle __read_mostly = true;
module_param(lp2_in_idle, bool, 0644);
static bool lp2_disabled_by_suspend;
+int tegra_lp2_exit_latency;
static unsigned int tegra_lp2_min_residency;
#endif
diff --git a/arch/arm/mach-tegra/cpuidle.h b/arch/arm/mach-tegra/cpuidle.h
index 35c3360a6e17..ae3386139d38 100644
--- a/arch/arm/mach-tegra/cpuidle.h
+++ b/arch/arm/mach-tegra/cpuidle.h
@@ -23,6 +23,8 @@
#ifdef CONFIG_PM_SLEEP
+extern int tegra_lp2_exit_latency;
+
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
void tegra2_idle_lp2(struct cpuidle_device *dev, struct cpuidle_state *state);
void tegra2_cpu_idle_stats_lp2_ready(unsigned int cpu);