aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/cpuidle34xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/cpuidle34xx.c')
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c79
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 */
42struct omap3_idle_statedata { 40struct 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
78static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; 76static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
79 77
80static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
81 struct clockdomain *clkdm)
82{
83 clkdm_allow_idle(clkdm);
84 return 0;
85}
86
87static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
88 struct clockdomain *clkdm)
89{
90 clkdm_deny_idle(clkdm);
91 return 0;
92}
93
94static int __omap3_enter_idle(struct cpuidle_device *dev, 78static 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
138return_sleep_time: 122return_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 */
230static int omap3_enter_idle_bm(struct cpuidle_device *dev, 208static 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
274select_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
383int __init omap3_idle_init(void)
384{
385 return 0;
386}
387#endif /* CONFIG_CPU_IDLE */