diff options
Diffstat (limited to 'arch/arm/mach-omap2/cpuidle34xx.c')
-rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 134 |
1 files changed, 48 insertions, 86 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 942bb4f..4bf6e6e 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c @@ -24,7 +24,6 @@ #include <linux/sched.h> #include <linux/cpuidle.h> -#include <linux/export.h> #include <plat/prcm.h> #include <plat/irqs.h> @@ -89,21 +88,17 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm, /** * omap3_enter_idle - Programs OMAP3 to enter the specified state * @dev: cpuidle device - * @drv: cpuidle driver - * @index: the index of state to be entered + * @state: The target state to be programmed * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. */ static int omap3_enter_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) + struct cpuidle_state *state) { - struct omap3_idle_statedata *cx = - cpuidle_get_statedata(&dev->states_usage[index]); + struct omap3_idle_statedata *cx = cpuidle_get_statedata(state); 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 */ getnstimeofday(&ts_preidle); @@ -118,7 +113,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, goto return_sleep_time; /* Deny idle for C1 */ - if (index == 0) { + if (state == &dev->states[0]) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); } @@ -127,7 +122,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev, omap_sram_idle(); /* Re-allow idle for C1 */ - if (index == 0) { + if (state == &dev->states[0]) { pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); } @@ -139,38 +134,28 @@ return_sleep_time: local_irq_enable(); local_fiq_enable(); - idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \ - USEC_PER_SEC; - - /* Update cpuidle counters */ - dev->last_residency = idle_time; - - return index; + return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; } /** * next_valid_state - Find next valid C-state * @dev: cpuidle device - * @drv: cpuidle driver - * @index: Index of currently selected c-state + * @state: Currently selected C-state * - * If the state corresponding to index is valid, index is returned back - * to the caller. Else, this function searches for a lower c-state which is - * still valid (as defined in omap3_power_states[]) and returns its index. + * 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 + * valid. * * A state is valid if the 'valid' field is enabled and * if it satisfies the enable_off_mode condition. */ -static int next_valid_state(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) +static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, + struct cpuidle_state *curr) { - struct cpuidle_state_usage *curr_usage = &dev->states_usage[index]; - struct cpuidle_state *curr = &drv->states[index]; - struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage); + struct cpuidle_state *next = NULL; + struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); u32 mpu_deepest_state = PWRDM_POWER_RET; u32 core_deepest_state = PWRDM_POWER_RET; - int next_index = -1; if (enable_off_mode) { mpu_deepest_state = PWRDM_POWER_OFF; @@ -187,20 +172,20 @@ static int next_valid_state(struct cpuidle_device *dev, if ((cx->valid) && (cx->mpu_state >= mpu_deepest_state) && (cx->core_state >= core_deepest_state)) { - return index; + return curr; } else { int idx = OMAP3_NUM_STATES - 1; /* Reach the current state starting at highest C-state */ for (; idx >= 0; idx--) { - if (&drv->states[idx] == curr) { - next_index = idx; + if (&dev->states[idx] == curr) { + next = &dev->states[idx]; break; } } /* Should never hit this condition */ - WARN_ON(next_index == -1); + WARN_ON(next == NULL); /* * Drop to next valid state. @@ -208,44 +193,41 @@ static int next_valid_state(struct cpuidle_device *dev, */ idx--; for (; idx >= 0; idx--) { - cx = cpuidle_get_statedata(&dev->states_usage[idx]); + cx = cpuidle_get_statedata(&dev->states[idx]); if ((cx->valid) && (cx->mpu_state >= mpu_deepest_state) && (cx->core_state >= core_deepest_state)) { - next_index = idx; + next = &dev->states[idx]; break; } } /* * C1 is always valid. - * So, no need to check for 'next_index == -1' outside - * this loop. + * So, no need to check for 'next==NULL' outside this loop. */ } - return next_index; + return next; } /** * omap3_enter_idle_bm - Checks for any bus activity * @dev: cpuidle device - * @drv: cpuidle driver - * @index: array index of target state to be programmed + * @state: The target state to be programmed * * This function checks for any pending activity and then programs * the device to the specified or a safer state. */ static int omap3_enter_idle_bm(struct cpuidle_device *dev, - struct cpuidle_driver *drv, - int index) + struct cpuidle_state *state) { - int new_state_idx; + struct cpuidle_state *new_state; u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; struct omap3_idle_statedata *cx; int ret; if (!omap3_can_sleep()) { - new_state_idx = drv->safe_state_index; + new_state = dev->safe_state; goto select_state; } @@ -255,7 +237,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, */ cam_state = pwrdm_read_pwrst(cam_pd); if (cam_state == PWRDM_POWER_ON) { - new_state_idx = drv->safe_state_index; + new_state = dev->safe_state; goto select_state; } @@ -271,7 +253,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, * Prevent PER off if CORE is not in retention or off as this * would disable PER wakeups completely. */ - cx = cpuidle_get_statedata(&dev->states_usage[index]); + cx = cpuidle_get_statedata(state); 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) && @@ -282,10 +264,11 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, 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); + new_state = next_valid_state(dev, state); select_state: - ret = omap3_enter_idle(dev, drv, new_state_idx); + dev->last_state = new_state; + ret = omap3_enter_idle(dev, new_state); /* Restore original PER state if it was modified */ if (per_next_state != per_saved_state) @@ -318,31 +301,22 @@ struct cpuidle_driver omap3_idle_driver = { .owner = THIS_MODULE, }; -/* Helper to fill the C-state common data*/ -static inline void _fill_cstate(struct cpuidle_driver *drv, +/* Helper to fill the C-state common data and register the driver_data */ +static inline struct omap3_idle_statedata *_fill_cstate( + struct cpuidle_device *dev, int idx, const char *descr) { - struct cpuidle_state *state = &drv->states[idx]; + struct omap3_idle_statedata *cx = &omap3_idle_data[idx]; + struct cpuidle_state *state = &dev->states[idx]; state->exit_latency = cpuidle_params_table[idx].exit_latency; state->target_residency = cpuidle_params_table[idx].target_residency; state->flags = CPUIDLE_FLAG_TIME_VALID; state->enter = omap3_enter_idle_bm; + cx->valid = cpuidle_params_table[idx].valid; sprintf(state->name, "C%d", idx + 1); strncpy(state->desc, descr, CPUIDLE_DESC_LEN); - -} - -/* Helper to register the driver_data */ -static inline struct omap3_idle_statedata *_fill_cstate_usage( - struct cpuidle_device *dev, - int idx) -{ - struct omap3_idle_statedata *cx = &omap3_idle_data[idx]; - struct cpuidle_state_usage *state_usage = &dev->states_usage[idx]; - - cx->valid = cpuidle_params_table[idx].valid; - cpuidle_set_statedata(state_usage, cx); + cpuidle_set_statedata(state, cx); return cx; } @@ -356,7 +330,6 @@ static inline struct omap3_idle_statedata *_fill_cstate_usage( int __init omap3_idle_init(void) { struct cpuidle_device *dev; - struct cpuidle_driver *drv = &omap3_idle_driver; struct omap3_idle_statedata *cx; mpu_pd = pwrdm_lookup("mpu_pwrdm"); @@ -364,52 +337,44 @@ int __init omap3_idle_init(void) per_pd = pwrdm_lookup("per_pwrdm"); cam_pd = pwrdm_lookup("cam_pwrdm"); - - drv->safe_state_index = -1; + cpuidle_register_driver(&omap3_idle_driver); dev = &per_cpu(omap3_idle_dev, smp_processor_id()); /* C1 . MPU WFI + Core active */ - _fill_cstate(drv, 0, "MPU ON + CORE ON"); - (&drv->states[0])->enter = omap3_enter_idle; - drv->safe_state_index = 0; - cx = _fill_cstate_usage(dev, 0); + cx = _fill_cstate(dev, 0, "MPU ON + CORE ON"); + (&dev->states[0])->enter = omap3_enter_idle; + dev->safe_state = &dev->states[0]; cx->valid = 1; /* C1 is always valid */ cx->mpu_state = PWRDM_POWER_ON; cx->core_state = PWRDM_POWER_ON; /* C2 . MPU WFI + Core inactive */ - _fill_cstate(drv, 1, "MPU ON + CORE ON"); - cx = _fill_cstate_usage(dev, 1); + cx = _fill_cstate(dev, 1, "MPU ON + CORE ON"); cx->mpu_state = PWRDM_POWER_ON; cx->core_state = PWRDM_POWER_ON; /* C3 . MPU CSWR + Core inactive */ - _fill_cstate(drv, 2, "MPU RET + CORE ON"); - cx = _fill_cstate_usage(dev, 2); + cx = _fill_cstate(dev, 2, "MPU RET + CORE ON"); cx->mpu_state = PWRDM_POWER_RET; cx->core_state = PWRDM_POWER_ON; /* C4 . MPU OFF + Core inactive */ - _fill_cstate(drv, 3, "MPU OFF + CORE ON"); - cx = _fill_cstate_usage(dev, 3); + cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON"); cx->mpu_state = PWRDM_POWER_OFF; cx->core_state = PWRDM_POWER_ON; /* C5 . MPU RET + Core RET */ - _fill_cstate(drv, 4, "MPU RET + CORE RET"); - cx = _fill_cstate_usage(dev, 4); + cx = _fill_cstate(dev, 4, "MPU RET + CORE RET"); cx->mpu_state = PWRDM_POWER_RET; cx->core_state = PWRDM_POWER_RET; /* C6 . MPU OFF + Core RET */ - _fill_cstate(drv, 5, "MPU OFF + CORE RET"); - cx = _fill_cstate_usage(dev, 5); + cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET"); cx->mpu_state = PWRDM_POWER_OFF; cx->core_state = PWRDM_POWER_RET; /* C7 . MPU OFF + Core OFF */ - _fill_cstate(drv, 6, "MPU OFF + CORE OFF"); - cx = _fill_cstate_usage(dev, 6); + cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF"); /* * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot * enable OFF mode in a stable form for previous revisions. @@ -423,9 +388,6 @@ int __init omap3_idle_init(void) cx->mpu_state = PWRDM_POWER_OFF; cx->core_state = PWRDM_POWER_OFF; - drv->state_count = OMAP3_NUM_STATES; - cpuidle_register_driver(&omap3_idle_driver); - dev->state_count = OMAP3_NUM_STATES; if (cpuidle_register_device(dev)) { printk(KERN_ERR "%s: CPUidle register device failed\n", |