summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Frid <afrid@nvidia.com>2010-04-06 23:07:28 -0700
committerGary King <gking@nvidia.com>2010-04-08 13:02:40 -0700
commitad159fa937e9d917737956d12d530b723cba2b13 (patch)
tree6cca27e95ef31382f6a0f929a1febf40a28a2157
parent0970c4147f0931f34edf6d019192593b580104df (diff)
tegra RM: Updated tegra idle loop timing.
Updated tegra idle loop timing: - Added scheduler tick stop as a condition for LP2 entry; it made sure that jiffies are updated by the kernel after tegra idle code exit; hence, direct (unprotected) jiffies increment in idle code is removed - Rounded down sleep time estimate to avoid over-sleeping next interrupt in LP2 - Set more realistic LP2 turn-around time to take into account power rail transition time Change-Id: I7d97496b2f39d33a8150b51dfa152e72eb774fc0 Reviewed-on: http://git-master/r/1054 Tested-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/idle-t2.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/arch/arm/mach-tegra/idle-t2.c b/arch/arm/mach-tegra/idle-t2.c
index 27c3ff4f8acc..fa71134a58ca 100644
--- a/arch/arm/mach-tegra/idle-t2.c
+++ b/arch/arm/mach-tegra/idle-t2.c
@@ -29,6 +29,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/wakelock.h>
+#include <linux/tick.h>
#include "nvos.h"
extern NvRmDeviceHandle s_hRmGlobal;
@@ -51,7 +52,7 @@ extern struct wake_lock main_wake_lock;
#define TEMP_SAVE_AREA_SIZE 16
#define ENABLE_LP2 1
#define LP2_PADDING_FACTOR 5
-#define LP2_ROUNDTRIP_TIME_US 1000ul
+#define LP2_ROUNDTRIP_TIME_US 2500ul
//Let Max LP2 time wait be 71 min (Almost a wrap around)
#define LP2_MAX_WAIT_TIME_US (71*60*1000000ul)
@@ -295,18 +296,29 @@ void mach_tegra_idle(void)
!(NvRmPrivGetDfsFlags(s_hRmGlobal) & NvRmDfsStatusFlags_Pause))
lp2_ok = false;
+ if (lp2_ok) {
+ struct tick_sched *ts =
+ tick_get_tick_sched(smp_processor_id());
+ if (!ts->tick_stopped)
+ lp2_ok = false;
+ }
+
if (lp2_ok) {
- unsigned long long now, sleep_jiffies;
+ unsigned long now, sleep_jiffies;
- now = get_jiffies_64();
+ now = (unsigned long)get_jiffies_64();
sleep_jiffies = get_next_timer_interrupt(now) - now;
- sleep_time = jiffies_to_usecs(sleep_jiffies);
+ if (sleep_jiffies > 1) {
+ sleep_time = jiffies_to_usecs(sleep_jiffies - 1);
- sleep_time = min_t(unsigned long, sleep_time,
- LP2_MAX_WAIT_TIME_US);
+ sleep_time = min_t(unsigned long, sleep_time,
+ LP2_MAX_WAIT_TIME_US);
- if (sleep_time <= (LP2_ROUNDTRIP_TIME_US*LP2_PADDING_FACTOR))
+ if (sleep_time <=
+ (LP2_ROUNDTRIP_TIME_US*LP2_PADDING_FACTOR))
+ lp2_ok = false;
+ } else
lp2_ok = false;
}
@@ -315,13 +327,15 @@ void mach_tegra_idle(void)
tegra_lp2_set_trigger(sleep_time);
cpu_ap20_do_lp2();
tegra_lp2_set_trigger(0);
+
/* add the actual amount of time spent in lp2 to the timers */
sleep_time = NV_REGR(s_hRmGlobal, NvRmModuleID_Pmif,
0, APBDEV_PMC_SCRATCH39_0);
sleep_time -= NV_REGR(s_hRmGlobal, NvRmModuleID_Pmif,
0, APBDEV_PMC_SCRATCH38_0);
- jiffies += usecs_to_jiffies(sleep_time);
+ // jiffies += usecs_to_jiffies(sleep_time);
+ // jiffies updated by tick_nohz_restart_sched_tick() after exit
NvRmPrivSetLp2TimeUS(s_hRmGlobal, sleep_time);
} else
cpu_ap20_do_idle();