1670c104aSTony Lindgren/* 2670c104aSTony Lindgren * linux/arch/arm/mach-omap1/sleep.S 3670c104aSTony Lindgren * 47c006926SAlistair Buxton * Low-level OMAP7XX/1510/1610 sleep/wakeUp support 5670c104aSTony Lindgren * 6670c104aSTony Lindgren * Initial SA1110 code: 7670c104aSTony Lindgren * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> 8670c104aSTony Lindgren * 9670c104aSTony Lindgren * Adapted for PXA by Nicolas Pitre: 10670c104aSTony Lindgren * Copyright (c) 2002 Monta Vista Software, Inc. 11670c104aSTony Lindgren * 12670c104aSTony Lindgren * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com> 13670c104aSTony Lindgren * 14670c104aSTony Lindgren * This program is free software; you can redistribute it and/or modify it 15670c104aSTony Lindgren * under the terms of the GNU General Public License as published by the 16670c104aSTony Lindgren * Free Software Foundation; either version 2 of the License, or (at your 17670c104aSTony Lindgren * option) any later version. 18670c104aSTony Lindgren * 19670c104aSTony Lindgren * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 20670c104aSTony Lindgren * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21670c104aSTony Lindgren * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 22670c104aSTony Lindgren * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23670c104aSTony Lindgren * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24670c104aSTony Lindgren * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 25670c104aSTony Lindgren * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26670c104aSTony Lindgren * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27670c104aSTony Lindgren * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28670c104aSTony Lindgren * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29670c104aSTony Lindgren * 30670c104aSTony Lindgren * You should have received a copy of the GNU General Public License along 31670c104aSTony Lindgren * with this program; if not, write to the Free Software Foundation, Inc., 32670c104aSTony Lindgren * 675 Mass Ave, Cambridge, MA 02139, USA. 33670c104aSTony Lindgren */ 34670c104aSTony Lindgren 35670c104aSTony Lindgren#include <linux/linkage.h> 362e3ee9f4STony Lindgren 37670c104aSTony Lindgren#include <asm/assembler.h> 382e3ee9f4STony Lindgren 39*7e0a9e62SArnd Bergmann#include "hardware.h" 404e969010STony Lindgren 412e3ee9f4STony Lindgren#include "iomap.h" 42c912f7e1SKevin Hilman#include "pm.h" 43670c104aSTony Lindgren 44670c104aSTony Lindgren .text 45670c104aSTony Lindgren 46670c104aSTony Lindgren 47670c104aSTony Lindgren/* 48670c104aSTony Lindgren * Forces OMAP into deep sleep state 49670c104aSTony Lindgren * 50670c104aSTony Lindgren * omapXXXX_cpu_suspend() 51670c104aSTony Lindgren * 52670c104aSTony Lindgren * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed 53670c104aSTony Lindgren * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1 54670c104aSTony Lindgren * in register r1. 55670c104aSTony Lindgren * 56670c104aSTony Lindgren * Note: This code get's copied to internal SRAM at boot. When the OMAP 57670c104aSTony Lindgren * wakes up it continues execution at the point it went to sleep. 58670c104aSTony Lindgren * 59670c104aSTony Lindgren * Note: Because of errata work arounds we have processor specific functions 60670c104aSTony Lindgren * here. They are mostly the same, but slightly different. 61670c104aSTony Lindgren * 62670c104aSTony Lindgren */ 63670c104aSTony Lindgren 64670c104aSTony Lindgren#ifdef CONFIG_ARCH_OMAP15XX 65b6338bdcSJean Pihet .align 3 66670c104aSTony LindgrenENTRY(omap1510_cpu_suspend) 67670c104aSTony Lindgren 68670c104aSTony Lindgren @ save registers on stack 69670c104aSTony Lindgren stmfd sp!, {r0 - r12, lr} 70670c104aSTony Lindgren 71670c104aSTony Lindgren @ load base address of Traffic Controller 72670c104aSTony Lindgren mov r4, #TCMIF_ASM_BASE & 0xff000000 73670c104aSTony Lindgren orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000 74670c104aSTony Lindgren orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00 75670c104aSTony Lindgren 76670c104aSTony Lindgren @ work around errata of OMAP1510 PDE bit for TC shut down 77670c104aSTony Lindgren @ clear PDE bit 78670c104aSTony Lindgren ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 79670c104aSTony Lindgren bic r5, r5, #PDE_BIT & 0xff 80670c104aSTony Lindgren str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 81670c104aSTony Lindgren 82670c104aSTony Lindgren @ set PWD_EN bit 83670c104aSTony Lindgren and r5, r5, #PWD_EN_BIT & 0xff 84670c104aSTony Lindgren str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 85670c104aSTony Lindgren 86670c104aSTony Lindgren @ prepare to put SDRAM into self-refresh manually 87670c104aSTony Lindgren ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] 88670c104aSTony Lindgren orr r5, r5, #SELF_REFRESH_MODE & 0xff000000 89670c104aSTony Lindgren orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff 90670c104aSTony Lindgren str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] 91670c104aSTony Lindgren 92670c104aSTony Lindgren @ prepare to put EMIFS to Sleep 93670c104aSTony Lindgren ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 94670c104aSTony Lindgren orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff 95670c104aSTony Lindgren str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 96670c104aSTony Lindgren 97670c104aSTony Lindgren @ load base address of ARM_IDLECT1 and ARM_IDLECT2 98670c104aSTony Lindgren mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 99670c104aSTony Lindgren orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 100670c104aSTony Lindgren orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 101670c104aSTony Lindgren 102670c104aSTony Lindgren @ turn off clock domains 103670c104aSTony Lindgren mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff 104670c104aSTony Lindgren orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 105670c104aSTony Lindgren strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] 106670c104aSTony Lindgren 107670c104aSTony Lindgren @ request ARM idle 108670c104aSTony Lindgren mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff 109670c104aSTony Lindgren orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00 110670c104aSTony Lindgren strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] 111670c104aSTony Lindgren 112670c104aSTony Lindgren mov r5, #IDLE_WAIT_CYCLES & 0xff 113670c104aSTony Lindgren orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 114670c104aSTony Lindgrenl_1510_2: 115670c104aSTony Lindgren subs r5, r5, #1 116670c104aSTony Lindgren bne l_1510_2 117670c104aSTony Lindgren/* 118670c104aSTony Lindgren * Let's wait for the next wake up event to wake us up. r0 can't be 119670c104aSTony Lindgren * used here because r0 holds ARM_IDLECT1 120670c104aSTony Lindgren */ 121670c104aSTony Lindgren mov r2, #0 122670c104aSTony Lindgren mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt 123670c104aSTony Lindgren/* 124670c104aSTony Lindgren * omap1510_cpu_suspend()'s resume point. 125670c104aSTony Lindgren * 126670c104aSTony Lindgren * It will just start executing here, so we'll restore stuff from the 127670c104aSTony Lindgren * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. 128670c104aSTony Lindgren */ 129670c104aSTony Lindgren strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] 130670c104aSTony Lindgren strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] 131670c104aSTony Lindgren 132670c104aSTony Lindgren @ restore regs and return 133670c104aSTony Lindgren ldmfd sp!, {r0 - r12, pc} 134670c104aSTony Lindgren 135670c104aSTony LindgrenENTRY(omap1510_cpu_suspend_sz) 136670c104aSTony Lindgren .word . - omap1510_cpu_suspend 137670c104aSTony Lindgren#endif /* CONFIG_ARCH_OMAP15XX */ 138670c104aSTony Lindgren 139670c104aSTony Lindgren#if defined(CONFIG_ARCH_OMAP16XX) 140b6338bdcSJean Pihet .align 3 141670c104aSTony LindgrenENTRY(omap1610_cpu_suspend) 142670c104aSTony Lindgren 143670c104aSTony Lindgren @ save registers on stack 144670c104aSTony Lindgren stmfd sp!, {r0 - r12, lr} 145670c104aSTony Lindgren 146670c104aSTony Lindgren @ Drain write cache 147670c104aSTony Lindgren mov r4, #0 148670c104aSTony Lindgren mcr p15, 0, r0, c7, c10, 4 149670c104aSTony Lindgren nop 150670c104aSTony Lindgren 151670c104aSTony Lindgren @ Load base address of Traffic Controller 152670c104aSTony Lindgren mov r6, #TCMIF_ASM_BASE & 0xff000000 153670c104aSTony Lindgren orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 154670c104aSTony Lindgren orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 155670c104aSTony Lindgren 156670c104aSTony Lindgren @ Prepare to put SDRAM into self-refresh manually 157670c104aSTony Lindgren ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] 158670c104aSTony Lindgren orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 159670c104aSTony Lindgren orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff 160670c104aSTony Lindgren str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] 161670c104aSTony Lindgren 162670c104aSTony Lindgren @ Prepare to put EMIFS to Sleep 163670c104aSTony Lindgren ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 164670c104aSTony Lindgren orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff 165670c104aSTony Lindgren str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 166670c104aSTony Lindgren 167670c104aSTony Lindgren @ Load base address of ARM_IDLECT1 and ARM_IDLECT2 168670c104aSTony Lindgren mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 169670c104aSTony Lindgren orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 170670c104aSTony Lindgren orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 171670c104aSTony Lindgren 172670c104aSTony Lindgren @ Turn off clock domains 173670c104aSTony Lindgren @ Do not disable PERCK (0x04) 174670c104aSTony Lindgren mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff 175670c104aSTony Lindgren orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00 176670c104aSTony Lindgren strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] 177670c104aSTony Lindgren 178670c104aSTony Lindgren @ Request ARM idle 179670c104aSTony Lindgren mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff 180670c104aSTony Lindgren orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00 181670c104aSTony Lindgren strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] 182670c104aSTony Lindgren 183670c104aSTony Lindgren/* 184670c104aSTony Lindgren * Let's wait for the next wake up event to wake us up. r0 can't be 185670c104aSTony Lindgren * used here because r0 holds ARM_IDLECT1 186670c104aSTony Lindgren */ 187670c104aSTony Lindgren mov r2, #0 188670c104aSTony Lindgren mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt 189670c104aSTony Lindgren 190670c104aSTony Lindgren @ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions 191670c104aSTony Lindgren @ according to this formula: 192670c104aSTony Lindgren @ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV 193670c104aSTony Lindgren @ Max DPLL_MULT = 18 194670c104aSTony Lindgren @ DPLL_DIV = 1 195670c104aSTony Lindgren @ ARMDIV = 1 196670c104aSTony Lindgren @ => 74 nop-instructions 197670c104aSTony Lindgren nop 198670c104aSTony Lindgren nop 199670c104aSTony Lindgren nop 200670c104aSTony Lindgren nop 201670c104aSTony Lindgren nop 202670c104aSTony Lindgren nop 203670c104aSTony Lindgren nop 204670c104aSTony Lindgren nop 205670c104aSTony Lindgren nop 206670c104aSTony Lindgren nop @10 207670c104aSTony Lindgren nop 208670c104aSTony Lindgren nop 209670c104aSTony Lindgren nop 210670c104aSTony Lindgren nop 211670c104aSTony Lindgren nop 212670c104aSTony Lindgren nop 213670c104aSTony Lindgren nop 214670c104aSTony Lindgren nop 215670c104aSTony Lindgren nop 216670c104aSTony Lindgren nop @20 217670c104aSTony Lindgren nop 218670c104aSTony Lindgren nop 219670c104aSTony Lindgren nop 220670c104aSTony Lindgren nop 221670c104aSTony Lindgren nop 222670c104aSTony Lindgren nop 223670c104aSTony Lindgren nop 224670c104aSTony Lindgren nop 225670c104aSTony Lindgren nop 226670c104aSTony Lindgren nop @30 227670c104aSTony Lindgren nop 228670c104aSTony Lindgren nop 229670c104aSTony Lindgren nop 230670c104aSTony Lindgren nop 231670c104aSTony Lindgren nop 232670c104aSTony Lindgren nop 233670c104aSTony Lindgren nop 234670c104aSTony Lindgren nop 235670c104aSTony Lindgren nop 236670c104aSTony Lindgren nop @40 237670c104aSTony Lindgren nop 238670c104aSTony Lindgren nop 239670c104aSTony Lindgren nop 240670c104aSTony Lindgren nop 241670c104aSTony Lindgren nop 242670c104aSTony Lindgren nop 243670c104aSTony Lindgren nop 244670c104aSTony Lindgren nop 245670c104aSTony Lindgren nop 246670c104aSTony Lindgren nop @50 247670c104aSTony Lindgren nop 248670c104aSTony Lindgren nop 249670c104aSTony Lindgren nop 250670c104aSTony Lindgren nop 251670c104aSTony Lindgren nop 252670c104aSTony Lindgren nop 253670c104aSTony Lindgren nop 254670c104aSTony Lindgren nop 255670c104aSTony Lindgren nop 256670c104aSTony Lindgren nop @60 257670c104aSTony Lindgren nop 258670c104aSTony Lindgren nop 259670c104aSTony Lindgren nop 260670c104aSTony Lindgren nop 261670c104aSTony Lindgren nop 262670c104aSTony Lindgren nop 263670c104aSTony Lindgren nop 264670c104aSTony Lindgren nop 265670c104aSTony Lindgren nop 266670c104aSTony Lindgren nop @70 267670c104aSTony Lindgren nop 268670c104aSTony Lindgren nop 269670c104aSTony Lindgren nop 270670c104aSTony Lindgren nop @74 271670c104aSTony Lindgren/* 272670c104aSTony Lindgren * omap1610_cpu_suspend()'s resume point. 273670c104aSTony Lindgren * 274670c104aSTony Lindgren * It will just start executing here, so we'll restore stuff from the 275670c104aSTony Lindgren * stack. 276670c104aSTony Lindgren */ 277670c104aSTony Lindgren @ Restore the ARM_IDLECT1 and ARM_IDLECT2. 278670c104aSTony Lindgren strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] 279670c104aSTony Lindgren strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] 280670c104aSTony Lindgren 281670c104aSTony Lindgren @ Restore EMIFF controls 282670c104aSTony Lindgren str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] 283670c104aSTony Lindgren str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 284670c104aSTony Lindgren 285670c104aSTony Lindgren @ Restore regs and return 286670c104aSTony Lindgren ldmfd sp!, {r0 - r12, pc} 287670c104aSTony Lindgren 288670c104aSTony LindgrenENTRY(omap1610_cpu_suspend_sz) 289670c104aSTony Lindgren .word . - omap1610_cpu_suspend 290670c104aSTony Lindgren#endif /* CONFIG_ARCH_OMAP16XX */ 291