Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * linux/arch/arm/mach-omap2/sleep.S
0004  *
0005  * (C) Copyright 2004
0006  * Texas Instruments, <www.ti.com>
0007  * Richard Woodruff <r-woodruff2@ti.com>
0008  *
0009  * (C) Copyright 2006 Nokia Corporation
0010  * Fixed idle loop sleep
0011  * Igor Stoppa <igor.stoppa@nokia.com>
0012  */
0013 
0014 #include <linux/linkage.h>
0015 #include <asm/assembler.h>
0016 
0017 #include "omap24xx.h"
0018 #include "sdrc.h"
0019 
0020 /* First address of reserved address space?  apparently valid for OMAP2 & 3 */
0021 #define A_SDRC0_V       (0xC0000000)
0022 
0023     .text
0024 
0025 /*
0026  * omap24xx_cpu_suspend() - Forces OMAP into deep sleep state by completing
0027  * SDRC shutdown then ARM shutdown.  Upon wake MPU is back on so just restore
0028  * SDRC.
0029  *
0030  * Input:
0031  * R0 : DLL ctrl value pre-Sleep
0032  * R1 : SDRC_DLLA_CTRL
0033  * R2 : SDRC_POWER
0034  *
0035  * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
0036  * when we get called, but the DLL probably isn't.  We will wait a bit more in
0037  * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
0038  * if in unlocked mode.
0039  *
0040  * For less than 242x-ES2.2 upon wake from a sleep mode where the external
0041  * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
0042  * clock can pass into the PRCM can cause problems at DSP and IVA.
0043  * To work around this the code will switch to the 32kHz source prior to sleep.
0044  * Post sleep we will shift back to using the DPLL.  Apparently,
0045  * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
0046  * 3x12MHz + 3x32kHz clocks for a full switch.
0047  *
0048  * The DLL load value is not kept in RETENTION or OFF.  It needs to be restored
0049  * at wake
0050  */
0051     .align  3
0052 ENTRY(omap24xx_cpu_suspend)
0053     stmfd   sp!, {r0 - r12, lr} @ save registers on stack
0054     mov r3, #0x0        @ clear for mcr call
0055     mcr p15, 0, r3, c7, c10, 4  @ memory barrier, hope SDR/DDR finished
0056     nop
0057     nop
0058     ldr r4, [r2]        @ read SDRC_POWER
0059     orr r4, r4, #0x40       @ enable self refresh on idle req
0060     mov r5, #0x2000     @ set delay (DPLL relock + DLL relock)
0061     str r4, [r2]        @ make it so
0062     nop
0063     mcr p15, 0, r3, c7, c0, 4   @ wait for interrupt
0064     nop
0065 loop:
0066     subs    r5, r5, #0x1        @ awake, wait just a bit
0067     bne loop
0068 
0069     /* The DPLL has to be on before we take the DDR out of self refresh */
0070     bic r4, r4, #0x40       @ now clear self refresh bit.
0071     str r4, [r2]        @ write to SDRC_POWER
0072     ldr r4, A_SDRC0     @ make a clock happen
0073     ldr r4, [r4]        @ read A_SDRC0
0074     nop             @ start auto refresh only after clk ok
0075     movs    r0, r0          @ see if DDR or SDR
0076     strne   r0, [r1]        @ rewrite DLLA to force DLL reload
0077     addne   r1, r1, #0x8        @ move to DLLB
0078     strne   r0, [r1]        @ rewrite DLLB to force DLL reload
0079 
0080     mov r5, #0x1000
0081 loop2:
0082     subs    r5, r5, #0x1
0083     bne loop2
0084     /* resume*/
0085     ldmfd   sp!, {r0 - r12, pc} @ restore regs and return
0086 
0087 A_SDRC0:
0088     .word A_SDRC0_V
0089 
0090 ENTRY(omap24xx_cpu_suspend_sz)
0091     .word   . - omap24xx_cpu_suspend