diff options
| -rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 71 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap-mpuss-lowpower.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 21 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/powerdomain.c | 16 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/powerdomain.h | 4 |
5 files changed, 57 insertions, 59 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 207bc1c7759f..e6ae3fe5cdc6 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c | |||
| @@ -77,20 +77,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = { | |||
| 77 | 77 | ||
| 78 | static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; | 78 | static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; |
| 79 | 79 | ||
| 80 | static int _cpuidle_allow_idle(struct powerdomain *pwrdm, | ||
| 81 | struct clockdomain *clkdm) | ||
| 82 | { | ||
| 83 | clkdm_allow_idle(clkdm); | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int _cpuidle_deny_idle(struct powerdomain *pwrdm, | ||
| 88 | struct clockdomain *clkdm) | ||
| 89 | { | ||
| 90 | clkdm_deny_idle(clkdm); | ||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int __omap3_enter_idle(struct cpuidle_device *dev, | 80 | static int __omap3_enter_idle(struct cpuidle_device *dev, |
| 95 | struct cpuidle_driver *drv, | 81 | struct cpuidle_driver *drv, |
| 96 | int index) | 82 | int index) |
| @@ -108,8 +94,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, | |||
| 108 | 94 | ||
| 109 | /* Deny idle for C1 */ | 95 | /* Deny idle for C1 */ |
| 110 | if (index == 0) { | 96 | if (index == 0) { |
| 111 | pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); | 97 | clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]); |
| 112 | pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); | 98 | clkdm_deny_idle(core_pd->pwrdm_clkdms[0]); |
| 113 | } | 99 | } |
| 114 | 100 | ||
| 115 | /* | 101 | /* |
| @@ -131,8 +117,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, | |||
| 131 | 117 | ||
| 132 | /* Re-allow idle for C1 */ | 118 | /* Re-allow idle for C1 */ |
| 133 | if (index == 0) { | 119 | if (index == 0) { |
| 134 | pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); | 120 | clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]); |
| 135 | pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); | 121 | clkdm_allow_idle(core_pd->pwrdm_clkdms[0]); |
| 136 | } | 122 | } |
| 137 | 123 | ||
| 138 | return_sleep_time: | 124 | return_sleep_time: |
| @@ -178,7 +164,7 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
| 178 | u32 mpu_deepest_state = PWRDM_POWER_RET; | 164 | u32 mpu_deepest_state = PWRDM_POWER_RET; |
| 179 | u32 core_deepest_state = PWRDM_POWER_RET; | 165 | u32 core_deepest_state = PWRDM_POWER_RET; |
| 180 | int idx; | 166 | int idx; |
| 181 | int next_index = -1; | 167 | int next_index = 0; /* C1 is the default value */ |
| 182 | 168 | ||
| 183 | if (enable_off_mode) { | 169 | if (enable_off_mode) { |
| 184 | mpu_deepest_state = PWRDM_POWER_OFF; | 170 | mpu_deepest_state = PWRDM_POWER_OFF; |
| @@ -209,12 +195,6 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
| 209 | } | 195 | } |
| 210 | } | 196 | } |
| 211 | 197 | ||
| 212 | /* | ||
| 213 | * C1 is always valid. | ||
| 214 | * So, no need to check for 'next_index == -1' outside | ||
| 215 | * this loop. | ||
| 216 | */ | ||
| 217 | |||
| 218 | return next_index; | 198 | return next_index; |
| 219 | } | 199 | } |
| 220 | 200 | ||
| @@ -228,23 +208,22 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
| 228 | * the device to the specified or a safer state. | 208 | * the device to the specified or a safer state. |
| 229 | */ | 209 | */ |
| 230 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, | 210 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, |
| 231 | struct cpuidle_driver *drv, | 211 | struct cpuidle_driver *drv, |
| 232 | int index) | 212 | int index) |
| 233 | { | 213 | { |
| 234 | int new_state_idx; | 214 | int new_state_idx; |
| 235 | u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; | 215 | u32 core_next_state, per_next_state = 0, per_saved_state = 0; |
| 236 | struct omap3_idle_statedata *cx; | 216 | struct omap3_idle_statedata *cx; |
| 237 | int ret; | 217 | int ret; |
| 238 | 218 | ||
| 239 | /* | 219 | /* |
| 240 | * Prevent idle completely if CAM is active. | 220 | * Use only C1 if CAM is active. |
| 241 | * CAM does not have wakeup capability in OMAP3. | 221 | * CAM does not have wakeup capability in OMAP3. |
| 242 | */ | 222 | */ |
| 243 | cam_state = pwrdm_read_pwrst(cam_pd); | 223 | if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON) |
| 244 | if (cam_state == PWRDM_POWER_ON) { | ||
| 245 | new_state_idx = drv->safe_state_index; | 224 | new_state_idx = drv->safe_state_index; |
| 246 | goto select_state; | 225 | else |
| 247 | } | 226 | new_state_idx = next_valid_state(dev, drv, index); |
| 248 | 227 | ||
| 249 | /* | 228 | /* |
| 250 | * FIXME: we currently manage device-specific idle states | 229 | * FIXME: we currently manage device-specific idle states |
| @@ -254,24 +233,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, | |||
| 254 | * its own code. | 233 | * its own code. |
| 255 | */ | 234 | */ |
| 256 | 235 | ||
| 257 | /* | 236 | /* Program PER state */ |
| 258 | * Prevent PER off if CORE is not in retention or off as this | 237 | cx = &omap3_idle_data[new_state_idx]; |
| 259 | * would disable PER wakeups completely. | ||
| 260 | */ | ||
| 261 | cx = &omap3_idle_data[index]; | ||
| 262 | core_next_state = cx->core_state; | 238 | core_next_state = cx->core_state; |
| 263 | per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); | 239 | per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); |
| 264 | if ((per_next_state == PWRDM_POWER_OFF) && | 240 | if (new_state_idx == 0) { |
| 265 | (core_next_state > PWRDM_POWER_RET)) | 241 | /* In C1 do not allow PER state lower than CORE state */ |
| 266 | per_next_state = PWRDM_POWER_RET; | 242 | if (per_next_state < core_next_state) |
| 243 | per_next_state = core_next_state; | ||
| 244 | } else { | ||
| 245 | /* | ||
| 246 | * Prevent PER OFF if CORE is not in RETention or OFF as this | ||
| 247 | * would disable PER wakeups completely. | ||
| 248 | */ | ||
| 249 | if ((per_next_state == PWRDM_POWER_OFF) && | ||
| 250 | (core_next_state > PWRDM_POWER_RET)) | ||
| 251 | per_next_state = PWRDM_POWER_RET; | ||
| 252 | } | ||
| 267 | 253 | ||
| 268 | /* Are we changing PER target state? */ | 254 | /* Are we changing PER target state? */ |
| 269 | if (per_next_state != per_saved_state) | 255 | if (per_next_state != per_saved_state) |
| 270 | pwrdm_set_next_pwrst(per_pd, per_next_state); | 256 | pwrdm_set_next_pwrst(per_pd, per_next_state); |
| 271 | 257 | ||
| 272 | new_state_idx = next_valid_state(dev, drv, index); | ||
| 273 | |||
| 274 | select_state: | ||
| 275 | ret = omap3_enter_idle(dev, drv, new_state_idx); | 258 | ret = omap3_enter_idle(dev, drv, new_state_idx); |
| 276 | 259 | ||
| 277 | /* Restore original PER state if it was modified */ | 260 | /* Restore original PER state if it was modified */ |
| @@ -288,7 +271,7 @@ struct cpuidle_driver omap3_idle_driver = { | |||
| 288 | .owner = THIS_MODULE, | 271 | .owner = THIS_MODULE, |
| 289 | .states = { | 272 | .states = { |
| 290 | { | 273 | { |
| 291 | .enter = omap3_enter_idle, | 274 | .enter = omap3_enter_idle_bm, |
| 292 | .exit_latency = 2 + 2, | 275 | .exit_latency = 2 + 2, |
| 293 | .target_residency = 5, | 276 | .target_residency = 5, |
| 294 | .flags = CPUIDLE_FLAG_TIME_VALID, | 277 | .flags = CPUIDLE_FLAG_TIME_VALID, |
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 13670aa84e58..e35a86bf4e1d 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c | |||
| @@ -255,7 +255,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) | |||
| 255 | return -ENXIO; | 255 | return -ENXIO; |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | pwrdm_pre_transition(); | 258 | pwrdm_pre_transition(NULL); |
| 259 | 259 | ||
| 260 | /* | 260 | /* |
| 261 | * Check MPUSS next state and save interrupt controller if needed. | 261 | * 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 | wakeup_cpu = smp_processor_id(); | 287 | wakeup_cpu = smp_processor_id(); |
| 288 | set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON); | 288 | set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON); |
| 289 | 289 | ||
| 290 | pwrdm_post_transition(); | 290 | pwrdm_post_transition(NULL); |
| 291 | 291 | ||
| 292 | return 0; | 292 | return 0; |
| 293 | } | 293 | } |
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index e67d898433fb..e63fdd02c6f5 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c | |||
| @@ -70,7 +70,6 @@ void (*omap3_do_wfi_sram)(void); | |||
| 70 | 70 | ||
| 71 | static struct powerdomain *mpu_pwrdm, *neon_pwrdm; | 71 | static struct powerdomain *mpu_pwrdm, *neon_pwrdm; |
| 72 | static struct powerdomain *core_pwrdm, *per_pwrdm; | 72 | static struct powerdomain *core_pwrdm, *per_pwrdm; |
| 73 | static struct powerdomain *cam_pwrdm; | ||
| 74 | 73 | ||
| 75 | static void omap3_core_save_context(void) | 74 | static void omap3_core_save_context(void) |
| 76 | { | 75 | { |
| @@ -273,16 +272,21 @@ void omap_sram_idle(void) | |||
| 273 | per_next_state = pwrdm_read_next_pwrst(per_pwrdm); | 272 | per_next_state = pwrdm_read_next_pwrst(per_pwrdm); |
| 274 | core_next_state = pwrdm_read_next_pwrst(core_pwrdm); | 273 | core_next_state = pwrdm_read_next_pwrst(core_pwrdm); |
| 275 | 274 | ||
| 276 | pwrdm_pre_transition(); | 275 | if (mpu_next_state < PWRDM_POWER_ON) { |
| 276 | pwrdm_pre_transition(mpu_pwrdm); | ||
| 277 | pwrdm_pre_transition(neon_pwrdm); | ||
| 278 | } | ||
| 277 | 279 | ||
| 278 | /* PER */ | 280 | /* PER */ |
| 279 | if (per_next_state < PWRDM_POWER_ON) { | 281 | if (per_next_state < PWRDM_POWER_ON) { |
| 282 | pwrdm_pre_transition(per_pwrdm); | ||
| 280 | per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; | 283 | per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; |
| 281 | omap2_gpio_prepare_for_idle(per_going_off); | 284 | omap2_gpio_prepare_for_idle(per_going_off); |
| 282 | } | 285 | } |
| 283 | 286 | ||
| 284 | /* CORE */ | 287 | /* CORE */ |
| 285 | if (core_next_state < PWRDM_POWER_ON) { | 288 | if (core_next_state < PWRDM_POWER_ON) { |
| 289 | pwrdm_pre_transition(core_pwrdm); | ||
| 286 | if (core_next_state == PWRDM_POWER_OFF) { | 290 | if (core_next_state == PWRDM_POWER_OFF) { |
| 287 | omap3_core_save_context(); | 291 | omap3_core_save_context(); |
| 288 | omap3_cm_save_context(); | 292 | omap3_cm_save_context(); |
| @@ -335,16 +339,20 @@ void omap_sram_idle(void) | |||
| 335 | omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK, | 339 | omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK, |
| 336 | OMAP3430_GR_MOD, | 340 | OMAP3430_GR_MOD, |
| 337 | OMAP3_PRM_VOLTCTRL_OFFSET); | 341 | OMAP3_PRM_VOLTCTRL_OFFSET); |
| 342 | pwrdm_post_transition(core_pwrdm); | ||
| 338 | } | 343 | } |
| 339 | omap3_intc_resume_idle(); | 344 | omap3_intc_resume_idle(); |
| 340 | 345 | ||
| 341 | pwrdm_post_transition(); | ||
| 342 | |||
| 343 | /* PER */ | 346 | /* PER */ |
| 344 | if (per_next_state < PWRDM_POWER_ON) | 347 | if (per_next_state < PWRDM_POWER_ON) { |
| 345 | omap2_gpio_resume_after_idle(); | 348 | omap2_gpio_resume_after_idle(); |
| 349 | pwrdm_post_transition(per_pwrdm); | ||
| 350 | } | ||
| 346 | 351 | ||
| 347 | clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]); | 352 | if (mpu_next_state < PWRDM_POWER_ON) { |
| 353 | pwrdm_post_transition(mpu_pwrdm); | ||
| 354 | pwrdm_post_transition(neon_pwrdm); | ||
| 355 | } | ||
| 348 | } | 356 | } |
| 349 | 357 | ||
| 350 | static void omap3_pm_idle(void) | 358 | static void omap3_pm_idle(void) |
| @@ -705,7 +713,6 @@ int __init omap3_pm_init(void) | |||
| 705 | neon_pwrdm = pwrdm_lookup("neon_pwrdm"); | 713 | neon_pwrdm = pwrdm_lookup("neon_pwrdm"); |
| 706 | per_pwrdm = pwrdm_lookup("per_pwrdm"); | 714 | per_pwrdm = pwrdm_lookup("per_pwrdm"); |
| 707 | core_pwrdm = pwrdm_lookup("core_pwrdm"); | 715 | core_pwrdm = pwrdm_lookup("core_pwrdm"); |
| 708 | cam_pwrdm = pwrdm_lookup("cam_pwrdm"); | ||
| 709 | 716 | ||
| 710 | neon_clkdm = clkdm_lookup("neon_clkdm"); | 717 | neon_clkdm = clkdm_lookup("neon_clkdm"); |
| 711 | mpu_clkdm = clkdm_lookup("mpu_clkdm"); | 718 | mpu_clkdm = clkdm_lookup("mpu_clkdm"); |
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 96114901b932..eefe179045e6 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c | |||
| @@ -981,15 +981,23 @@ int pwrdm_state_switch(struct powerdomain *pwrdm) | |||
| 981 | return ret; | 981 | return ret; |
| 982 | } | 982 | } |
| 983 | 983 | ||
| 984 | int pwrdm_pre_transition(void) | 984 | int pwrdm_pre_transition(struct powerdomain *pwrdm) |
| 985 | { | 985 | { |
| 986 | pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); | 986 | if (pwrdm) |
| 987 | _pwrdm_pre_transition_cb(pwrdm, NULL); | ||
| 988 | else | ||
| 989 | pwrdm_for_each(_pwrdm_pre_transition_cb, NULL); | ||
| 990 | |||
| 987 | return 0; | 991 | return 0; |
| 988 | } | 992 | } |
| 989 | 993 | ||
| 990 | int pwrdm_post_transition(void) | 994 | int pwrdm_post_transition(struct powerdomain *pwrdm) |
| 991 | { | 995 | { |
| 992 | pwrdm_for_each(_pwrdm_post_transition_cb, NULL); | 996 | if (pwrdm) |
| 997 | _pwrdm_post_transition_cb(pwrdm, NULL); | ||
| 998 | else | ||
| 999 | pwrdm_for_each(_pwrdm_post_transition_cb, NULL); | ||
| 1000 | |||
| 993 | return 0; | 1001 | return 0; |
| 994 | } | 1002 | } |
| 995 | 1003 | ||
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 8f88d65c46ea..a6a4604801ad 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h | |||
| @@ -213,8 +213,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm); | |||
| 213 | int pwrdm_wait_transition(struct powerdomain *pwrdm); | 213 | int pwrdm_wait_transition(struct powerdomain *pwrdm); |
| 214 | 214 | ||
| 215 | int pwrdm_state_switch(struct powerdomain *pwrdm); | 215 | int pwrdm_state_switch(struct powerdomain *pwrdm); |
| 216 | int pwrdm_pre_transition(void); | 216 | int pwrdm_pre_transition(struct powerdomain *pwrdm); |
| 217 | int pwrdm_post_transition(void); | 217 | int pwrdm_post_transition(struct powerdomain *pwrdm); |
| 218 | int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); | 218 | int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); |
| 219 | int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); | 219 | int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); |
| 220 | bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); | 220 | bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); |
