^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-or-later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/arch/arm/mach-omap2/sleep.S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (C) Copyright 2004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Texas Instruments, <www.ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Richard Woodruff <r-woodruff2@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * (C) Copyright 2006 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Fixed idle loop sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Igor Stoppa <igor.stoppa@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/assembler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "omap24xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "sdrc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* First address of reserved address space? apparently valid for OMAP2 & 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define A_SDRC0_V (0xC0000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) .text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * omap24xx_cpu_suspend() - Forces OMAP into deep sleep state by completing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * SDRC shutdown then ARM shutdown. Upon wake MPU is back on so just restore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * SDRC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * R0 : DLL ctrl value pre-Sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * R1 : SDRC_DLLA_CTRL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * R2 : SDRC_POWER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * The if the DPLL is going to AutoIdle. It seems like the DPLL may be back on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * when we get called, but the DLL probably isn't. We will wait a bit more in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * case the DPLL isn't quite there yet. The code will wait on DLL for DDR even
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * if in unlocked mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * For less than 242x-ES2.2 upon wake from a sleep mode where the external
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * oscillator was stopped, a timing bug exists where a non-stabilized 12MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * clock can pass into the PRCM can cause problems at DSP and IVA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * To work around this the code will switch to the 32kHz source prior to sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * Post sleep we will shift back to using the DPLL. Apparently,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * CM_IDLEST_CLKGEN does not reflect the full clock change so you need to wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * 3x12MHz + 3x32kHz clocks for a full switch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * The DLL load value is not kept in RETENTION or OFF. It needs to be restored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * at wake
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .align 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ENTRY(omap24xx_cpu_suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) stmfd sp!, {r0 - r12, lr} @ save registers on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) mov r3, #0x0 @ clear for mcr call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) mcr p15, 0, r3, c7, c10, 4 @ memory barrier, hope SDR/DDR finished
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ldr r4, [r2] @ read SDRC_POWER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) orr r4, r4, #0x40 @ enable self refresh on idle req
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) mov r5, #0x2000 @ set delay (DPLL relock + DLL relock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) str r4, [r2] @ make it so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) mcr p15, 0, r3, c7, c0, 4 @ wait for interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) subs r5, r5, #0x1 @ awake, wait just a bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) bne loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* The DPLL has to be on before we take the DDR out of self refresh */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) bic r4, r4, #0x40 @ now clear self refresh bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) str r4, [r2] @ write to SDRC_POWER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ldr r4, A_SDRC0 @ make a clock happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ldr r4, [r4] @ read A_SDRC0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) nop @ start auto refresh only after clk ok
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) movs r0, r0 @ see if DDR or SDR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) strne r0, [r1] @ rewrite DLLA to force DLL reload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) addne r1, r1, #0x8 @ move to DLLB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) strne r0, [r1] @ rewrite DLLB to force DLL reload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) mov r5, #0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) loop2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) subs r5, r5, #0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) bne loop2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* resume*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ldmfd sp!, {r0 - r12, pc} @ restore regs and return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) A_SDRC0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .word A_SDRC0_V
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ENTRY(omap24xx_cpu_suspend_sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .word . - omap24xx_cpu_suspend