diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap2/cpuidle34xx.c | 52 |
1 files changed, 19 insertions, 33 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index f9c8676b1f4c..dd31e539274c 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c | |||
@@ -71,13 +71,6 @@ struct omap3_idle_statedata omap3_idle_data[OMAP3_NUM_STATES]; | |||
71 | 71 | ||
72 | struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; | 72 | struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd; |
73 | 73 | ||
74 | static int omap3_idle_bm_check(void) | ||
75 | { | ||
76 | if (!omap3_can_sleep()) | ||
77 | return 1; | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int _cpuidle_allow_idle(struct powerdomain *pwrdm, | 74 | static int _cpuidle_allow_idle(struct powerdomain *pwrdm, |
82 | struct clockdomain *clkdm) | 75 | struct clockdomain *clkdm) |
83 | { | 76 | { |
@@ -157,9 +150,7 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, | |||
157 | struct cpuidle_state *curr) | 150 | struct cpuidle_state *curr) |
158 | { | 151 | { |
159 | struct cpuidle_state *next = NULL; | 152 | struct cpuidle_state *next = NULL; |
160 | struct omap3_idle_statedata *cx; | 153 | struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); |
161 | |||
162 | cx = cpuidle_get_statedata(curr); | ||
163 | 154 | ||
164 | /* Check if current state is valid */ | 155 | /* Check if current state is valid */ |
165 | if (cx->valid) { | 156 | if (cx->valid) { |
@@ -167,9 +158,7 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, | |||
167 | } else { | 158 | } else { |
168 | int idx = OMAP3_NUM_STATES - 1; | 159 | int idx = OMAP3_NUM_STATES - 1; |
169 | 160 | ||
170 | /* | 161 | /* Reach the current state starting at highest C-state */ |
171 | * Reach the current state starting at highest C-state | ||
172 | */ | ||
173 | for (; idx >= 0; idx--) { | 162 | for (; idx >= 0; idx--) { |
174 | if (&dev->states[idx] == curr) { | 163 | if (&dev->states[idx] == curr) { |
175 | next = &dev->states[idx]; | 164 | next = &dev->states[idx]; |
@@ -177,9 +166,7 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, | |||
177 | } | 166 | } |
178 | } | 167 | } |
179 | 168 | ||
180 | /* | 169 | /* Should never hit this condition */ |
181 | * Should never hit this condition. | ||
182 | */ | ||
183 | WARN_ON(next == NULL); | 170 | WARN_ON(next == NULL); |
184 | 171 | ||
185 | /* | 172 | /* |
@@ -214,29 +201,16 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, | |||
214 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, | 201 | static int omap3_enter_idle_bm(struct cpuidle_device *dev, |
215 | struct cpuidle_state *state) | 202 | struct cpuidle_state *state) |
216 | { | 203 | { |
217 | struct cpuidle_state *new_state = next_valid_state(dev, state); | 204 | struct cpuidle_state *new_state; |
218 | u32 core_next_state, per_next_state = 0, per_saved_state = 0; | 205 | u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; |
219 | u32 cam_state; | ||
220 | struct omap3_idle_statedata *cx; | 206 | struct omap3_idle_statedata *cx; |
221 | int ret; | 207 | int ret; |
222 | 208 | ||
223 | if (omap3_idle_bm_check()) { | 209 | if (!omap3_can_sleep()) { |
224 | BUG_ON(!dev->safe_state); | ||
225 | new_state = dev->safe_state; | 210 | new_state = dev->safe_state; |
226 | goto select_state; | 211 | goto select_state; |
227 | } | 212 | } |
228 | 213 | ||
229 | cx = cpuidle_get_statedata(state); | ||
230 | core_next_state = cx->core_state; | ||
231 | |||
232 | /* | ||
233 | * FIXME: we currently manage device-specific idle states | ||
234 | * for PER and CORE in combination with CPU-specific | ||
235 | * idle states. This is wrong, and device-specific | ||
236 | * idle management needs to be separated out into | ||
237 | * its own code. | ||
238 | */ | ||
239 | |||
240 | /* | 214 | /* |
241 | * Prevent idle completely if CAM is active. | 215 | * Prevent idle completely if CAM is active. |
242 | * CAM does not have wakeup capability in OMAP3. | 216 | * CAM does not have wakeup capability in OMAP3. |
@@ -248,9 +222,19 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, | |||
248 | } | 222 | } |
249 | 223 | ||
250 | /* | 224 | /* |
225 | * FIXME: we currently manage device-specific idle states | ||
226 | * for PER and CORE in combination with CPU-specific | ||
227 | * idle states. This is wrong, and device-specific | ||
228 | * idle management needs to be separated out into | ||
229 | * its own code. | ||
230 | */ | ||
231 | |||
232 | /* | ||
251 | * Prevent PER off if CORE is not in retention or off as this | 233 | * Prevent PER off if CORE is not in retention or off as this |
252 | * would disable PER wakeups completely. | 234 | * would disable PER wakeups completely. |
253 | */ | 235 | */ |
236 | cx = cpuidle_get_statedata(state); | ||
237 | core_next_state = cx->core_state; | ||
254 | per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); | 238 | per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); |
255 | if ((per_next_state == PWRDM_POWER_OFF) && | 239 | if ((per_next_state == PWRDM_POWER_OFF) && |
256 | (core_next_state > PWRDM_POWER_RET)) | 240 | (core_next_state > PWRDM_POWER_RET)) |
@@ -260,6 +244,8 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev, | |||
260 | if (per_next_state != per_saved_state) | 244 | if (per_next_state != per_saved_state) |
261 | pwrdm_set_next_pwrst(per_pd, per_next_state); | 245 | pwrdm_set_next_pwrst(per_pd, per_next_state); |
262 | 246 | ||
247 | new_state = next_valid_state(dev, state); | ||
248 | |||
263 | select_state: | 249 | select_state: |
264 | dev->last_state = new_state; | 250 | dev->last_state = new_state; |
265 | ret = omap3_enter_idle(dev, new_state); | 251 | ret = omap3_enter_idle(dev, new_state); |
@@ -320,7 +306,7 @@ struct cpuidle_driver omap3_idle_driver = { | |||
320 | .owner = THIS_MODULE, | 306 | .owner = THIS_MODULE, |
321 | }; | 307 | }; |
322 | 308 | ||
323 | /* Fill in the state data from the mach tables and register the driver_data */ | 309 | /* Helper to fill the C-state common data and register the driver_data */ |
324 | static inline struct omap3_idle_statedata *_fill_cstate( | 310 | static inline struct omap3_idle_statedata *_fill_cstate( |
325 | struct cpuidle_device *dev, | 311 | struct cpuidle_device *dev, |
326 | int idx, const char *descr) | 312 | int idx, const char *descr) |