OMAP3: cpuidle: change the power domains modes determination logic

The achievable power modes of the power domains in cpuidle
depends on the system wide 'enable_off_mode' knob in debugfs.
Upon changing enable_off_mode, do not change the C-states
'valid' field but instead dynamically restrict the power modes
when entering idle.

The C-states 'valid' field is just used to enable/disable some
C-states at init and shall not be changed later on.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
This commit is contained in:
Jean Pihet 2011-05-09 12:02:16 +02:00 committed by Kevin Hilman
parent c6cd91de1c
commit 0490891819
3 changed files with 24 additions and 50 deletions

View File

@ -138,22 +138,40 @@ return_sleep_time:
} }
/** /**
* next_valid_state - Find next valid c-state * next_valid_state - Find next valid C-state
* @dev: cpuidle device * @dev: cpuidle device
* @state: Currently selected c-state * @state: Currently selected C-state
* *
* If the current state is valid, it is returned back to the caller. * If the current state is valid, it is returned back to the caller.
* Else, this function searches for a lower c-state which is still * Else, this function searches for a lower c-state which is still
* valid. * valid.
*
* A state is valid if the 'valid' field is enabled and
* if it satisfies the enable_off_mode condition.
*/ */
static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
struct cpuidle_state *curr) struct cpuidle_state *curr)
{ {
struct cpuidle_state *next = NULL; struct cpuidle_state *next = NULL;
struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr);
u32 mpu_deepest_state = PWRDM_POWER_RET;
u32 core_deepest_state = PWRDM_POWER_RET;
if (enable_off_mode) {
mpu_deepest_state = PWRDM_POWER_OFF;
/*
* Erratum i583: valable for ES rev < Es1.2 on 3630.
* CORE OFF mode is not supported in a stable form, restrict
* instead the CORE state to RET.
*/
if (!IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
core_deepest_state = PWRDM_POWER_OFF;
}
/* Check if current state is valid */ /* Check if current state is valid */
if (cx->valid) { if ((cx->valid) &&
(cx->mpu_state >= mpu_deepest_state) &&
(cx->core_state >= core_deepest_state)) {
return curr; return curr;
} else { } else {
int idx = OMAP3_NUM_STATES - 1; int idx = OMAP3_NUM_STATES - 1;
@ -176,7 +194,9 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
idx--; idx--;
for (; idx >= 0; idx--) { for (; idx >= 0; idx--) {
cx = cpuidle_get_statedata(&dev->states[idx]); cx = cpuidle_get_statedata(&dev->states[idx]);
if (cx->valid) { if ((cx->valid) &&
(cx->mpu_state >= mpu_deepest_state) &&
(cx->core_state >= core_deepest_state)) {
next = &dev->states[idx]; next = &dev->states[idx];
break; break;
} }
@ -259,31 +279,6 @@ select_state:
DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev); DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
/**
* omap3_cpuidle_update_states() - Update the cpuidle states
* @mpu_deepest_state: Enable states up to and including this for mpu domain
* @core_deepest_state: Enable states up to and including this for core domain
*
* This goes through the list of states available and enables and disables the
* validity of C states based on deepest state that can be achieved for the
* variable domain
*/
void omap3_cpuidle_update_states(u32 mpu_deepest_state, u32 core_deepest_state)
{
int i;
for (i = 0; i < OMAP3_NUM_STATES; i++) {
struct omap3_idle_statedata *cx = &omap3_idle_data[i];
if ((cx->mpu_state >= mpu_deepest_state) &&
(cx->core_state >= core_deepest_state)) {
cx->valid = 1;
} else {
cx->valid = 0;
}
}
}
void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params) void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
{ {
int i; int i;
@ -393,11 +388,6 @@ int __init omap3_idle_init(void)
cx->mpu_state = PWRDM_POWER_OFF; cx->mpu_state = PWRDM_POWER_OFF;
cx->core_state = PWRDM_POWER_OFF; cx->core_state = PWRDM_POWER_OFF;
if (enable_off_mode)
omap3_cpuidle_update_states(PWRDM_POWER_OFF, PWRDM_POWER_OFF);
else
omap3_cpuidle_update_states(PWRDM_POWER_RET, PWRDM_POWER_RET);
dev->state_count = OMAP3_NUM_STATES; dev->state_count = OMAP3_NUM_STATES;
if (cpuidle_register_device(dev)) { if (cpuidle_register_device(dev)) {
printk(KERN_ERR "%s: CPUidle register device failed\n", printk(KERN_ERR "%s: CPUidle register device failed\n",

View File

@ -78,10 +78,6 @@ extern u32 sleep_while_idle;
#define sleep_while_idle 0 #define sleep_while_idle 0
#endif #endif
#if defined(CONFIG_CPU_IDLE)
extern void omap3_cpuidle_update_states(u32, u32);
#endif
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS) #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev); extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
extern int pm_dbg_regset_save(int reg_set); extern int pm_dbg_regset_save(int reg_set);

View File

@ -779,18 +779,6 @@ void omap3_pm_off_mode_enable(int enable)
else else
state = PWRDM_POWER_RET; state = PWRDM_POWER_RET;
#ifdef CONFIG_CPU_IDLE
/*
* Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
* enable OFF mode in a stable form for previous revisions, restrict
* instead to RET
*/
if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583))
omap3_cpuidle_update_states(state, PWRDM_POWER_RET);
else
omap3_cpuidle_update_states(state, state);
#endif
list_for_each_entry(pwrst, &pwrst_list, node) { list_for_each_entry(pwrst, &pwrst_list, node) {
if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) && if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583) &&
pwrst->pwrdm == core_pwrdm && pwrst->pwrdm == core_pwrdm &&