summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/cpuidle-t3.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2011-09-28 22:42:06 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:12 -0800
commitbe98d35b06c52310e8a5cdb22f0ba454c30313c2 (patch)
tree38aad22e51b059d93585ae175b13aeee540eaf3b /arch/arm/mach-tegra/cpuidle-t3.c
parentf61025d7b8189d5df711283ffbfa0d411c4c5dc0 (diff)
ARM: tegra: power: Update Tegra3 LP2 time prediction
Use local timer count to predict time to be spent by secondary CPU in LP2 state instead of scheduler timing. This is more accurate, as local timer wakes CPU after counts down to zero. Change-Id: I28fe6c3153e1c527abf4cf66b556d64516582a35 Reviewed-on: http://git-master/r/55629 Reviewed-by: Aleksandr Frid <afrid@nvidia.com> Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Scott Williams <scwilliams@nvidia.com> Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Reviewed-by: Antti Miettinen <amiettinen@nvidia.com> Rebase-Id: R577246dfe6bce06bf7a1f87d0ab488322d98b631
Diffstat (limited to 'arch/arm/mach-tegra/cpuidle-t3.c')
-rw-r--r--arch/arm/mach-tegra/cpuidle-t3.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/cpuidle-t3.c b/arch/arm/mach-tegra/cpuidle-t3.c
index e8e552c7717c..8ef8ed45e8bd 100644
--- a/arch/arm/mach-tegra/cpuidle-t3.c
+++ b/arch/arm/mach-tegra/cpuidle-t3.c
@@ -37,6 +37,7 @@
#include <linux/smp.h>
#include <linux/suspend.h>
#include <linux/tick.h>
+#include <linux/clk.h>
#include <asm/cacheflush.h>
#include <asm/cpu_pm.h>
@@ -67,6 +68,7 @@ static s64 tegra_cpu_wake_by_time[4] = {
#endif
static struct clk *cpu_clk_for_dvfs;
+static struct clk *twd_clk;
static struct {
unsigned int cpu_ready_count[5];
@@ -268,6 +270,17 @@ static void tegra3_idle_enter_lp2_cpu_n(struct cpuidle_device *dev,
struct cpuidle_state *state, s64 request)
{
#ifdef CONFIG_SMP
+
+ u32 twd_cnt;
+ u32 twd_ctrl = readl(twd_base + TWD_TIMER_CONTROL);
+ unsigned long twd_rate = clk_get_rate(twd_clk);
+
+ if ((twd_ctrl & TWD_TIMER_CONTROL_ENABLE) &&
+ (twd_ctrl & TWD_TIMER_CONTROL_IT_ENABLE)) {
+ twd_cnt = readl(twd_base + TWD_TIMER_COUNTER);
+ request = div_u64((u64)twd_cnt * 1000000, twd_rate);
+ }
+
if (request < tegra_lp2_exit_latency) {
/*
* Not enough time left to enter LP2
@@ -307,9 +320,10 @@ void tegra3_idle_lp2(struct cpuidle_device *dev,
tegra_clear_cpu_in_lp2(dev->cpu);
}
-int tegra_cpudile_init_soc(void)
+int tegra3_cpudile_init_soc(void)
{
cpu_clk_for_dvfs = tegra_get_clock_by_name("cpu_g");
+ twd_clk = tegra_get_clock_by_name("twd");
return 0;
}