162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * linux/arch/arm/mach-omap1/sleep.S 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Low-level OMAP7XX/1510/1610 sleep/wakeUp support 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Initial SA1110 code: 762306a36Sopenharmony_ci * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Adapted for PXA by Nicolas Pitre: 1062306a36Sopenharmony_ci * Copyright (c) 2002 Monta Vista Software, Inc. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com> 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it 1562306a36Sopenharmony_ci * under the terms of the GNU General Public License as published by the 1662306a36Sopenharmony_ci * Free Software Foundation; either version 2 of the License, or (at your 1762306a36Sopenharmony_ci * option) any later version. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 2062306a36Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 2162306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 2262306a36Sopenharmony_ci * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2362306a36Sopenharmony_ci * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2462306a36Sopenharmony_ci * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 2562306a36Sopenharmony_ci * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 2662306a36Sopenharmony_ci * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2762306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2862306a36Sopenharmony_ci * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * You should have received a copy of the GNU General Public License along 3162306a36Sopenharmony_ci * with this program; if not, write to the Free Software Foundation, Inc., 3262306a36Sopenharmony_ci * 675 Mass Ave, Cambridge, MA 02139, USA. 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include <linux/linkage.h> 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#include <asm/assembler.h> 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#include "hardware.h" 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#include "iomap.h" 4262306a36Sopenharmony_ci#include "pm.h" 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci .text 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* 4862306a36Sopenharmony_ci * Forces OMAP into deep sleep state 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * omapXXXX_cpu_suspend() 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed 5362306a36Sopenharmony_ci * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1 5462306a36Sopenharmony_ci * in register r1. 5562306a36Sopenharmony_ci * 5662306a36Sopenharmony_ci * Note: This code get's copied to internal SRAM at boot. When the OMAP 5762306a36Sopenharmony_ci * wakes up it continues execution at the point it went to sleep. 5862306a36Sopenharmony_ci * 5962306a36Sopenharmony_ci * Note: Because of errata work arounds we have processor specific functions 6062306a36Sopenharmony_ci * here. They are mostly the same, but slightly different. 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#ifdef CONFIG_ARCH_OMAP15XX 6562306a36Sopenharmony_ci .align 3 6662306a36Sopenharmony_ciENTRY(omap1510_cpu_suspend) 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci @ save registers on stack 6962306a36Sopenharmony_ci stmfd sp!, {r0 - r12, lr} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci @ load base address of Traffic Controller 7262306a36Sopenharmony_ci mov r4, #TCMIF_ASM_BASE & 0xff000000 7362306a36Sopenharmony_ci orr r4, r4, #TCMIF_ASM_BASE & 0x00ff0000 7462306a36Sopenharmony_ci orr r4, r4, #TCMIF_ASM_BASE & 0x0000ff00 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci @ work around errata of OMAP1510 PDE bit for TC shut down 7762306a36Sopenharmony_ci @ clear PDE bit 7862306a36Sopenharmony_ci ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 7962306a36Sopenharmony_ci bic r5, r5, #PDE_BIT & 0xff 8062306a36Sopenharmony_ci str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci @ set PWD_EN bit 8362306a36Sopenharmony_ci and r5, r5, #PWD_EN_BIT & 0xff 8462306a36Sopenharmony_ci str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci @ prepare to put SDRAM into self-refresh manually 8762306a36Sopenharmony_ci ldr r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] 8862306a36Sopenharmony_ci orr r5, r5, #SELF_REFRESH_MODE & 0xff000000 8962306a36Sopenharmony_ci orr r5, r5, #SELF_REFRESH_MODE & 0x000000ff 9062306a36Sopenharmony_ci str r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci @ prepare to put EMIFS to Sleep 9362306a36Sopenharmony_ci ldr r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 9462306a36Sopenharmony_ci orr r5, r5, #IDLE_EMIFS_REQUEST & 0xff 9562306a36Sopenharmony_ci str r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci @ load base address of ARM_IDLECT1 and ARM_IDLECT2 9862306a36Sopenharmony_ci mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 9962306a36Sopenharmony_ci orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 10062306a36Sopenharmony_ci orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci @ turn off clock domains 10362306a36Sopenharmony_ci mov r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff 10462306a36Sopenharmony_ci orr r5, r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00 10562306a36Sopenharmony_ci strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci @ request ARM idle 10862306a36Sopenharmony_ci mov r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff 10962306a36Sopenharmony_ci orr r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00 11062306a36Sopenharmony_ci strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci mov r5, #IDLE_WAIT_CYCLES & 0xff 11362306a36Sopenharmony_ci orr r5, r5, #IDLE_WAIT_CYCLES & 0xff00 11462306a36Sopenharmony_cil_1510_2: 11562306a36Sopenharmony_ci subs r5, r5, #1 11662306a36Sopenharmony_ci bne l_1510_2 11762306a36Sopenharmony_ci/* 11862306a36Sopenharmony_ci * Let's wait for the next wake up event to wake us up. r0 can't be 11962306a36Sopenharmony_ci * used here because r0 holds ARM_IDLECT1 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ci mov r2, #0 12262306a36Sopenharmony_ci mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt 12362306a36Sopenharmony_ci/* 12462306a36Sopenharmony_ci * omap1510_cpu_suspend()'s resume point. 12562306a36Sopenharmony_ci * 12662306a36Sopenharmony_ci * It will just start executing here, so we'll restore stuff from the 12762306a36Sopenharmony_ci * stack, reset the ARM_IDLECT1 and ARM_IDLECT2. 12862306a36Sopenharmony_ci */ 12962306a36Sopenharmony_ci strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] 13062306a36Sopenharmony_ci strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci @ restore regs and return 13362306a36Sopenharmony_ci ldmfd sp!, {r0 - r12, pc} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ciENTRY(omap1510_cpu_suspend_sz) 13662306a36Sopenharmony_ci .word . - omap1510_cpu_suspend 13762306a36Sopenharmony_ci#endif /* CONFIG_ARCH_OMAP15XX */ 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci#if defined(CONFIG_ARCH_OMAP16XX) 14062306a36Sopenharmony_ci .align 3 14162306a36Sopenharmony_ciENTRY(omap1610_cpu_suspend) 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci @ save registers on stack 14462306a36Sopenharmony_ci stmfd sp!, {r0 - r12, lr} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci @ Drain write cache 14762306a36Sopenharmony_ci mov r4, #0 14862306a36Sopenharmony_ci mcr p15, 0, r0, c7, c10, 4 14962306a36Sopenharmony_ci nop 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci @ Load base address of Traffic Controller 15262306a36Sopenharmony_ci mov r6, #TCMIF_ASM_BASE & 0xff000000 15362306a36Sopenharmony_ci orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000 15462306a36Sopenharmony_ci orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci @ Prepare to put SDRAM into self-refresh manually 15762306a36Sopenharmony_ci ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] 15862306a36Sopenharmony_ci orr r9, r7, #SELF_REFRESH_MODE & 0xff000000 15962306a36Sopenharmony_ci orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff 16062306a36Sopenharmony_ci str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci @ Prepare to put EMIFS to Sleep 16362306a36Sopenharmony_ci ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 16462306a36Sopenharmony_ci orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff 16562306a36Sopenharmony_ci str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci @ Load base address of ARM_IDLECT1 and ARM_IDLECT2 16862306a36Sopenharmony_ci mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000 16962306a36Sopenharmony_ci orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000 17062306a36Sopenharmony_ci orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci @ Turn off clock domains 17362306a36Sopenharmony_ci @ Do not disable PERCK (0x04) 17462306a36Sopenharmony_ci mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff 17562306a36Sopenharmony_ci orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00 17662306a36Sopenharmony_ci strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci @ Request ARM idle 17962306a36Sopenharmony_ci mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff 18062306a36Sopenharmony_ci orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00 18162306a36Sopenharmony_ci strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci/* 18462306a36Sopenharmony_ci * Let's wait for the next wake up event to wake us up. r0 can't be 18562306a36Sopenharmony_ci * used here because r0 holds ARM_IDLECT1 18662306a36Sopenharmony_ci */ 18762306a36Sopenharmony_ci mov r2, #0 18862306a36Sopenharmony_ci mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci @ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions 19162306a36Sopenharmony_ci @ according to this formula: 19262306a36Sopenharmony_ci @ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV 19362306a36Sopenharmony_ci @ Max DPLL_MULT = 18 19462306a36Sopenharmony_ci @ DPLL_DIV = 1 19562306a36Sopenharmony_ci @ ARMDIV = 1 19662306a36Sopenharmony_ci @ => 74 nop-instructions 19762306a36Sopenharmony_ci nop 19862306a36Sopenharmony_ci nop 19962306a36Sopenharmony_ci nop 20062306a36Sopenharmony_ci nop 20162306a36Sopenharmony_ci nop 20262306a36Sopenharmony_ci nop 20362306a36Sopenharmony_ci nop 20462306a36Sopenharmony_ci nop 20562306a36Sopenharmony_ci nop 20662306a36Sopenharmony_ci nop @10 20762306a36Sopenharmony_ci nop 20862306a36Sopenharmony_ci nop 20962306a36Sopenharmony_ci nop 21062306a36Sopenharmony_ci nop 21162306a36Sopenharmony_ci nop 21262306a36Sopenharmony_ci nop 21362306a36Sopenharmony_ci nop 21462306a36Sopenharmony_ci nop 21562306a36Sopenharmony_ci nop 21662306a36Sopenharmony_ci nop @20 21762306a36Sopenharmony_ci nop 21862306a36Sopenharmony_ci nop 21962306a36Sopenharmony_ci nop 22062306a36Sopenharmony_ci nop 22162306a36Sopenharmony_ci nop 22262306a36Sopenharmony_ci nop 22362306a36Sopenharmony_ci nop 22462306a36Sopenharmony_ci nop 22562306a36Sopenharmony_ci nop 22662306a36Sopenharmony_ci nop @30 22762306a36Sopenharmony_ci nop 22862306a36Sopenharmony_ci nop 22962306a36Sopenharmony_ci nop 23062306a36Sopenharmony_ci nop 23162306a36Sopenharmony_ci nop 23262306a36Sopenharmony_ci nop 23362306a36Sopenharmony_ci nop 23462306a36Sopenharmony_ci nop 23562306a36Sopenharmony_ci nop 23662306a36Sopenharmony_ci nop @40 23762306a36Sopenharmony_ci nop 23862306a36Sopenharmony_ci nop 23962306a36Sopenharmony_ci nop 24062306a36Sopenharmony_ci nop 24162306a36Sopenharmony_ci nop 24262306a36Sopenharmony_ci nop 24362306a36Sopenharmony_ci nop 24462306a36Sopenharmony_ci nop 24562306a36Sopenharmony_ci nop 24662306a36Sopenharmony_ci nop @50 24762306a36Sopenharmony_ci nop 24862306a36Sopenharmony_ci nop 24962306a36Sopenharmony_ci nop 25062306a36Sopenharmony_ci nop 25162306a36Sopenharmony_ci nop 25262306a36Sopenharmony_ci nop 25362306a36Sopenharmony_ci nop 25462306a36Sopenharmony_ci nop 25562306a36Sopenharmony_ci nop 25662306a36Sopenharmony_ci nop @60 25762306a36Sopenharmony_ci nop 25862306a36Sopenharmony_ci nop 25962306a36Sopenharmony_ci nop 26062306a36Sopenharmony_ci nop 26162306a36Sopenharmony_ci nop 26262306a36Sopenharmony_ci nop 26362306a36Sopenharmony_ci nop 26462306a36Sopenharmony_ci nop 26562306a36Sopenharmony_ci nop 26662306a36Sopenharmony_ci nop @70 26762306a36Sopenharmony_ci nop 26862306a36Sopenharmony_ci nop 26962306a36Sopenharmony_ci nop 27062306a36Sopenharmony_ci nop @74 27162306a36Sopenharmony_ci/* 27262306a36Sopenharmony_ci * omap1610_cpu_suspend()'s resume point. 27362306a36Sopenharmony_ci * 27462306a36Sopenharmony_ci * It will just start executing here, so we'll restore stuff from the 27562306a36Sopenharmony_ci * stack. 27662306a36Sopenharmony_ci */ 27762306a36Sopenharmony_ci @ Restore the ARM_IDLECT1 and ARM_IDLECT2. 27862306a36Sopenharmony_ci strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] 27962306a36Sopenharmony_ci strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci @ Restore EMIFF controls 28262306a36Sopenharmony_ci str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff] 28362306a36Sopenharmony_ci str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff] 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci @ Restore regs and return 28662306a36Sopenharmony_ci ldmfd sp!, {r0 - r12, pc} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ciENTRY(omap1610_cpu_suspend_sz) 28962306a36Sopenharmony_ci .word . - omap1610_cpu_suspend 29062306a36Sopenharmony_ci#endif /* CONFIG_ARCH_OMAP16XX */ 291