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[] = {
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;
}
......@@ -232,19 +212,18 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
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.
*/
/* 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 (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
* Prevent PER OFF if CORE is not in RETention or OFF as this
* would disable PER wakeups completely.
*/
cx = &omap3_idle_data[index];
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;
}
/* 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,
......
......@@ -255,7 +255,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
return -ENXIO;
}
pwrdm_pre_transition();
pwrdm_pre_transition(NULL);
/*
* 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)
wakeup_cpu = smp_processor_id();
set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
pwrdm_post_transition();
pwrdm_post_transition(NULL);
return 0;
}
......
......@@ -70,7 +70,6 @@ void (*omap3_do_wfi_sram)(void);
static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm;
static struct powerdomain *cam_pwrdm;
static void omap3_core_save_context(void)
{
......@@ -273,16 +272,21 @@ void omap_sram_idle(void)
per_next_state = pwrdm_read_next_pwrst(per_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 */
if (per_next_state < PWRDM_POWER_ON) {
pwrdm_pre_transition(per_pwrdm);
per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
omap2_gpio_prepare_for_idle(per_going_off);
}
/* CORE */
if (core_next_state < PWRDM_POWER_ON) {
pwrdm_pre_transition(core_pwrdm);
if (core_next_state == PWRDM_POWER_OFF) {
omap3_core_save_context();
omap3_cm_save_context();
......@@ -335,16 +339,20 @@ void omap_sram_idle(void)
omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
OMAP3430_GR_MOD,
OMAP3_PRM_VOLTCTRL_OFFSET);
pwrdm_post_transition(core_pwrdm);
}
omap3_intc_resume_idle();
pwrdm_post_transition();
/* PER */
if (per_next_state < PWRDM_POWER_ON)
if (per_next_state < PWRDM_POWER_ON) {
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)
......@@ -705,7 +713,6 @@ int __init omap3_pm_init(void)
neon_pwrdm = pwrdm_lookup("neon_pwrdm");
per_pwrdm = pwrdm_lookup("per_pwrdm");
core_pwrdm = pwrdm_lookup("core_pwrdm");
cam_pwrdm = pwrdm_lookup("cam_pwrdm");
neon_clkdm = clkdm_lookup("neon_clkdm");
mpu_clkdm = clkdm_lookup("mpu_clkdm");
......
......@@ -981,15 +981,23 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
return ret;
}
int pwrdm_pre_transition(void)
int pwrdm_pre_transition(struct powerdomain *pwrdm)
{
if (pwrdm)
_pwrdm_pre_transition_cb(pwrdm, NULL);
else
pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
return 0;
}
int pwrdm_post_transition(void)
int pwrdm_post_transition(struct powerdomain *pwrdm)
{
if (pwrdm)
_pwrdm_post_transition_cb(pwrdm, NULL);
else
pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
return 0;
}
......
......@@ -213,8 +213,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
int pwrdm_wait_transition(struct powerdomain *pwrdm);
int pwrdm_state_switch(struct powerdomain *pwrdm);
int pwrdm_pre_transition(void);
int pwrdm_post_transition(void);
int pwrdm_pre_transition(struct powerdomain *pwrdm);
int pwrdm_post_transition(struct powerdomain *pwrdm);
int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
int pwrdm_get_context_loss_count(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