root/arch/arm/mach-omap2/sleep24xx.S

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

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