aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/cpuidle34xx.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2011-11-23 17:46:10 -0500
committerTony Lindgren <tony@atomide.com>2011-11-23 17:46:10 -0500
commit52f3a41e0aca5625fbd118ed57a4debb25817e99 (patch)
tree86730c862fc97eef5f1eb1a81bf74bf2a8a36754 /arch/arm/mach-omap2/cpuidle34xx.c
parente9b7086b80c4d9e354f4edc9e280ae85a60df408 (diff)
parent8770b07c2dff3cec2c751b289ee690137c88ea54 (diff)
Merge branch 'fixes-v3.2-rc2' into fixes
Diffstat (limited to 'arch/arm/mach-omap2/cpuidle34xx.c')
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c133
1 files changed, 85 insertions, 48 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 2e0fa5a4aaeb..942bb4f19f9f 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -89,17 +89,21 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
89/** 89/**
90 * omap3_enter_idle - Programs OMAP3 to enter the specified state 90 * omap3_enter_idle - Programs OMAP3 to enter the specified state
91 * @dev: cpuidle device 91 * @dev: cpuidle device
92 * @state: The target state to be programmed 92 * @drv: cpuidle driver
93 * @index: the index of state to be entered
93 * 94 *
94 * Called from the CPUidle framework to program the device to the 95 * Called from the CPUidle framework to program the device to the
95 * specified target state selected by the governor. 96 * specified target state selected by the governor.
96 */ 97 */
97static int omap3_enter_idle(struct cpuidle_device *dev, 98static int omap3_enter_idle(struct cpuidle_device *dev,
98 struct cpuidle_state *state) 99 struct cpuidle_driver *drv,
100 int index)
99{ 101{
100 struct omap3_idle_statedata *cx = cpuidle_get_statedata(state); 102 struct omap3_idle_statedata *cx =
103 cpuidle_get_statedata(&dev->states_usage[index]);
101 struct timespec ts_preidle, ts_postidle, ts_idle; 104 struct timespec ts_preidle, ts_postidle, ts_idle;
102 u32 mpu_state = cx->mpu_state, core_state = cx->core_state; 105 u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
106 int idle_time;
103 107
104 /* Used to keep track of the total time in idle */ 108 /* Used to keep track of the total time in idle */
105 getnstimeofday(&ts_preidle); 109 getnstimeofday(&ts_preidle);
@@ -114,7 +118,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
114 goto return_sleep_time; 118 goto return_sleep_time;
115 119
116 /* Deny idle for C1 */ 120 /* Deny idle for C1 */
117 if (state == &dev->states[0]) { 121 if (index == 0) {
118 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); 122 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
119 pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); 123 pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
120 } 124 }
@@ -123,7 +127,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
123 omap_sram_idle(); 127 omap_sram_idle();
124 128
125 /* Re-allow idle for C1 */ 129 /* Re-allow idle for C1 */
126 if (state == &dev->states[0]) { 130 if (index == 0) {
127 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); 131 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
128 pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); 132 pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
129 } 133 }
@@ -135,28 +139,38 @@ return_sleep_time:
135 local_irq_enable(); 139 local_irq_enable();
136 local_fiq_enable(); 140 local_fiq_enable();
137 141
138 return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; 142 idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \
143 USEC_PER_SEC;
144
145 /* Update cpuidle counters */
146 dev->last_residency = idle_time;
147
148 return index;
139} 149}
140 150
141/** 151/**
142 * next_valid_state - Find next valid C-state 152 * next_valid_state - Find next valid C-state
143 * @dev: cpuidle device 153 * @dev: cpuidle device
144 * @state: Currently selected C-state 154 * @drv: cpuidle driver
155 * @index: Index of currently selected c-state
145 * 156 *
146 * If the current state is valid, it is returned back to the caller. 157 * If the state corresponding to index is valid, index is returned back
147 * Else, this function searches for a lower c-state which is still 158 * to the caller. Else, this function searches for a lower c-state which is
148 * valid. 159 * still valid (as defined in omap3_power_states[]) and returns its index.
149 * 160 *
150 * A state is valid if the 'valid' field is enabled and 161 * A state is valid if the 'valid' field is enabled and
151 * if it satisfies the enable_off_mode condition. 162 * if it satisfies the enable_off_mode condition.
152 */ 163 */
153static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, 164static int next_valid_state(struct cpuidle_device *dev,
154 struct cpuidle_state *curr) 165 struct cpuidle_driver *drv,
166 int index)
155{ 167{
156 struct cpuidle_state *next = NULL; 168 struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
157 struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); 169 struct cpuidle_state *curr = &drv->states[index];
170 struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
158 u32 mpu_deepest_state = PWRDM_POWER_RET; 171 u32 mpu_deepest_state = PWRDM_POWER_RET;
159 u32 core_deepest_state = PWRDM_POWER_RET; 172 u32 core_deepest_state = PWRDM_POWER_RET;
173 int next_index = -1;
160 174
161 if (enable_off_mode) { 175 if (enable_off_mode) {
162 mpu_deepest_state = PWRDM_POWER_OFF; 176 mpu_deepest_state = PWRDM_POWER_OFF;
@@ -173,20 +187,20 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
173 if ((cx->valid) && 187 if ((cx->valid) &&
174 (cx->mpu_state >= mpu_deepest_state) && 188 (cx->mpu_state >= mpu_deepest_state) &&
175 (cx->core_state >= core_deepest_state)) { 189 (cx->core_state >= core_deepest_state)) {
176 return curr; 190 return index;
177 } else { 191 } else {
178 int idx = OMAP3_NUM_STATES - 1; 192 int idx = OMAP3_NUM_STATES - 1;
179 193
180 /* Reach the current state starting at highest C-state */ 194 /* Reach the current state starting at highest C-state */
181 for (; idx >= 0; idx--) { 195 for (; idx >= 0; idx--) {
182 if (&dev->states[idx] == curr) { 196 if (&drv->states[idx] == curr) {
183 next = &dev->states[idx]; 197 next_index = idx;
184 break; 198 break;
185 } 199 }
186 } 200 }
187 201
188 /* Should never hit this condition */ 202 /* Should never hit this condition */
189 WARN_ON(next == NULL); 203 WARN_ON(next_index == -1);
190 204
191 /* 205 /*
192 * Drop to next valid state. 206 * Drop to next valid state.
@@ -194,41 +208,44 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
194 */ 208 */
195 idx--; 209 idx--;
196 for (; idx >= 0; idx--) { 210 for (; idx >= 0; idx--) {
197 cx = cpuidle_get_statedata(&dev->states[idx]); 211 cx = cpuidle_get_statedata(&dev->states_usage[idx]);
198 if ((cx->valid) && 212 if ((cx->valid) &&
199 (cx->mpu_state >= mpu_deepest_state) && 213 (cx->mpu_state >= mpu_deepest_state) &&
200 (cx->core_state >= core_deepest_state)) { 214 (cx->core_state >= core_deepest_state)) {
201 next = &dev->states[idx]; 215 next_index = idx;
202 break; 216 break;
203 } 217 }
204 } 218 }
205 /* 219 /*
206 * C1 is always valid. 220 * C1 is always valid.
207 * So, no need to check for 'next==NULL' outside this loop. 221 * So, no need to check for 'next_index == -1' outside
222 * this loop.
208 */ 223 */
209 } 224 }
210 225
211 return next; 226 return next_index;
212} 227}
213 228
214/** 229/**
215 * omap3_enter_idle_bm - Checks for any bus activity 230 * omap3_enter_idle_bm - Checks for any bus activity
216 * @dev: cpuidle device 231 * @dev: cpuidle device
217 * @state: The target state to be programmed 232 * @drv: cpuidle driver
233 * @index: array index of target state to be programmed
218 * 234 *
219 * This function checks for any pending activity and then programs 235 * This function checks for any pending activity and then programs
220 * the device to the specified or a safer state. 236 * the device to the specified or a safer state.
221 */ 237 */
222static int omap3_enter_idle_bm(struct cpuidle_device *dev, 238static int omap3_enter_idle_bm(struct cpuidle_device *dev,
223 struct cpuidle_state *state) 239 struct cpuidle_driver *drv,
240 int index)
224{ 241{
225 struct cpuidle_state *new_state; 242 int new_state_idx;
226 u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; 243 u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
227 struct omap3_idle_statedata *cx; 244 struct omap3_idle_statedata *cx;
228 int ret; 245 int ret;
229 246
230 if (!omap3_can_sleep()) { 247 if (!omap3_can_sleep()) {
231 new_state = dev->safe_state; 248 new_state_idx = drv->safe_state_index;
232 goto select_state; 249 goto select_state;
233 } 250 }
234 251
@@ -238,7 +255,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
238 */ 255 */
239 cam_state = pwrdm_read_pwrst(cam_pd); 256 cam_state = pwrdm_read_pwrst(cam_pd);
240 if (cam_state == PWRDM_POWER_ON) { 257 if (cam_state == PWRDM_POWER_ON) {
241 new_state = dev->safe_state; 258 new_state_idx = drv->safe_state_index;
242 goto select_state; 259 goto select_state;
243 } 260 }
244 261
@@ -254,7 +271,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
254 * Prevent PER off if CORE is not in retention or off as this 271 * Prevent PER off if CORE is not in retention or off as this
255 * would disable PER wakeups completely. 272 * would disable PER wakeups completely.
256 */ 273 */
257 cx = cpuidle_get_statedata(state); 274 cx = cpuidle_get_statedata(&dev->states_usage[index]);
258 core_next_state = cx->core_state; 275 core_next_state = cx->core_state;
259 per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd); 276 per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
260 if ((per_next_state == PWRDM_POWER_OFF) && 277 if ((per_next_state == PWRDM_POWER_OFF) &&
@@ -265,11 +282,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
265 if (per_next_state != per_saved_state) 282 if (per_next_state != per_saved_state)
266 pwrdm_set_next_pwrst(per_pd, per_next_state); 283 pwrdm_set_next_pwrst(per_pd, per_next_state);
267 284
268 new_state = next_valid_state(dev, state); 285 new_state_idx = next_valid_state(dev, drv, index);
269 286
270select_state: 287select_state:
271 dev->last_state = new_state; 288 ret = omap3_enter_idle(dev, drv, new_state_idx);
272 ret = omap3_enter_idle(dev, new_state);
273 289
274 /* Restore original PER state if it was modified */ 290 /* Restore original PER state if it was modified */
275 if (per_next_state != per_saved_state) 291 if (per_next_state != per_saved_state)
@@ -302,22 +318,31 @@ struct cpuidle_driver omap3_idle_driver = {
302 .owner = THIS_MODULE, 318 .owner = THIS_MODULE,
303}; 319};
304 320
305/* Helper to fill the C-state common data and register the driver_data */ 321/* Helper to fill the C-state common data*/
306static inline struct omap3_idle_statedata *_fill_cstate( 322static inline void _fill_cstate(struct cpuidle_driver *drv,
307 struct cpuidle_device *dev,
308 int idx, const char *descr) 323 int idx, const char *descr)
309{ 324{
310 struct omap3_idle_statedata *cx = &omap3_idle_data[idx]; 325 struct cpuidle_state *state = &drv->states[idx];
311 struct cpuidle_state *state = &dev->states[idx];
312 326
313 state->exit_latency = cpuidle_params_table[idx].exit_latency; 327 state->exit_latency = cpuidle_params_table[idx].exit_latency;
314 state->target_residency = cpuidle_params_table[idx].target_residency; 328 state->target_residency = cpuidle_params_table[idx].target_residency;
315 state->flags = CPUIDLE_FLAG_TIME_VALID; 329 state->flags = CPUIDLE_FLAG_TIME_VALID;
316 state->enter = omap3_enter_idle_bm; 330 state->enter = omap3_enter_idle_bm;
317 cx->valid = cpuidle_params_table[idx].valid;
318 sprintf(state->name, "C%d", idx + 1); 331 sprintf(state->name, "C%d", idx + 1);
319 strncpy(state->desc, descr, CPUIDLE_DESC_LEN); 332 strncpy(state->desc, descr, CPUIDLE_DESC_LEN);
320 cpuidle_set_statedata(state, cx); 333
334}
335
336/* Helper to register the driver_data */
337static inline struct omap3_idle_statedata *_fill_cstate_usage(
338 struct cpuidle_device *dev,
339 int idx)
340{
341 struct omap3_idle_statedata *cx = &omap3_idle_data[idx];
342 struct cpuidle_state_usage *state_usage = &dev->states_usage[idx];
343
344 cx->valid = cpuidle_params_table[idx].valid;
345 cpuidle_set_statedata(state_usage, cx);
321 346
322 return cx; 347 return cx;
323} 348}
@@ -331,6 +356,7 @@ static inline struct omap3_idle_statedata *_fill_cstate(
331int __init omap3_idle_init(void) 356int __init omap3_idle_init(void)
332{ 357{
333 struct cpuidle_device *dev; 358 struct cpuidle_device *dev;
359 struct cpuidle_driver *drv = &omap3_idle_driver;
334 struct omap3_idle_statedata *cx; 360 struct omap3_idle_statedata *cx;
335 361
336 mpu_pd = pwrdm_lookup("mpu_pwrdm"); 362 mpu_pd = pwrdm_lookup("mpu_pwrdm");
@@ -338,44 +364,52 @@ int __init omap3_idle_init(void)
338 per_pd = pwrdm_lookup("per_pwrdm"); 364 per_pd = pwrdm_lookup("per_pwrdm");
339 cam_pd = pwrdm_lookup("cam_pwrdm"); 365 cam_pd = pwrdm_lookup("cam_pwrdm");
340 366
341 cpuidle_register_driver(&omap3_idle_driver); 367
368 drv->safe_state_index = -1;
342 dev = &per_cpu(omap3_idle_dev, smp_processor_id()); 369 dev = &per_cpu(omap3_idle_dev, smp_processor_id());
343 370
344 /* C1 . MPU WFI + Core active */ 371 /* C1 . MPU WFI + Core active */
345 cx = _fill_cstate(dev, 0, "MPU ON + CORE ON"); 372 _fill_cstate(drv, 0, "MPU ON + CORE ON");
346 (&dev->states[0])->enter = omap3_enter_idle; 373 (&drv->states[0])->enter = omap3_enter_idle;
347 dev->safe_state = &dev->states[0]; 374 drv->safe_state_index = 0;
375 cx = _fill_cstate_usage(dev, 0);
348 cx->valid = 1; /* C1 is always valid */ 376 cx->valid = 1; /* C1 is always valid */
349 cx->mpu_state = PWRDM_POWER_ON; 377 cx->mpu_state = PWRDM_POWER_ON;
350 cx->core_state = PWRDM_POWER_ON; 378 cx->core_state = PWRDM_POWER_ON;
351 379
352 /* C2 . MPU WFI + Core inactive */ 380 /* C2 . MPU WFI + Core inactive */
353 cx = _fill_cstate(dev, 1, "MPU ON + CORE ON"); 381 _fill_cstate(drv, 1, "MPU ON + CORE ON");
382 cx = _fill_cstate_usage(dev, 1);
354 cx->mpu_state = PWRDM_POWER_ON; 383 cx->mpu_state = PWRDM_POWER_ON;
355 cx->core_state = PWRDM_POWER_ON; 384 cx->core_state = PWRDM_POWER_ON;
356 385
357 /* C3 . MPU CSWR + Core inactive */ 386 /* C3 . MPU CSWR + Core inactive */
358 cx = _fill_cstate(dev, 2, "MPU RET + CORE ON"); 387 _fill_cstate(drv, 2, "MPU RET + CORE ON");
388 cx = _fill_cstate_usage(dev, 2);
359 cx->mpu_state = PWRDM_POWER_RET; 389 cx->mpu_state = PWRDM_POWER_RET;
360 cx->core_state = PWRDM_POWER_ON; 390 cx->core_state = PWRDM_POWER_ON;
361 391
362 /* C4 . MPU OFF + Core inactive */ 392 /* C4 . MPU OFF + Core inactive */
363 cx = _fill_cstate(dev, 3, "MPU OFF + CORE ON"); 393 _fill_cstate(drv, 3, "MPU OFF + CORE ON");
394 cx = _fill_cstate_usage(dev, 3);
364 cx->mpu_state = PWRDM_POWER_OFF; 395 cx->mpu_state = PWRDM_POWER_OFF;
365 cx->core_state = PWRDM_POWER_ON; 396 cx->core_state = PWRDM_POWER_ON;
366 397
367 /* C5 . MPU RET + Core RET */ 398 /* C5 . MPU RET + Core RET */
368 cx = _fill_cstate(dev, 4, "MPU RET + CORE RET"); 399 _fill_cstate(drv, 4, "MPU RET + CORE RET");
400 cx = _fill_cstate_usage(dev, 4);
369 cx->mpu_state = PWRDM_POWER_RET; 401 cx->mpu_state = PWRDM_POWER_RET;
370 cx->core_state = PWRDM_POWER_RET; 402 cx->core_state = PWRDM_POWER_RET;
371 403
372 /* C6 . MPU OFF + Core RET */ 404 /* C6 . MPU OFF + Core RET */
373 cx = _fill_cstate(dev, 5, "MPU OFF + CORE RET"); 405 _fill_cstate(drv, 5, "MPU OFF + CORE RET");
406 cx = _fill_cstate_usage(dev, 5);
374 cx->mpu_state = PWRDM_POWER_OFF; 407 cx->mpu_state = PWRDM_POWER_OFF;
375 cx->core_state = PWRDM_POWER_RET; 408 cx->core_state = PWRDM_POWER_RET;
376 409
377 /* C7 . MPU OFF + Core OFF */ 410 /* C7 . MPU OFF + Core OFF */
378 cx = _fill_cstate(dev, 6, "MPU OFF + CORE OFF"); 411 _fill_cstate(drv, 6, "MPU OFF + CORE OFF");
412 cx = _fill_cstate_usage(dev, 6);
379 /* 413 /*
380 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot 414 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
381 * enable OFF mode in a stable form for previous revisions. 415 * enable OFF mode in a stable form for previous revisions.
@@ -389,6 +423,9 @@ int __init omap3_idle_init(void)
389 cx->mpu_state = PWRDM_POWER_OFF; 423 cx->mpu_state = PWRDM_POWER_OFF;
390 cx->core_state = PWRDM_POWER_OFF; 424 cx->core_state = PWRDM_POWER_OFF;
391 425
426 drv->state_count = OMAP3_NUM_STATES;
427 cpuidle_register_driver(&omap3_idle_driver);
428
392 dev->state_count = OMAP3_NUM_STATES; 429 dev->state_count = OMAP3_NUM_STATES;
393 if (cpuidle_register_device(dev)) { 430 if (cpuidle_register_device(dev)) {
394 printk(KERN_ERR "%s: CPUidle register device failed\n", 431 printk(KERN_ERR "%s: CPUidle register device failed\n",