Commit 4556494b authored by Tony Lindgren's avatar Tony Lindgren

Merge branch 'for_3.6/pm/performance' of...

Merge branch 'for_3.6/pm/performance' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into devel-pm
parents 9a17d88e 05011f71
...@@ -77,20 +77,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = { ...@@ -77,20 +77,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = {
static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; 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, static int __omap3_enter_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, struct cpuidle_driver *drv,
int index) int index)
...@@ -108,8 +94,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, ...@@ -108,8 +94,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
/* Deny idle for C1 */ /* Deny idle for C1 */
if (index == 0) { if (index == 0) {
pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]);
pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); clkdm_deny_idle(core_pd->pwrdm_clkdms[0]);
} }
/* /*
...@@ -131,8 +117,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, ...@@ -131,8 +117,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
/* Re-allow idle for C1 */ /* Re-allow idle for C1 */
if (index == 0) { if (index == 0) {
pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]);
pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); clkdm_allow_idle(core_pd->pwrdm_clkdms[0]);
} }
return_sleep_time: return_sleep_time:
...@@ -178,7 +164,7 @@ static int next_valid_state(struct cpuidle_device *dev, ...@@ -178,7 +164,7 @@ static int next_valid_state(struct cpuidle_device *dev,
u32 mpu_deepest_state = PWRDM_POWER_RET; u32 mpu_deepest_state = PWRDM_POWER_RET;
u32 core_deepest_state = PWRDM_POWER_RET; u32 core_deepest_state = PWRDM_POWER_RET;
int idx; int idx;
int next_index = -1; int next_index = 0; /* C1 is the default value */
if (enable_off_mode) { if (enable_off_mode) {
mpu_deepest_state = PWRDM_POWER_OFF; mpu_deepest_state = PWRDM_POWER_OFF;
...@@ -209,12 +195,6 @@ static int next_valid_state(struct cpuidle_device *dev, ...@@ -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; return next_index;
} }
...@@ -228,23 +208,22 @@ static int next_valid_state(struct cpuidle_device *dev, ...@@ -228,23 +208,22 @@ static int next_valid_state(struct cpuidle_device *dev,
* the device to the specified or a safer state. * the device to the specified or a safer state.
*/ */
static int omap3_enter_idle_bm(struct cpuidle_device *dev, static int omap3_enter_idle_bm(struct cpuidle_device *dev,
struct cpuidle_driver *drv, struct cpuidle_driver *drv,
int index) int index)
{ {
int new_state_idx; 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; struct omap3_idle_statedata *cx;
int ret; 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 does not have wakeup capability in OMAP3.
*/ */
cam_state = pwrdm_read_pwrst(cam_pd); if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON)
if (cam_state == PWRDM_POWER_ON) {
new_state_idx = drv->safe_state_index; 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 * FIXME: we currently manage device-specific idle states
...@@ -254,24 +233,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, ...@@ -254,24 +233,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
* its own code. * its own code.
*/ */
/* /* Program PER state */
* Prevent PER off if CORE is not in retention or off as this cx = &omap3_idle_data[new_state_idx];
* would disable PER wakeups completely.
*/
cx = &omap3_idle_data[index];
core_next_state = cx->core_state; core_next_state = cx->core_state;
per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
if ((per_next_state == PWRDM_POWER_OFF) && if (new_state_idx == 0) {
(core_next_state > PWRDM_POWER_RET)) /* In C1 do not allow PER state lower than CORE state */
per_next_state = PWRDM_POWER_RET; 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? */ /* Are we changing PER target state? */
if (per_next_state != per_saved_state) if (per_next_state != per_saved_state)
pwrdm_set_next_pwrst(per_pd, per_next_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); ret = omap3_enter_idle(dev, drv, new_state_idx);
/* Restore original PER state if it was modified */ /* Restore original PER state if it was modified */
...@@ -288,7 +271,7 @@ struct cpuidle_driver omap3_idle_driver = { ...@@ -288,7 +271,7 @@ struct cpuidle_driver omap3_idle_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.states = { .states = {
{ {
.enter = omap3_enter_idle, .enter = omap3_enter_idle_bm,
.exit_latency = 2 + 2, .exit_latency = 2 + 2,
.target_residency = 5, .target_residency = 5,
.flags = CPUIDLE_FLAG_TIME_VALID, .flags = CPUIDLE_FLAG_TIME_VALID,
......
...@@ -255,7 +255,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) ...@@ -255,7 +255,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
return -ENXIO; return -ENXIO;
} }
pwrdm_pre_transition(); pwrdm_pre_transition(NULL);
/* /*
* Check MPUSS next state and save interrupt controller if needed. * Check MPUSS next state and save interrupt controller if needed.
...@@ -287,7 +287,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) ...@@ -287,7 +287,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
wakeup_cpu = smp_processor_id(); wakeup_cpu = smp_processor_id();
set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON); set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
pwrdm_post_transition(); pwrdm_post_transition(NULL);
return 0; return 0;
} }
......
...@@ -70,7 +70,6 @@ void (*omap3_do_wfi_sram)(void); ...@@ -70,7 +70,6 @@ void (*omap3_do_wfi_sram)(void);
static struct powerdomain *mpu_pwrdm, *neon_pwrdm; static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm; static struct powerdomain *core_pwrdm, *per_pwrdm;
static struct powerdomain *cam_pwrdm;
static void omap3_core_save_context(void) static void omap3_core_save_context(void)
{ {
...@@ -273,16 +272,21 @@ void omap_sram_idle(void) ...@@ -273,16 +272,21 @@ void omap_sram_idle(void)
per_next_state = pwrdm_read_next_pwrst(per_pwrdm); per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
core_next_state = pwrdm_read_next_pwrst(core_pwrdm); core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
pwrdm_pre_transition(); if (mpu_next_state < PWRDM_POWER_ON) {
pwrdm_pre_transition(mpu_pwrdm);
pwrdm_pre_transition(neon_pwrdm);
}
/* PER */ /* PER */
if (per_next_state < PWRDM_POWER_ON) { if (per_next_state < PWRDM_POWER_ON) {
pwrdm_pre_transition(per_pwrdm);
per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
omap2_gpio_prepare_for_idle(per_going_off); omap2_gpio_prepare_for_idle(per_going_off);
} }
/* CORE */ /* CORE */
if (core_next_state < PWRDM_POWER_ON) { if (core_next_state < PWRDM_POWER_ON) {
pwrdm_pre_transition(core_pwrdm);
if (core_next_state == PWRDM_POWER_OFF) { if (core_next_state == PWRDM_POWER_OFF) {
omap3_core_save_context(); omap3_core_save_context();
omap3_cm_save_context(); omap3_cm_save_context();
...@@ -335,16 +339,20 @@ void omap_sram_idle(void) ...@@ -335,16 +339,20 @@ void omap_sram_idle(void)
omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK, omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
OMAP3430_GR_MOD, OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET); OMAP3_PRM_VOLTCTRL_OFFSET);
pwrdm_post_transition(core_pwrdm);
} }
omap3_intc_resume_idle(); omap3_intc_resume_idle();
pwrdm_post_transition();
/* PER */ /* PER */
if (per_next_state < PWRDM_POWER_ON) if (per_next_state < PWRDM_POWER_ON) {
omap2_gpio_resume_after_idle(); omap2_gpio_resume_after_idle();
pwrdm_post_transition(per_pwrdm);
}
clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]); if (mpu_next_state < PWRDM_POWER_ON) {
pwrdm_post_transition(mpu_pwrdm);
pwrdm_post_transition(neon_pwrdm);
}
} }
static void omap3_pm_idle(void) static void omap3_pm_idle(void)
...@@ -705,7 +713,6 @@ int __init omap3_pm_init(void) ...@@ -705,7 +713,6 @@ int __init omap3_pm_init(void)
neon_pwrdm = pwrdm_lookup("neon_pwrdm"); neon_pwrdm = pwrdm_lookup("neon_pwrdm");
per_pwrdm = pwrdm_lookup("per_pwrdm"); per_pwrdm = pwrdm_lookup("per_pwrdm");
core_pwrdm = pwrdm_lookup("core_pwrdm"); core_pwrdm = pwrdm_lookup("core_pwrdm");
cam_pwrdm = pwrdm_lookup("cam_pwrdm");
neon_clkdm = clkdm_lookup("neon_clkdm"); neon_clkdm = clkdm_lookup("neon_clkdm");
mpu_clkdm = clkdm_lookup("mpu_clkdm"); mpu_clkdm = clkdm_lookup("mpu_clkdm");
......
...@@ -981,15 +981,23 @@ int pwrdm_state_switch(struct powerdomain *pwrdm) ...@@ -981,15 +981,23 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
return ret; return ret;
} }
int pwrdm_pre_transition(void) int pwrdm_pre_transition(struct powerdomain *pwrdm)
{ {
pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); if (pwrdm)
_pwrdm_pre_transition_cb(pwrdm, NULL);
else
pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
return 0; return 0;
} }
int pwrdm_post_transition(void) int pwrdm_post_transition(struct powerdomain *pwrdm)
{ {
pwrdm_for_each(_pwrdm_post_transition_cb, NULL); if (pwrdm)
_pwrdm_post_transition_cb(pwrdm, NULL);
else
pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
return 0; return 0;
} }
......
...@@ -213,8 +213,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm); ...@@ -213,8 +213,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
int pwrdm_wait_transition(struct powerdomain *pwrdm); int pwrdm_wait_transition(struct powerdomain *pwrdm);
int pwrdm_state_switch(struct powerdomain *pwrdm); int pwrdm_state_switch(struct powerdomain *pwrdm);
int pwrdm_pre_transition(void); int pwrdm_pre_transition(struct powerdomain *pwrdm);
int pwrdm_post_transition(void); int pwrdm_post_transition(struct powerdomain *pwrdm);
int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment