diff options
Diffstat (limited to 'arch/arm/mach-omap2/cpuidle34xx.c')
-rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 79 |
1 files changed, 27 insertions, 52 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 207bc1c7759f..f2a49a48ef59 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c | |||
@@ -36,8 +36,6 @@ | |||
36 | #include "control.h" | 36 | #include "control.h" |
37 | #include "common.h" | 37 | #include "common.h" |
38 | 38 | ||
39 | #ifdef CONFIG_CPU_IDLE | ||
40 | |||
41 | /* Mach specific information to be recorded in the C-state driver_data */ | 39 | /* Mach specific information to be recorded in the C-state driver_data */ |
42 | struct omap3_idle_statedata { | 40 | struct omap3_idle_statedata { |
43 | u32 mpu_state; | 41 | u32 mpu_state; |
@@ -77,20 +75,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = { | |||
77 | 75 | ||
78 | static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; | 76 | static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; |
79 | 77 | ||
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, | 78 | static int __omap3_enter_idle(struct cpuidle_device *dev, |
95 | struct cpuidle_driver *drv, | 79 | struct cpuidle_driver *drv, |
96 | int index) | 80 | int index) |
@@ -108,8 +92,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, | |||
108 | 92 | ||
109 | /* Deny idle for C1 */ | 93 | /* Deny idle for C1 */ |
110 | if (index == 0) { | 94 | if (index == 0) { |
111 | pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); | 95 | clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]); |
112 | pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); | 96 | clkdm_deny_idle(core_pd->pwrdm_clkdms[0]); |
113 | } | 97 | } |
114 | 98 | ||
115 | /* | 99 | /* |
@@ -131,8 +115,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev, | |||
131 | 115 | ||
132 | /* Re-allow idle for C1 */ | 116 | /* Re-allow idle for C1 */ |
133 | if (index == 0) { | 117 | if (index == 0) { |
134 | pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); | 118 | clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]); |
135 | pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); | 119 | clkdm_allow_idle(core_pd->pwrdm_clkdms[0]); |
136 | } | 120 | } |
137 | 121 | ||
138 | return_sleep_time: | 122 | return_sleep_time: |
@@ -178,7 +162,7 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
178 | u32 mpu_deepest_state = PWRDM_POWER_RET; | 162 | u32 mpu_deepest_state = PWRDM_POWER_RET; |
179 | u32 core_deepest_state = PWRDM_POWER_RET; | 163 | u32 core_deepest_state = PWRDM_POWER_RET; |
180 | int idx; | 164 | int idx; |
181 | int next_index = -1; | 165 | int next_index = 0; /* C1 is the default value */ |
182 | 166 | ||
183 | if (enable_off_mode) { | 167 | if (enable_off_mode) { |
184 | mpu_deepest_state = PWRDM_POWER_OFF; | 168 | mpu_deepest_state = PWRDM_POWER_OFF; |
@@ -209,12 +193,6 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
209 | } | 193 | } |
210 | } | 194 | } |
211 | 195 | ||
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; | 196 | return next_index; |
219 | } | 197 | } |
220 | 198 | ||
@@ -228,23 +206,22 @@ static int next_valid_state(struct cpuidle_device *dev, | |||
228 | * the device to the specified or a safer state. | 206 | * the device to the specified or a safer state. |
229 | */ | 207 | */ |
230 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, | 208 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, |
231 | struct cpuidle_driver *drv, | 209 | struct cpuidle_driver *drv, |
232 | int index) | 210 | int index) |
233 | { | 211 | { |
234 | int new_state_idx; | 212 | int new_state_idx; |
235 | u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; | 213 | u32 core_next_state, per_next_state = 0, per_saved_state = 0; |
236 | struct omap3_idle_statedata *cx; | 214 | struct omap3_idle_statedata *cx; |
237 | int ret; | 215 | int ret; |
238 | 216 | ||
239 | /* | 217 | /* |
240 | * Prevent idle completely if CAM is active. | 218 | * Use only C1 if CAM is active. |
241 | * CAM does not have wakeup capability in OMAP3. | 219 | * CAM does not have wakeup capability in OMAP3. |
242 | */ | 220 | */ |
243 | cam_state = pwrdm_read_pwrst(cam_pd); | 221 | if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON) |
244 | if (cam_state == PWRDM_POWER_ON) { | ||
245 | new_state_idx = drv->safe_state_index; | 222 | new_state_idx = drv->safe_state_index; |
246 | goto select_state; | 223 | else |
247 | } | 224 | new_state_idx = next_valid_state(dev, drv, index); |
248 | 225 | ||
249 | /* | 226 | /* |
250 | * FIXME: we currently manage device-specific idle states | 227 | * FIXME: we currently manage device-specific idle states |
@@ -254,24 +231,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, | |||
254 | * its own code. | 231 | * its own code. |
255 | */ | 232 | */ |
256 | 233 | ||
257 | /* | 234 | /* Program PER state */ |
258 | * Prevent PER off if CORE is not in retention or off as this | 235 | 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; | 236 | core_next_state = cx->core_state; |
263 | per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); | 237 | per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); |
264 | if ((per_next_state == PWRDM_POWER_OFF) && | 238 | if (new_state_idx == 0) { |
265 | (core_next_state > PWRDM_POWER_RET)) | 239 | /* In C1 do not allow PER state lower than CORE state */ |
266 | per_next_state = PWRDM_POWER_RET; | 240 | if (per_next_state < core_next_state) |
241 | per_next_state = core_next_state; | ||
242 | } else { | ||
243 | /* | ||
244 | * Prevent PER OFF if CORE is not in RETention or OFF as this | ||
245 | * would disable PER wakeups completely. | ||
246 | */ | ||
247 | if ((per_next_state == PWRDM_POWER_OFF) && | ||
248 | (core_next_state > PWRDM_POWER_RET)) | ||
249 | per_next_state = PWRDM_POWER_RET; | ||
250 | } | ||
267 | 251 | ||
268 | /* Are we changing PER target state? */ | 252 | /* Are we changing PER target state? */ |
269 | if (per_next_state != per_saved_state) | 253 | if (per_next_state != per_saved_state) |
270 | pwrdm_set_next_pwrst(per_pd, per_next_state); | 254 | pwrdm_set_next_pwrst(per_pd, per_next_state); |
271 | 255 | ||
272 | new_state_idx = next_valid_state(dev, drv, index); | ||
273 | |||
274 | select_state: | ||
275 | ret = omap3_enter_idle(dev, drv, new_state_idx); | 256 | ret = omap3_enter_idle(dev, drv, new_state_idx); |
276 | 257 | ||
277 | /* Restore original PER state if it was modified */ | 258 | /* Restore original PER state if it was modified */ |
@@ -288,7 +269,7 @@ struct cpuidle_driver omap3_idle_driver = { | |||
288 | .owner = THIS_MODULE, | 269 | .owner = THIS_MODULE, |
289 | .states = { | 270 | .states = { |
290 | { | 271 | { |
291 | .enter = omap3_enter_idle, | 272 | .enter = omap3_enter_idle_bm, |
292 | .exit_latency = 2 + 2, | 273 | .exit_latency = 2 + 2, |
293 | .target_residency = 5, | 274 | .target_residency = 5, |
294 | .flags = CPUIDLE_FLAG_TIME_VALID, | 275 | .flags = CPUIDLE_FLAG_TIME_VALID, |
@@ -379,9 +360,3 @@ int __init omap3_idle_init(void) | |||
379 | 360 | ||
380 | return 0; | 361 | return 0; |
381 | } | 362 | } |
382 | #else | ||
383 | int __init omap3_idle_init(void) | ||
384 | { | ||
385 | return 0; | ||
386 | } | ||
387 | #endif /* CONFIG_CPU_IDLE */ | ||