diff options
author | Jean Pihet <j-pihet@ti.com> | 2010-12-18 10:44:45 -0500 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2010-12-21 17:45:58 -0500 |
commit | f7dfe3d8a98b7c4869c09826e3a65663cb9c71be (patch) | |
tree | a308e3f5416dc4a690814e08442805555f52d762 /arch/arm/mach-omap2 | |
parent | 1e81bc015a444e0f908451642b0197199d0c6fa4 (diff) |
OMAP3: rework of the ASM sleep code execution paths
- Reworked and simplified the execution paths for better
readability and to avoid duplication of code,
- Added comments on the entry and exit points and the interaction
with the ROM code for OFF mode restore,
- Reworked the existing comments for better readability.
Tested on N900 and Beagleboard with full RET and OFF modes,
using cpuidle and suspend.
Signed-off-by: Jean Pihet <j-pihet@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Tested-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/control.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-omap2/sleep34xx.S | 318 |
2 files changed, 195 insertions, 132 deletions
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index 27ed558fdf54..0269bb055b69 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c | |||
@@ -239,7 +239,14 @@ void omap3_save_scratchpad_contents(void) | |||
239 | struct omap3_scratchpad_prcm_block prcm_block_contents; | 239 | struct omap3_scratchpad_prcm_block prcm_block_contents; |
240 | struct omap3_scratchpad_sdrc_block sdrc_block_contents; | 240 | struct omap3_scratchpad_sdrc_block sdrc_block_contents; |
241 | 241 | ||
242 | /* Populate the Scratchpad contents */ | 242 | /* |
243 | * Populate the Scratchpad contents | ||
244 | * | ||
245 | * The "get_*restore_pointer" functions are used to provide a | ||
246 | * physical restore address where the ROM code jumps while waking | ||
247 | * up from MPU OFF/OSWR state. | ||
248 | * The restore pointer is stored into the scratchpad. | ||
249 | */ | ||
243 | scratchpad_contents.boot_config_ptr = 0x0; | 250 | scratchpad_contents.boot_config_ptr = 0x0; |
244 | if (cpu_is_omap3630()) | 251 | if (cpu_is_omap3630()) |
245 | scratchpad_contents.public_restore_ptr = | 252 | scratchpad_contents.public_restore_ptr = |
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S index 5b978b8401c4..06e47326e17c 100644 --- a/arch/arm/mach-omap2/sleep34xx.S +++ b/arch/arm/mach-omap2/sleep34xx.S | |||
@@ -71,6 +71,13 @@ | |||
71 | * API functions | 71 | * API functions |
72 | */ | 72 | */ |
73 | 73 | ||
74 | /* | ||
75 | * The "get_*restore_pointer" functions are used to provide a | ||
76 | * physical restore address where the ROM code jumps while waking | ||
77 | * up from MPU OFF/OSWR state. | ||
78 | * The restore pointer is stored into the scratchpad. | ||
79 | */ | ||
80 | |||
74 | .text | 81 | .text |
75 | /* Function call to get the restore pointer for resume from OFF */ | 82 | /* Function call to get the restore pointer for resume from OFF */ |
76 | ENTRY(get_restore_pointer) | 83 | ENTRY(get_restore_pointer) |
@@ -102,7 +109,7 @@ ENTRY(get_es3_restore_pointer_sz) | |||
102 | /* | 109 | /* |
103 | * L2 cache needs to be toggled for stable OFF mode functionality on 3630. | 110 | * L2 cache needs to be toggled for stable OFF mode functionality on 3630. |
104 | * This function sets up a flag that will allow for this toggling to take | 111 | * This function sets up a flag that will allow for this toggling to take |
105 | * place on 3630. Hopefully some version in the future maynot need this | 112 | * place on 3630. Hopefully some version in the future may not need this. |
106 | */ | 113 | */ |
107 | ENTRY(enable_omap3630_toggle_l2_on_restore) | 114 | ENTRY(enable_omap3630_toggle_l2_on_restore) |
108 | stmfd sp!, {lr} @ save registers on stack | 115 | stmfd sp!, {lr} @ save registers on stack |
@@ -144,34 +151,162 @@ ENTRY(save_secure_ram_context_sz) | |||
144 | .word . - save_secure_ram_context | 151 | .word . - save_secure_ram_context |
145 | 152 | ||
146 | /* | 153 | /* |
154 | * ====================== | ||
155 | * == Idle entry point == | ||
156 | * ====================== | ||
157 | */ | ||
158 | |||
159 | /* | ||
147 | * Forces OMAP into idle state | 160 | * Forces OMAP into idle state |
148 | * | 161 | * |
149 | * omap34xx_suspend() - This bit of code just executes the WFI | 162 | * omap34xx_cpu_suspend() - This bit of code saves the CPU context if needed |
150 | * for normal idles. | 163 | * and executes the WFI instruction. Calling WFI effectively changes the |
164 | * power domains states to the desired target power states. | ||
165 | * | ||
151 | * | 166 | * |
152 | * Note: This code get's copied to internal SRAM at boot. When the OMAP | 167 | * Notes: |
153 | * wakes up it continues execution at the point it went to sleep. | 168 | * - this code gets copied to internal SRAM at boot. The execution pointer |
169 | * in SRAM is _omap_sram_idle. | ||
170 | * - when the OMAP wakes up it continues at different execution points | ||
171 | * depending on the low power mode (non-OFF vs OFF modes), | ||
172 | * cf. 'Resume path for xxx mode' comments. | ||
154 | */ | 173 | */ |
155 | ENTRY(omap34xx_cpu_suspend) | 174 | ENTRY(omap34xx_cpu_suspend) |
156 | stmfd sp!, {r0-r12, lr} @ save registers on stack | 175 | stmfd sp!, {r0-r12, lr} @ save registers on stack |
157 | 176 | ||
158 | /* r0 contains restore pointer in sdram */ | 177 | /* |
159 | /* r1 contains information about saving context */ | 178 | * r0 contains restore pointer in sdram |
160 | ldr r4, sdrc_power @ read the SDRC_POWER register | 179 | * r1 contains information about saving context: |
161 | ldr r5, [r4] @ read the contents of SDRC_POWER | 180 | * 0 - No context lost |
162 | orr r5, r5, #0x40 @ enable self refresh on idle req | 181 | * 1 - Only L1 and logic lost |
163 | str r5, [r4] @ write back to SDRC_POWER register | 182 | * 2 - Only L2 lost |
183 | * 3 - Both L1 and L2 lost | ||
184 | */ | ||
164 | 185 | ||
186 | /* Directly jump to WFI is the context save is not required */ | ||
165 | cmp r1, #0x0 | 187 | cmp r1, #0x0 |
166 | /* If context save is required, do that and execute wfi */ | 188 | beq omap3_do_wfi |
167 | bne save_context_wfi | 189 | |
190 | /* Otherwise fall through to the save context code */ | ||
191 | save_context_wfi: | ||
192 | mov r8, r0 @ Store SDRAM address in r8 | ||
193 | mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register | ||
194 | mov r4, #0x1 @ Number of parameters for restore call | ||
195 | stmia r8!, {r4-r5} @ Push parameters for restore call | ||
196 | mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register | ||
197 | stmia r8!, {r4-r5} @ Push parameters for restore call | ||
198 | |||
199 | /* Check what that target sleep state is from r1 */ | ||
200 | cmp r1, #0x2 @ Only L2 lost, no need to save context | ||
201 | beq clean_caches | ||
202 | |||
203 | l1_logic_lost: | ||
204 | /* Store sp and spsr to SDRAM */ | ||
205 | mov r4, sp | ||
206 | mrs r5, spsr | ||
207 | mov r6, lr | ||
208 | stmia r8!, {r4-r6} | ||
209 | /* Save all ARM registers */ | ||
210 | /* Coprocessor access control register */ | ||
211 | mrc p15, 0, r6, c1, c0, 2 | ||
212 | stmia r8!, {r6} | ||
213 | /* TTBR0, TTBR1 and Translation table base control */ | ||
214 | mrc p15, 0, r4, c2, c0, 0 | ||
215 | mrc p15, 0, r5, c2, c0, 1 | ||
216 | mrc p15, 0, r6, c2, c0, 2 | ||
217 | stmia r8!, {r4-r6} | ||
218 | /* | ||
219 | * Domain access control register, data fault status register, | ||
220 | * and instruction fault status register | ||
221 | */ | ||
222 | mrc p15, 0, r4, c3, c0, 0 | ||
223 | mrc p15, 0, r5, c5, c0, 0 | ||
224 | mrc p15, 0, r6, c5, c0, 1 | ||
225 | stmia r8!, {r4-r6} | ||
226 | /* | ||
227 | * Data aux fault status register, instruction aux fault status, | ||
228 | * data fault address register and instruction fault address register | ||
229 | */ | ||
230 | mrc p15, 0, r4, c5, c1, 0 | ||
231 | mrc p15, 0, r5, c5, c1, 1 | ||
232 | mrc p15, 0, r6, c6, c0, 0 | ||
233 | mrc p15, 0, r7, c6, c0, 2 | ||
234 | stmia r8!, {r4-r7} | ||
235 | /* | ||
236 | * user r/w thread and process ID, user r/o thread and process ID, | ||
237 | * priv only thread and process ID, cache size selection | ||
238 | */ | ||
239 | mrc p15, 0, r4, c13, c0, 2 | ||
240 | mrc p15, 0, r5, c13, c0, 3 | ||
241 | mrc p15, 0, r6, c13, c0, 4 | ||
242 | mrc p15, 2, r7, c0, c0, 0 | ||
243 | stmia r8!, {r4-r7} | ||
244 | /* Data TLB lockdown, instruction TLB lockdown registers */ | ||
245 | mrc p15, 0, r5, c10, c0, 0 | ||
246 | mrc p15, 0, r6, c10, c0, 1 | ||
247 | stmia r8!, {r5-r6} | ||
248 | /* Secure or non secure vector base address, FCSE PID, Context PID*/ | ||
249 | mrc p15, 0, r4, c12, c0, 0 | ||
250 | mrc p15, 0, r5, c13, c0, 0 | ||
251 | mrc p15, 0, r6, c13, c0, 1 | ||
252 | stmia r8!, {r4-r6} | ||
253 | /* Primary remap, normal remap registers */ | ||
254 | mrc p15, 0, r4, c10, c2, 0 | ||
255 | mrc p15, 0, r5, c10, c2, 1 | ||
256 | stmia r8!,{r4-r5} | ||
257 | |||
258 | /* Store current cpsr*/ | ||
259 | mrs r2, cpsr | ||
260 | stmia r8!, {r2} | ||
261 | |||
262 | mrc p15, 0, r4, c1, c0, 0 | ||
263 | /* save control register */ | ||
264 | stmia r8!, {r4} | ||
265 | |||
266 | clean_caches: | ||
267 | /* | ||
268 | * Clean Data or unified cache to POU | ||
269 | * How to invalidate only L1 cache???? - #FIX_ME# | ||
270 | * mcr p15, 0, r11, c7, c11, 1 | ||
271 | */ | ||
272 | cmp r1, #0x1 @ Check whether L2 inval is required | ||
273 | beq omap3_do_wfi | ||
274 | |||
275 | clean_l2: | ||
276 | /* | ||
277 | * jump out to kernel flush routine | ||
278 | * - reuse that code is better | ||
279 | * - it executes in a cached space so is faster than refetch per-block | ||
280 | * - should be faster and will change with kernel | ||
281 | * - 'might' have to copy address, load and jump to it | ||
282 | */ | ||
283 | ldr r1, kernel_flush | ||
284 | mov lr, pc | ||
285 | bx r1 | ||
286 | |||
287 | omap3_do_wfi: | ||
288 | ldr r4, sdrc_power @ read the SDRC_POWER register | ||
289 | ldr r5, [r4] @ read the contents of SDRC_POWER | ||
290 | orr r5, r5, #0x40 @ enable self refresh on idle req | ||
291 | str r5, [r4] @ write back to SDRC_POWER register | ||
292 | |||
168 | /* Data memory barrier and Data sync barrier */ | 293 | /* Data memory barrier and Data sync barrier */ |
169 | mov r1, #0 | 294 | mov r1, #0 |
170 | mcr p15, 0, r1, c7, c10, 4 | 295 | mcr p15, 0, r1, c7, c10, 4 |
171 | mcr p15, 0, r1, c7, c10, 5 | 296 | mcr p15, 0, r1, c7, c10, 5 |
172 | 297 | ||
298 | /* | ||
299 | * =================================== | ||
300 | * == WFI instruction => Enter idle == | ||
301 | * =================================== | ||
302 | */ | ||
173 | wfi @ wait for interrupt | 303 | wfi @ wait for interrupt |
174 | 304 | ||
305 | /* | ||
306 | * =================================== | ||
307 | * == Resume path for non-OFF modes == | ||
308 | * =================================== | ||
309 | */ | ||
175 | nop | 310 | nop |
176 | nop | 311 | nop |
177 | nop | 312 | nop |
@@ -184,7 +319,29 @@ ENTRY(omap34xx_cpu_suspend) | |||
184 | nop | 319 | nop |
185 | bl wait_sdrc_ok | 320 | bl wait_sdrc_ok |
186 | 321 | ||
187 | ldmfd sp!, {r0-r12, pc} @ restore regs and return | 322 | /* |
323 | * =================================== | ||
324 | * == Exit point from non-OFF modes == | ||
325 | * =================================== | ||
326 | */ | ||
327 | ldmfd sp!, {r0-r12, pc} @ restore regs and return | ||
328 | |||
329 | |||
330 | /* | ||
331 | * ============================== | ||
332 | * == Resume path for OFF mode == | ||
333 | * ============================== | ||
334 | */ | ||
335 | |||
336 | /* | ||
337 | * The restore_* functions are called by the ROM code | ||
338 | * when back from WFI in OFF mode. | ||
339 | * Cf. the get_*restore_pointer functions. | ||
340 | * | ||
341 | * restore_es3: applies to 34xx >= ES3.0 | ||
342 | * restore_3630: applies to 36xx | ||
343 | * restore: common code for 3xxx | ||
344 | */ | ||
188 | restore_es3: | 345 | restore_es3: |
189 | ldr r5, pm_prepwstst_core_p | 346 | ldr r5, pm_prepwstst_core_p |
190 | ldr r4, [r5] | 347 | ldr r4, [r5] |
@@ -214,12 +371,17 @@ restore_3630: | |||
214 | ldr r1, control_mem_rta | 371 | ldr r1, control_mem_rta |
215 | mov r2, #OMAP36XX_RTA_DISABLE | 372 | mov r2, #OMAP36XX_RTA_DISABLE |
216 | str r2, [r1] | 373 | str r2, [r1] |
217 | /* Fall thru for the remaining logic */ | 374 | |
375 | /* Fall through to common code for the remaining logic */ | ||
376 | |||
218 | restore: | 377 | restore: |
219 | /* Check what was the reason for mpu reset and store the reason in r9*/ | 378 | /* |
220 | /* 1 - Only L1 and logic lost */ | 379 | * Check what was the reason for mpu reset and store the reason in r9: |
221 | /* 2 - Only L2 lost - In this case, we wont be here */ | 380 | * 0 - No context lost |
222 | /* 3 - Both L1 and L2 lost */ | 381 | * 1 - Only L1 and logic lost |
382 | * 2 - Only L2 lost - In this case, we wont be here | ||
383 | * 3 - Both L1 and L2 lost | ||
384 | */ | ||
223 | ldr r1, pm_pwstctrl_mpu | 385 | ldr r1, pm_pwstctrl_mpu |
224 | ldr r2, [r1] | 386 | ldr r2, [r1] |
225 | and r2, r2, #0x3 | 387 | and r2, r2, #0x3 |
@@ -422,119 +584,12 @@ usettbr0: | |||
422 | and r4, r2 | 584 | and r4, r2 |
423 | mcr p15, 0, r4, c1, c0, 0 | 585 | mcr p15, 0, r4, c1, c0, 0 |
424 | 586 | ||
587 | /* | ||
588 | * ============================== | ||
589 | * == Exit point from OFF mode == | ||
590 | * ============================== | ||
591 | */ | ||
425 | ldmfd sp!, {r0-r12, pc} @ restore regs and return | 592 | ldmfd sp!, {r0-r12, pc} @ restore regs and return |
426 | save_context_wfi: | ||
427 | mov r8, r0 /* Store SDRAM address in r8 */ | ||
428 | mrc p15, 0, r5, c1, c0, 1 @ Read Auxiliary Control Register | ||
429 | mov r4, #0x1 @ Number of parameters for restore call | ||
430 | stmia r8!, {r4-r5} @ Push parameters for restore call | ||
431 | mrc p15, 1, r5, c9, c0, 2 @ Read L2 AUX ctrl register | ||
432 | stmia r8!, {r4-r5} @ Push parameters for restore call | ||
433 | /* Check what that target sleep state is:stored in r1*/ | ||
434 | /* 1 - Only L1 and logic lost */ | ||
435 | /* 2 - Only L2 lost */ | ||
436 | /* 3 - Both L1 and L2 lost */ | ||
437 | cmp r1, #0x2 /* Only L2 lost */ | ||
438 | beq clean_l2 | ||
439 | cmp r1, #0x1 /* L2 retained */ | ||
440 | /* r9 stores whether to clean L2 or not*/ | ||
441 | moveq r9, #0x0 /* Dont Clean L2 */ | ||
442 | movne r9, #0x1 /* Clean L2 */ | ||
443 | l1_logic_lost: | ||
444 | /* Store sp and spsr to SDRAM */ | ||
445 | mov r4, sp | ||
446 | mrs r5, spsr | ||
447 | mov r6, lr | ||
448 | stmia r8!, {r4-r6} | ||
449 | /* Save all ARM registers */ | ||
450 | /* Coprocessor access control register */ | ||
451 | mrc p15, 0, r6, c1, c0, 2 | ||
452 | stmia r8!, {r6} | ||
453 | /* TTBR0, TTBR1 and Translation table base control */ | ||
454 | mrc p15, 0, r4, c2, c0, 0 | ||
455 | mrc p15, 0, r5, c2, c0, 1 | ||
456 | mrc p15, 0, r6, c2, c0, 2 | ||
457 | stmia r8!, {r4-r6} | ||
458 | /* Domain access control register, data fault status register, | ||
459 | and instruction fault status register */ | ||
460 | mrc p15, 0, r4, c3, c0, 0 | ||
461 | mrc p15, 0, r5, c5, c0, 0 | ||
462 | mrc p15, 0, r6, c5, c0, 1 | ||
463 | stmia r8!, {r4-r6} | ||
464 | /* Data aux fault status register, instruction aux fault status, | ||
465 | datat fault address register and instruction fault address register*/ | ||
466 | mrc p15, 0, r4, c5, c1, 0 | ||
467 | mrc p15, 0, r5, c5, c1, 1 | ||
468 | mrc p15, 0, r6, c6, c0, 0 | ||
469 | mrc p15, 0, r7, c6, c0, 2 | ||
470 | stmia r8!, {r4-r7} | ||
471 | /* user r/w thread and process ID, user r/o thread and process ID, | ||
472 | priv only thread and process ID, cache size selection */ | ||
473 | mrc p15, 0, r4, c13, c0, 2 | ||
474 | mrc p15, 0, r5, c13, c0, 3 | ||
475 | mrc p15, 0, r6, c13, c0, 4 | ||
476 | mrc p15, 2, r7, c0, c0, 0 | ||
477 | stmia r8!, {r4-r7} | ||
478 | /* Data TLB lockdown, instruction TLB lockdown registers */ | ||
479 | mrc p15, 0, r5, c10, c0, 0 | ||
480 | mrc p15, 0, r6, c10, c0, 1 | ||
481 | stmia r8!, {r5-r6} | ||
482 | /* Secure or non secure vector base address, FCSE PID, Context PID*/ | ||
483 | mrc p15, 0, r4, c12, c0, 0 | ||
484 | mrc p15, 0, r5, c13, c0, 0 | ||
485 | mrc p15, 0, r6, c13, c0, 1 | ||
486 | stmia r8!, {r4-r6} | ||
487 | /* Primary remap, normal remap registers */ | ||
488 | mrc p15, 0, r4, c10, c2, 0 | ||
489 | mrc p15, 0, r5, c10, c2, 1 | ||
490 | stmia r8!,{r4-r5} | ||
491 | |||
492 | /* Store current cpsr*/ | ||
493 | mrs r2, cpsr | ||
494 | stmia r8!, {r2} | ||
495 | |||
496 | mrc p15, 0, r4, c1, c0, 0 | ||
497 | /* save control register */ | ||
498 | stmia r8!, {r4} | ||
499 | clean_caches: | ||
500 | /* Clean Data or unified cache to POU*/ | ||
501 | /* How to invalidate only L1 cache???? - #FIX_ME# */ | ||
502 | /* mcr p15, 0, r11, c7, c11, 1 */ | ||
503 | cmp r9, #1 /* Check whether L2 inval is required or not*/ | ||
504 | bne skip_l2_inval | ||
505 | clean_l2: | ||
506 | /* | ||
507 | * Jump out to kernel flush routine | ||
508 | * - reuse that code is better | ||
509 | * - it executes in a cached space so is faster than refetch per-block | ||
510 | * - should be faster and will change with kernel | ||
511 | * - 'might' have to copy address, load and jump to it | ||
512 | * - lr is used since we are running in SRAM currently. | ||
513 | */ | ||
514 | ldr r1, kernel_flush | ||
515 | mov lr, pc | ||
516 | bx r1 | ||
517 | |||
518 | skip_l2_inval: | ||
519 | /* Data memory barrier and Data sync barrier */ | ||
520 | mov r1, #0 | ||
521 | mcr p15, 0, r1, c7, c10, 4 | ||
522 | mcr p15, 0, r1, c7, c10, 5 | ||
523 | |||
524 | wfi @ wait for interrupt | ||
525 | nop | ||
526 | nop | ||
527 | nop | ||
528 | nop | ||
529 | nop | ||
530 | nop | ||
531 | nop | ||
532 | nop | ||
533 | nop | ||
534 | nop | ||
535 | bl wait_sdrc_ok | ||
536 | /* restore regs and return */ | ||
537 | ldmfd sp!, {r0-r12, pc} | ||
538 | 593 | ||
539 | 594 | ||
540 | /* | 595 | /* |
@@ -687,5 +742,6 @@ kick_counter: | |||
687 | .word 0 | 742 | .word 0 |
688 | wait_dll_lock_counter: | 743 | wait_dll_lock_counter: |
689 | .word 0 | 744 | .word 0 |
745 | |||
690 | ENTRY(omap34xx_cpu_suspend_sz) | 746 | ENTRY(omap34xx_cpu_suspend_sz) |
691 | .word . - omap34xx_cpu_suspend | 747 | .word . - omap34xx_cpu_suspend |