diff options
Diffstat (limited to 'arch/arm/plat-omap/sleep.S')
| -rw-r--r-- | arch/arm/plat-omap/sleep.S | 139 |
1 files changed, 134 insertions, 5 deletions
diff --git a/arch/arm/plat-omap/sleep.S b/arch/arm/plat-omap/sleep.S index 9f745836f6aa..4cd7d292f854 100644 --- a/arch/arm/plat-omap/sleep.S +++ b/arch/arm/plat-omap/sleep.S | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/arch/arm/plat-omap/sleep.S | 2 | * linux/arch/arm/plat-omap/sleep.S |
| 3 | * | 3 | * |
| 4 | * Low-level OMAP1510/1610 sleep/wakeUp support | 4 | * Low-level OMAP730/1510/1610 sleep/wakeUp support |
| 5 | * | 5 | * |
| 6 | * Initial SA1110 code: | 6 | * Initial SA1110 code: |
| 7 | * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> | 7 | * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> |
| @@ -52,7 +52,57 @@ | |||
| 52 | * processor specific functions here. | 52 | * processor specific functions here. |
| 53 | */ | 53 | */ |
| 54 | 54 | ||
| 55 | #ifdef CONFIG_ARCH_OMAP1510 | 55 | #if defined(CONFIG_ARCH_OMAP730) |
| 56 | ENTRY(omap730_idle_loop_suspend) | ||
| 57 | |||
| 58 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | ||
| 59 | |||
| 60 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
| 61 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
| 62 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
| 63 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
| 64 | |||
| 65 | @ turn off clock domains | ||
| 66 | @ get ARM_IDLECT2 into r2 | ||
| 67 | ldrh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
| 68 | mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff | ||
| 69 | orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 | ||
| 70 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
| 71 | |||
| 72 | @ request ARM idle | ||
| 73 | @ get ARM_IDLECT1 into r1 | ||
| 74 | ldrh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
| 75 | orr r3, r1, #OMAP730_IDLE_LOOP_REQUEST & 0xffff | ||
| 76 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
| 77 | |||
| 78 | mov r5, #IDLE_WAIT_CYCLES & 0xff | ||
| 79 | orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 | ||
| 80 | l_730: subs r5, r5, #1 | ||
| 81 | bne l_730 | ||
| 82 | /* | ||
| 83 | * Let's wait for the next clock tick to wake us up. | ||
| 84 | */ | ||
| 85 | mov r0, #0 | ||
| 86 | mcr p15, 0, r0, c7, c0, 4 @ wait for interrupt | ||
| 87 | /* | ||
| 88 | * omap730_idle_loop_suspend()'s resume point. | ||
| 89 | * | ||
| 90 | * It will just start executing here, so we'll restore stuff from the | ||
| 91 | * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
| 92 | */ | ||
| 93 | |||
| 94 | @ restore ARM_IDLECT1 and ARM_IDLECT2 and return | ||
| 95 | @ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2 | ||
| 96 | strh r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
| 97 | strh r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
| 98 | |||
| 99 | ldmfd sp!, {r0 - r12, pc} @ restore regs and return | ||
| 100 | |||
| 101 | ENTRY(omap730_idle_loop_suspend_sz) | ||
| 102 | .word . - omap730_idle_loop_suspend | ||
| 103 | #endif /* CONFIG_ARCH_OMAP730 */ | ||
| 104 | |||
| 105 | #ifdef CONFIG_ARCH_OMAP15XX | ||
| 56 | ENTRY(omap1510_idle_loop_suspend) | 106 | ENTRY(omap1510_idle_loop_suspend) |
| 57 | 107 | ||
| 58 | stmfd sp!, {r0 - r12, lr} @ save registers on stack | 108 | stmfd sp!, {r0 - r12, lr} @ save registers on stack |
| @@ -100,7 +150,7 @@ l_1510: subs r5, r5, #1 | |||
| 100 | 150 | ||
| 101 | ENTRY(omap1510_idle_loop_suspend_sz) | 151 | ENTRY(omap1510_idle_loop_suspend_sz) |
| 102 | .word . - omap1510_idle_loop_suspend | 152 | .word . - omap1510_idle_loop_suspend |
| 103 | #endif /* CONFIG_ARCH_OMAP1510 */ | 153 | #endif /* CONFIG_ARCH_OMAP15XX */ |
| 104 | 154 | ||
| 105 | #if defined(CONFIG_ARCH_OMAP16XX) | 155 | #if defined(CONFIG_ARCH_OMAP16XX) |
| 106 | ENTRY(omap1610_idle_loop_suspend) | 156 | ENTRY(omap1610_idle_loop_suspend) |
| @@ -169,7 +219,86 @@ ENTRY(omap1610_idle_loop_suspend_sz) | |||
| 169 | * | 219 | * |
| 170 | */ | 220 | */ |
| 171 | 221 | ||
| 172 | #ifdef CONFIG_ARCH_OMAP1510 | 222 | #if defined(CONFIG_ARCH_OMAP730) |
| 223 | ENTRY(omap730_cpu_suspend) | ||
| 224 | |||
| 225 | @ save registers on stack | ||
| 226 | stmfd sp!, {r0 - r12, lr} | ||
| 227 | |||
| 228 | @ Drain write cache | ||
| 229 | mov r4, #0 | ||
| 230 | mcr p15, 0, r0, c7, c10, 4 | ||
| 231 | nop | ||
| 232 | |||
| 233 | @ load base address of Traffic Controller | ||
| 234 | mov r6, #TCMIF_ASM_BASE & 0xff000000 | ||
| 235 | orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 | ||
| 236 | orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 | ||
| 237 | |||
| 238 | @ prepare to put SDRAM into self-refresh manually | ||
| 239 | ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
| 240 | orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 | ||
| 241 | orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff | ||
| 242 | str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
| 243 | |||
| 244 | @ prepare to put EMIFS to Sleep | ||
| 245 | ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
| 246 | orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff | ||
| 247 | str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
| 248 | |||
| 249 | @ load base address of ARM_IDLECT1 and ARM_IDLECT2 | ||
| 250 | mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 | ||
| 251 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 | ||
| 252 | orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 | ||
| 253 | |||
| 254 | @ turn off clock domains | ||
| 255 | @ do not disable PERCK (0x04) | ||
| 256 | mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff | ||
| 257 | orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 | ||
| 258 | strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
| 259 | |||
| 260 | @ request ARM idle | ||
| 261 | mov r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff | ||
| 262 | orr r3, r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff00 | ||
| 263 | strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
| 264 | |||
| 265 | @ disable instruction cache | ||
| 266 | mrc p15, 0, r9, c1, c0, 0 | ||
| 267 | bic r2, r9, #0x1000 | ||
| 268 | mcr p15, 0, r2, c1, c0, 0 | ||
| 269 | nop | ||
| 270 | |||
| 271 | /* | ||
| 272 | * Let's wait for the next wake up event to wake us up. r0 can't be | ||
| 273 | * used here because r0 holds ARM_IDLECT1 | ||
| 274 | */ | ||
| 275 | mov r2, #0 | ||
| 276 | mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt | ||
| 277 | /* | ||
| 278 | * omap730_cpu_suspend()'s resume point. | ||
| 279 | * | ||
| 280 | * It will just start executing here, so we'll restore stuff from the | ||
| 281 | * stack. | ||
| 282 | */ | ||
| 283 | @ re-enable Icache | ||
| 284 | mcr p15, 0, r9, c1, c0, 0 | ||
| 285 | |||
| 286 | @ reset the ARM_IDLECT1 and ARM_IDLECT2. | ||
| 287 | strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] | ||
| 288 | strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] | ||
| 289 | |||
| 290 | @ Restore EMIFF controls | ||
| 291 | str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] | ||
| 292 | str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] | ||
| 293 | |||
| 294 | @ restore regs and return | ||
| 295 | ldmfd sp!, {r0 - r12, pc} | ||
| 296 | |||
| 297 | ENTRY(omap730_cpu_suspend_sz) | ||
| 298 | .word . - omap730_cpu_suspend | ||
| 299 | #endif /* CONFIG_ARCH_OMAP730 */ | ||
| 300 | |||
| 301 | #ifdef CONFIG_ARCH_OMAP15XX | ||
| 173 | ENTRY(omap1510_cpu_suspend) | 302 | ENTRY(omap1510_cpu_suspend) |
| 174 | 303 | ||
| 175 | @ save registers on stack | 304 | @ save registers on stack |
| @@ -241,7 +370,7 @@ l_1510_2: | |||
| 241 | 370 | ||
| 242 | ENTRY(omap1510_cpu_suspend_sz) | 371 | ENTRY(omap1510_cpu_suspend_sz) |
| 243 | .word . - omap1510_cpu_suspend | 372 | .word . - omap1510_cpu_suspend |
| 244 | #endif /* CONFIG_ARCH_OMAP1510 */ | 373 | #endif /* CONFIG_ARCH_OMAP15XX */ |
| 245 | 374 | ||
| 246 | #if defined(CONFIG_ARCH_OMAP16XX) | 375 | #if defined(CONFIG_ARCH_OMAP16XX) |
| 247 | ENTRY(omap1610_cpu_suspend) | 376 | ENTRY(omap1610_cpu_suspend) |
