summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/cpuidle-t3.c
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2012-01-30 13:42:05 -0800
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-02-03 06:17:59 -0800
commit98e66926adcf7af88c87f467a11fba35c143f663 (patch)
tree16fa23ae25a97a8b557d31048b38a53ad068f292 /arch/arm/mach-tegra/cpuidle-t3.c
parent3563d218e037805c363771df34adc3b8c666e8c1 (diff)
ARM: tegra: power: Separate lp2 latency for G/LP CPU modes
Do not use common lp2 exit latency for Tegra3 CPU G and CPU LP modes. Separately measure and adjust latency in each mode; restart calculation after mode switch from the last measured latency in the target mode. Reviewed-on: http://git-master/r/78344 Change-Id: I54803c6abf4107a578aa1fed8feaa4a419a9c07f Signed-off-by: Alex Frid <afrid@nvidia.com> Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-on: http://git-master/r/78902 Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com> Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/cpuidle-t3.c')
-rw-r--r--arch/arm/mach-tegra/cpuidle-t3.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/cpuidle-t3.c b/arch/arm/mach-tegra/cpuidle-t3.c
index fb51e25e75e9..a4e158f06095 100644
--- a/arch/arm/mach-tegra/cpuidle-t3.c
+++ b/arch/arm/mach-tegra/cpuidle-t3.c
@@ -76,6 +76,8 @@ module_param(lp2_n_in_idle, bool, 0644);
static struct clk *cpu_clk_for_dvfs;
static struct clk *twd_clk;
+static int lp2_exit_latencies[5];
+
static struct {
unsigned int cpu_ready_count[5];
unsigned int tear_down_count[5];
@@ -149,6 +151,11 @@ bool tegra3_lp2_is_allowed(struct cpuidle_device *dev,
}
request = ktime_to_us(tick_nohz_get_sleep_length());
+ if (state->exit_latency != lp2_exit_latencies[cpu_number(dev->cpu)]) {
+ /* possible on the 1st entry after cluster switch*/
+ state->exit_latency = lp2_exit_latencies[cpu_number(dev->cpu)];
+ tegra_lp2_update_target_residency(state);
+ }
if (request < state->target_residency) {
/* Not enough time left to enter LP2 */
return false;
@@ -224,7 +231,8 @@ static void tegra3_idle_enter_lp2_cpu_0(struct cpuidle_device *dev,
#endif
if (request > state->target_residency) {
- s64 sleep_time = request - tegra_lp2_exit_latency;
+ s64 sleep_time = request -
+ lp2_exit_latencies[cpu_number(dev->cpu)];
bin = time_to_bin((u32)request / 1000);
idle_stats.tear_down_count[cpu_number(dev->cpu)]++;
@@ -274,9 +282,12 @@ static void tegra3_idle_enter_lp2_cpu_0(struct cpuidle_device *dev,
*/
int offset = ktime_to_us(ktime_sub(exit_time, entry_time))
- request;
- int latency = tegra_lp2_exit_latency + offset / 16;
+ int latency = lp2_exit_latencies[cpu_number(dev->cpu)] +
+ offset / 16;
latency = clamp(latency, 0, 10000);
tegra_lp2_exit_latency = latency;
+ lp2_exit_latencies[cpu_number(dev->cpu)] = latency;
+ state->exit_latency = latency; /* for idle governor */
smp_wmb();
idle_stats.lp2_completed_count++;
@@ -326,6 +337,9 @@ static void tegra3_idle_enter_lp2_cpu_n(struct cpuidle_device *dev,
tegra_cpu_wake_by_time[dev->cpu] = LLONG_MAX;
+ /* FIXME: find real cpu_n latency */
+ lp2_exit_latencies[cpu_number(dev->cpu)] = tegra_lp2_exit_latency;
+ state->exit_latency = tegra_lp2_exit_latency; /* for idle governor */
idle_stats.in_lp2_time[cpu_number(dev->cpu)] +=
ktime_to_us(ktime_sub(ktime_get(), entery_time));
#endif
@@ -350,8 +364,14 @@ void tegra3_idle_lp2(struct cpuidle_device *dev,
int tegra3_cpudile_init_soc(void)
{
+ int i;
+
cpu_clk_for_dvfs = tegra_get_clock_by_name("cpu_g");
twd_clk = tegra_get_clock_by_name("twd");
+
+ for (i = 0; i < ARRAY_SIZE(lp2_exit_latencies); i++)
+ lp2_exit_latencies[i] = tegra_lp2_exit_latency;
+
return 0;
}