aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Pihet <jean.pihet@newoldbits.com>2012-06-01 11:11:07 -0400
committerKevin Hilman <khilman@ti.com>2012-06-25 14:24:24 -0400
commit13d65c897e93dfeaed6fe28233559239f9676164 (patch)
tree0e68226def4d9b927ef44abbf6ac742a42680496
parent063a5d011698950c86a01044394105605556e92c (diff)
ARM: OMAP3: PM: cpuidle: optimize the PER latency in C1 state
One of the main contributors of the low power code latency is the PER power domain. To optimize the high-performance and low-latency C1 state, prevent any PER state which is lower than the CORE state in C1. Reported and suggested by Kevin Hilman. Reported-by: Kevin Hilman <khilman@ti.com> Signed-off-by: Jean Pihet <j-pihet@ti.com> Signed-off-by: Kevin Hilman <khilman@ti.com>
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index f619a928f01e..2e2f1c6f0f0b 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -222,23 +222,22 @@ static int next_valid_state(struct cpuidle_device *dev,
222 * the device to the specified or a safer state. 222 * the device to the specified or a safer state.
223 */ 223 */
224static int omap3_enter_idle_bm(struct cpuidle_device *dev, 224static int omap3_enter_idle_bm(struct cpuidle_device *dev,
225 struct cpuidle_driver *drv, 225 struct cpuidle_driver *drv,
226 int index) 226 int index)
227{ 227{
228 int new_state_idx; 228 int new_state_idx;
229 u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; 229 u32 core_next_state, per_next_state = 0, per_saved_state = 0;
230 struct omap3_idle_statedata *cx; 230 struct omap3_idle_statedata *cx;
231 int ret; 231 int ret;
232 232
233 /* 233 /*
234 * Prevent idle completely if CAM is active. 234 * Use only C1 if CAM is active.
235 * CAM does not have wakeup capability in OMAP3. 235 * CAM does not have wakeup capability in OMAP3.
236 */ 236 */
237 cam_state = pwrdm_read_pwrst(cam_pd); 237 if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON)
238 if (cam_state == PWRDM_POWER_ON) {
239 new_state_idx = drv->safe_state_index; 238 new_state_idx = drv->safe_state_index;
240 goto select_state; 239 else
241 } 240 new_state_idx = next_valid_state(dev, drv, index);
242 241
243 /* 242 /*
244 * FIXME: we currently manage device-specific idle states 243 * FIXME: we currently manage device-specific idle states
@@ -248,24 +247,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
248 * its own code. 247 * its own code.
249 */ 248 */
250 249
251 /* 250 /* Program PER state */
252 * Prevent PER off if CORE is not in retention or off as this 251 cx = &omap3_idle_data[new_state_idx];
253 * would disable PER wakeups completely.
254 */
255 cx = &omap3_idle_data[index];
256 core_next_state = cx->core_state; 252 core_next_state = cx->core_state;
257 per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); 253 per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
258 if ((per_next_state == PWRDM_POWER_OFF) && 254 if (new_state_idx == 0) {
259 (core_next_state > PWRDM_POWER_RET)) 255 /* In C1 do not allow PER state lower than CORE state */
260 per_next_state = PWRDM_POWER_RET; 256 if (per_next_state < core_next_state)
257 per_next_state = core_next_state;
258 } else {
259 /*
260 * Prevent PER OFF if CORE is not in RETention or OFF as this
261 * would disable PER wakeups completely.
262 */
263 if ((per_next_state == PWRDM_POWER_OFF) &&
264 (core_next_state > PWRDM_POWER_RET))
265 per_next_state = PWRDM_POWER_RET;
266 }
261 267
262 /* Are we changing PER target state? */ 268 /* Are we changing PER target state? */
263 if (per_next_state != per_saved_state) 269 if (per_next_state != per_saved_state)
264 pwrdm_set_next_pwrst(per_pd, per_next_state); 270 pwrdm_set_next_pwrst(per_pd, per_next_state);
265 271
266 new_state_idx = next_valid_state(dev, drv, index);
267
268select_state:
269 ret = omap3_enter_idle(dev, drv, new_state_idx); 272 ret = omap3_enter_idle(dev, drv, new_state_idx);
270 273
271 /* Restore original PER state if it was modified */ 274 /* Restore original PER state if it was modified */
@@ -282,7 +285,7 @@ struct cpuidle_driver omap3_idle_driver = {
282 .owner = THIS_MODULE, 285 .owner = THIS_MODULE,
283 .states = { 286 .states = {
284 { 287 {
285 .enter = omap3_enter_idle, 288 .enter = omap3_enter_idle_bm,
286 .exit_latency = 2 + 2, 289 .exit_latency = 2 + 2,
287 .target_residency = 5, 290 .target_residency = 5,
288 .flags = CPUIDLE_FLAG_TIME_VALID, 291 .flags = CPUIDLE_FLAG_TIME_VALID,