|
@@ -77,20 +77,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = {
|
|
|
|
|
|
static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
|
|
|
|
|
|
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
|
|
|
- struct clockdomain *clkdm)
|
|
|
-{
|
|
|
- clkdm_allow_idle(clkdm);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
|
|
|
- struct clockdomain *clkdm)
|
|
|
-{
|
|
|
- clkdm_deny_idle(clkdm);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int __omap3_enter_idle(struct cpuidle_device *dev,
|
|
|
struct cpuidle_driver *drv,
|
|
|
int index)
|
|
@@ -108,8 +94,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
|
|
|
|
|
|
/* Deny idle for C1 */
|
|
|
if (index == 0) {
|
|
|
- pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
|
|
|
- pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
|
|
|
+ clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]);
|
|
|
+ clkdm_deny_idle(core_pd->pwrdm_clkdms[0]);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -131,8 +117,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
|
|
|
|
|
|
/* Re-allow idle for C1 */
|
|
|
if (index == 0) {
|
|
|
- pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
|
|
|
- pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
|
|
|
+ clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]);
|
|
|
+ clkdm_allow_idle(core_pd->pwrdm_clkdms[0]);
|
|
|
}
|
|
|
|
|
|
return_sleep_time:
|
|
@@ -178,7 +164,7 @@ static int next_valid_state(struct cpuidle_device *dev,
|
|
|
u32 mpu_deepest_state = PWRDM_POWER_RET;
|
|
|
u32 core_deepest_state = PWRDM_POWER_RET;
|
|
|
int idx;
|
|
|
- int next_index = -1;
|
|
|
+ int next_index = 0; /* C1 is the default value */
|
|
|
|
|
|
if (enable_off_mode) {
|
|
|
mpu_deepest_state = PWRDM_POWER_OFF;
|
|
@@ -209,12 +195,6 @@ static int next_valid_state(struct cpuidle_device *dev,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * C1 is always valid.
|
|
|
- * So, no need to check for 'next_index == -1' outside
|
|
|
- * this loop.
|
|
|
- */
|
|
|
-
|
|
|
return next_index;
|
|
|
}
|
|
|
|
|
@@ -228,23 +208,22 @@ static int next_valid_state(struct cpuidle_device *dev,
|
|
|
* the device to the specified or a safer state.
|
|
|
*/
|
|
|
static int omap3_enter_idle_bm(struct cpuidle_device *dev,
|
|
|
- struct cpuidle_driver *drv,
|
|
|
+ struct cpuidle_driver *drv,
|
|
|
int index)
|
|
|
{
|
|
|
int new_state_idx;
|
|
|
- u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
|
|
|
+ u32 core_next_state, per_next_state = 0, per_saved_state = 0;
|
|
|
struct omap3_idle_statedata *cx;
|
|
|
int ret;
|
|
|
|
|
|
/*
|
|
|
- * Prevent idle completely if CAM is active.
|
|
|
+ * Use only C1 if CAM is active.
|
|
|
* CAM does not have wakeup capability in OMAP3.
|
|
|
*/
|
|
|
- cam_state = pwrdm_read_pwrst(cam_pd);
|
|
|
- if (cam_state == PWRDM_POWER_ON) {
|
|
|
+ if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON)
|
|
|
new_state_idx = drv->safe_state_index;
|
|
|
- goto select_state;
|
|
|
- }
|
|
|
+ else
|
|
|
+ new_state_idx = next_valid_state(dev, drv, index);
|
|
|
|
|
|
/*
|
|
|
* FIXME: we currently manage device-specific idle states
|
|
@@ -254,24 +233,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
|
|
|
* its own code.
|
|
|
*/
|
|
|
|
|
|
- /*
|
|
|
- * Prevent PER off if CORE is not in retention or off as this
|
|
|
- * would disable PER wakeups completely.
|
|
|
- */
|
|
|
- cx = &omap3_idle_data[index];
|
|
|
+ /* Program PER state */
|
|
|
+ cx = &omap3_idle_data[new_state_idx];
|
|
|
core_next_state = cx->core_state;
|
|
|
per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
|
|
|
- if ((per_next_state == PWRDM_POWER_OFF) &&
|
|
|
- (core_next_state > PWRDM_POWER_RET))
|
|
|
- per_next_state = PWRDM_POWER_RET;
|
|
|
+ if (new_state_idx == 0) {
|
|
|
+ /* In C1 do not allow PER state lower than CORE state */
|
|
|
+ if (per_next_state < core_next_state)
|
|
|
+ per_next_state = core_next_state;
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * Prevent PER OFF if CORE is not in RETention or OFF as this
|
|
|
+ * would disable PER wakeups completely.
|
|
|
+ */
|
|
|
+ if ((per_next_state == PWRDM_POWER_OFF) &&
|
|
|
+ (core_next_state > PWRDM_POWER_RET))
|
|
|
+ per_next_state = PWRDM_POWER_RET;
|
|
|
+ }
|
|
|
|
|
|
/* Are we changing PER target state? */
|
|
|
if (per_next_state != per_saved_state)
|
|
|
pwrdm_set_next_pwrst(per_pd, per_next_state);
|
|
|
|
|
|
- new_state_idx = next_valid_state(dev, drv, index);
|
|
|
-
|
|
|
-select_state:
|
|
|
ret = omap3_enter_idle(dev, drv, new_state_idx);
|
|
|
|
|
|
/* Restore original PER state if it was modified */
|
|
@@ -288,7 +271,7 @@ struct cpuidle_driver omap3_idle_driver = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.states = {
|
|
|
{
|
|
|
- .enter = omap3_enter_idle,
|
|
|
+ .enter = omap3_enter_idle_bm,
|
|
|
.exit_latency = 2 + 2,
|
|
|
.target_residency = 5,
|
|
|
.flags = CPUIDLE_FLAG_TIME_VALID,
|