linux/arch/arm/mach-omap1/sleep.S
<<
>>
Prefs
   1/*
   2 * linux/arch/arm/mach-omap1/sleep.S
   3 *
   4 * Low-level OMAP7XX/1510/1610 sleep/wakeUp support
   5 *
   6 * Initial SA1110 code:
   7 * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
   8 *
   9 * Adapted for PXA by Nicolas Pitre:
  10 * Copyright (c) 2002 Monta Vista Software, Inc.
  11 *
  12 * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
  13 *
  14 * This program is free software; you can redistribute it and/or modify it
  15 * under the terms of the GNU General Public License as published by the
  16 * Free Software Foundation; either version 2 of the License, or (at your
  17 * option) any later version.
  18 *
  19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  22 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  25 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29 *
  30 * You should have received a copy of the GNU General Public License along
  31 * with this program; if not, write to the Free Software Foundation, Inc.,
  32 * 675 Mass Ave, Cambridge, MA 02139, USA.
  33 */
  34
  35#include <linux/linkage.h>
  36
  37#include <asm/assembler.h>
  38
  39#include <mach/hardware.h>
  40
  41#include "iomap.h"
  42#include "pm.h"
  43
  44                .text
  45
  46
  47/*
  48 * Forces OMAP into deep sleep state
  49 *
  50 * omapXXXX_cpu_suspend()
  51 *
  52 * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed
  53 * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1
  54 * in register r1.
  55 *
  56 * Note: This code get's copied to internal SRAM at boot. When the OMAP
  57 *       wakes up it continues execution at the point it went to sleep.
  58 *
  59 * Note: Because of errata work arounds we have processor specific functions
  60 *       here. They are mostly the same, but slightly different.
  61 *
  62 */
  63
  64#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
  65        .align  3
  66ENTRY(omap7xx_cpu_suspend)
  67
  68        @ save registers on stack
  69        stmfd   sp!, {r0 - r12, lr}
  70
  71        @ Drain write cache
  72        mov     r4, #0
  73        mcr     p15, 0, r0, c7, c10, 4
  74        nop
  75
  76        @ load base address of Traffic Controller
  77        mov     r6, #TCMIF_ASM_BASE & 0xff000000
  78        orr     r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
  79        orr     r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
  80
  81        @ prepare to put SDRAM into self-refresh manually
  82        ldr     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
  83        orr     r9, r7, #SELF_REFRESH_MODE & 0xff000000
  84        orr     r9, r9, #SELF_REFRESH_MODE & 0x000000ff
  85        str     r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
  86
  87        @ prepare to put EMIFS to Sleep
  88        ldr     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
  89        orr     r9, r8, #IDLE_EMIFS_REQUEST & 0xff
  90        str     r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
  91
  92        @ load base address of ARM_IDLECT1 and ARM_IDLECT2
  93        mov     r4, #CLKGEN_REG_ASM_BASE & 0xff000000
  94        orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
  95        orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
  96
  97        @ turn off clock domains
  98        @ do not disable PERCK (0x04)
  99        mov     r5, #OMAP7XX_IDLECT2_SLEEP_VAL & 0xff
 100        orr     r5, r5, #OMAP7XX_IDLECT2_SLEEP_VAL & 0xff00
 101        strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 102
 103        @ request ARM idle
 104        mov     r3, #OMAP7XX_IDLECT1_SLEEP_VAL & 0xff
 105        orr     r3, r3, #OMAP7XX_IDLECT1_SLEEP_VAL & 0xff00
 106        strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 107
 108        @ disable instruction cache
 109        mrc     p15, 0, r9, c1, c0, 0
 110        bic     r2, r9, #0x1000
 111        mcr     p15, 0, r2, c1, c0, 0
 112        nop
 113
 114/*
 115 * Let's wait for the next wake up event to wake us up. r0 can't be
 116 * used here because r0 holds ARM_IDLECT1
 117 */
 118        mov     r2, #0
 119        mcr     p15, 0, r2, c7, c0, 4           @ wait for interrupt
 120/*
 121 * omap7xx_cpu_suspend()'s resume point.
 122 *
 123 * It will just start executing here, so we'll restore stuff from the
 124 * stack.
 125 */
 126        @ re-enable Icache
 127        mcr     p15, 0, r9, c1, c0, 0
 128
 129        @ reset the ARM_IDLECT1 and ARM_IDLECT2.
 130        strh    r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 131        strh    r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 132
 133        @ Restore EMIFF controls
 134        str     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 135        str     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 136
 137        @ restore regs and return
 138        ldmfd   sp!, {r0 - r12, pc}
 139
 140ENTRY(omap7xx_cpu_suspend_sz)
 141        .word   . - omap7xx_cpu_suspend
 142#endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */
 143
 144#ifdef CONFIG_ARCH_OMAP15XX
 145        .align  3
 146ENTRY(omap1510_cpu_suspend)
 147
 148        @ save registers on stack
 149        stmfd   sp!, {r0 - r12, lr}
 150
 151        @ load base address of Traffic Controller
 152        mov     r4, #TCMIF_ASM_BASE & 0xff000000
 153        orr     r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
 154        orr     r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
 155
 156        @ work around errata of OMAP1510 PDE bit for TC shut down
 157        @ clear PDE bit
 158        ldr     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 159        bic     r5, r5, #PDE_BIT & 0xff
 160        str     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 161
 162        @ set PWD_EN bit
 163        and     r5, r5, #PWD_EN_BIT & 0xff
 164        str     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 165
 166        @ prepare to put SDRAM into self-refresh manually
 167        ldr     r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 168        orr     r5, r5, #SELF_REFRESH_MODE & 0xff000000
 169        orr     r5, r5, #SELF_REFRESH_MODE & 0x000000ff
 170        str     r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 171
 172        @ prepare to put EMIFS to Sleep
 173        ldr     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 174        orr     r5, r5, #IDLE_EMIFS_REQUEST & 0xff
 175        str     r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 176
 177        @ load base address of ARM_IDLECT1 and ARM_IDLECT2
 178        mov     r4, #CLKGEN_REG_ASM_BASE & 0xff000000
 179        orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
 180        orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
 181
 182        @ turn off clock domains
 183        mov     r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
 184        orr     r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
 185        strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 186
 187        @ request ARM idle
 188        mov     r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff
 189        orr     r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00
 190        strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 191
 192        mov     r5, #IDLE_WAIT_CYCLES & 0xff
 193        orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
 194l_1510_2:
 195        subs    r5, r5, #1
 196        bne     l_1510_2
 197/*
 198 * Let's wait for the next wake up event to wake us up. r0 can't be
 199 * used here because r0 holds ARM_IDLECT1
 200 */
 201        mov     r2, #0
 202        mcr     p15, 0, r2, c7, c0, 4           @ wait for interrupt
 203/*
 204 * omap1510_cpu_suspend()'s resume point.
 205 *
 206 * It will just start executing here, so we'll restore stuff from the
 207 * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
 208 */
 209        strh    r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 210        strh    r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 211
 212        @ restore regs and return
 213        ldmfd   sp!, {r0 - r12, pc}
 214
 215ENTRY(omap1510_cpu_suspend_sz)
 216        .word   . - omap1510_cpu_suspend
 217#endif /* CONFIG_ARCH_OMAP15XX */
 218
 219#if defined(CONFIG_ARCH_OMAP16XX)
 220        .align  3
 221ENTRY(omap1610_cpu_suspend)
 222
 223        @ save registers on stack
 224        stmfd   sp!, {r0 - r12, lr}
 225
 226        @ Drain write cache
 227        mov     r4, #0
 228        mcr     p15, 0, r0, c7, c10, 4
 229        nop
 230
 231        @ Load base address of Traffic Controller
 232        mov     r6, #TCMIF_ASM_BASE & 0xff000000
 233        orr     r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
 234        orr     r6, r6, #TCMIF_ASM_BASE & 0x0000ff00
 235
 236        @ Prepare to put SDRAM into self-refresh manually
 237        ldr     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 238        orr     r9, r7, #SELF_REFRESH_MODE & 0xff000000
 239        orr     r9, r9, #SELF_REFRESH_MODE & 0x000000ff
 240        str     r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 241
 242        @ Prepare to put EMIFS to Sleep
 243        ldr     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 244        orr     r9, r8, #IDLE_EMIFS_REQUEST & 0xff
 245        str     r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 246
 247        @ Load base address of ARM_IDLECT1 and ARM_IDLECT2
 248        mov     r4, #CLKGEN_REG_ASM_BASE & 0xff000000
 249        orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
 250        orr     r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
 251
 252        @ Turn off clock domains
 253        @ Do not disable PERCK (0x04)
 254        mov     r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
 255        orr     r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
 256        strh    r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 257
 258        @ Request ARM idle
 259        mov     r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
 260        orr     r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
 261        strh    r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 262
 263/*
 264 * Let's wait for the next wake up event to wake us up. r0 can't be
 265 * used here because r0 holds ARM_IDLECT1
 266 */
 267        mov     r2, #0
 268        mcr     p15, 0, r2, c7, c0, 4           @ wait for interrupt
 269
 270        @ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions
 271        @ according to this formula:
 272        @ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV
 273        @ Max DPLL_MULT = 18
 274        @ DPLL_DIV = 1
 275        @ ARMDIV = 1
 276        @ => 74 nop-instructions
 277        nop
 278        nop
 279        nop
 280        nop
 281        nop
 282        nop
 283        nop
 284        nop
 285        nop
 286        nop     @10
 287        nop
 288        nop
 289        nop
 290        nop
 291        nop
 292        nop
 293        nop
 294        nop
 295        nop
 296        nop     @20
 297        nop
 298        nop
 299        nop
 300        nop
 301        nop
 302        nop
 303        nop
 304        nop
 305        nop
 306        nop     @30
 307        nop
 308        nop
 309        nop
 310        nop
 311        nop
 312        nop
 313        nop
 314        nop
 315        nop
 316        nop     @40
 317        nop
 318        nop
 319        nop
 320        nop
 321        nop
 322        nop
 323        nop
 324        nop
 325        nop
 326        nop     @50
 327        nop
 328        nop
 329        nop
 330        nop
 331        nop
 332        nop
 333        nop
 334        nop
 335        nop
 336        nop     @60
 337        nop
 338        nop
 339        nop
 340        nop
 341        nop
 342        nop
 343        nop
 344        nop
 345        nop
 346        nop     @70
 347        nop
 348        nop
 349        nop
 350        nop     @74
 351/*
 352 * omap1610_cpu_suspend()'s resume point.
 353 *
 354 * It will just start executing here, so we'll restore stuff from the
 355 * stack.
 356 */
 357        @ Restore the ARM_IDLECT1 and ARM_IDLECT2.
 358        strh    r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
 359        strh    r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
 360
 361        @ Restore EMIFF controls
 362        str     r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
 363        str     r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
 364
 365        @ Restore regs and return
 366        ldmfd   sp!, {r0 - r12, pc}
 367
 368ENTRY(omap1610_cpu_suspend_sz)
 369        .word   . - omap1610_cpu_suspend
 370#endif /* CONFIG_ARCH_OMAP16XX */
 371