From a438b5a2cec75996da7628a089b15902b9f54bb8 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Sat, 26 Jan 2013 00:58:13 -0700 Subject: [PATCH] ARM: OMAP3xxx: CPUIdle: optimize __omap3_enter_idle() Avoid programming the MPU and CORE powerdomain next-power-state registers if those powerdomains will never enter low-power states (e.g., the state that people refer to as "C1"). To avoid making assumptions about CPUIdle states based on their order in the list, use a flag to mark CPUIdle states that don't enter powerdomain low-power states. Avoid a previous-power-state register read on the MPU powerdomain unless we know that the MPU was supposed to go OFF during the last state transition. Previous-power-state register reads can be very expensive, so it's worth avoiding these when possible. Since the CORE_L3 clockdomain can't go inactive unless the MPU is active, there's little point blocking autoidle on the CORE_L3 clockdomain in "C1" state, since we've programmed the MPU clockdomain to stay active. Remove the unnecessary code. [notasas@gmail.com: 3.2 backport] Signed-off-by: Paul Walmsley Cc: Kevin Hilman Conflicts: arch/arm/mach-omap2/cpuidle34xx.c --- arch/arm/mach-omap2/cpuidle34xx.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index e8e8d39a711d..bbb1a21b7f42 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -89,7 +89,6 @@ static int omap3_enter_idle(struct cpuidle_device *dev, struct omap3_idle_statedata *cx = cpuidle_get_statedata(&dev->states_usage[index]); struct timespec ts_preidle, ts_postidle, ts_idle; - u32 mpu_state = cx->mpu_state, core_state = cx->core_state; int idle_time; /* Used to keep track of the total time in idle */ @@ -97,23 +96,22 @@ static int omap3_enter_idle(struct cpuidle_device *dev, local_irq_disable(); - pwrdm_set_next_pwrst(mpu_pd, mpu_state); - pwrdm_set_next_pwrst(core_pd, core_state); - if (omap_irq_pending() || need_resched()) goto return_sleep_time; /* Deny idle for C1 */ if (index == 0) { clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]); - clkdm_deny_idle(core_pd->pwrdm_clkdms[0]); + } else { + pwrdm_set_next_pwrst(mpu_pd, cx->mpu_state); + pwrdm_set_next_pwrst(core_pd, cx->core_state); } /* * Call idle CPU PM enter notifier chain so that * VFP context is saved. */ - if (mpu_state == PWRDM_POWER_OFF) + if (cx->mpu_state == PWRDM_POWER_OFF) cpu_pm_enter(); /* Execute ARM wfi */ @@ -123,14 +121,13 @@ static int omap3_enter_idle(struct cpuidle_device *dev, * Call idle CPU PM enter notifier chain to restore * VFP context. */ - if (pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF) + if (cx->mpu_state == PWRDM_POWER_OFF && + pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF) cpu_pm_exit(); /* Re-allow idle for C1 */ - if (index == 0) { + if (index == 0) clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]); - clkdm_allow_idle(core_pd->pwrdm_clkdms[0]); - } return_sleep_time: getnstimeofday(&ts_postidle); -- 2.39.2