ARM: OMAP3xxx: CPUIdle: optimize __omap3_enter_idle()
authorPaul Walmsley <paul@pwsan.com>
Sat, 26 Jan 2013 07:58:13 +0000 (00:58 -0700)
committerGrazvydas Ignotas <notasas@gmail.com>
Mon, 14 Apr 2014 00:23:56 +0000 (03:23 +0300)
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 <paul@pwsan.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Conflicts:

arch/arm/mach-omap2/cpuidle34xx.c

arch/arm/mach-omap2/cpuidle34xx.c

index e8e8d39..bbb1a21 100644 (file)
@@ -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);