diff options
author | Alex Frid <afrid@nvidia.com> | 2010-04-06 23:07:28 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-04-08 13:02:40 -0700 |
commit | ad159fa937e9d917737956d12d530b723cba2b13 (patch) | |
tree | 6cca27e95ef31382f6a0f929a1febf40a28a2157 | |
parent | 0970c4147f0931f34edf6d019192593b580104df (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.c | 30 |
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(); |