root/arch/arm/mach-omap1/sleep.S

/* [<][>][^][v][top][bottom][index][help] */
   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
  66 ENTRY(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 
 140 ENTRY(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
 146 ENTRY(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
 194 l_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 
 215 ENTRY(omap1510_cpu_suspend_sz)
 216         .word   . - omap1510_cpu_suspend
 217 #endif /* CONFIG_ARCH_OMAP15XX */
 218 
 219 #if defined(CONFIG_ARCH_OMAP16XX)
 220         .align  3
 221 ENTRY(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 
 368 ENTRY(omap1610_cpu_suspend_sz)
 369         .word   . - omap1610_cpu_suspend
 370 #endif /* CONFIG_ARCH_OMAP16XX */

/* [<][>][^][v][top][bottom][index][help] */