root/arch/arm/mach-davinci/sleep.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0-only */
   2 /*
   3  * (C) Copyright 2009, Texas Instruments, Inc. http://www.ti.com/
   4  */
   5 
   6 /* replicated define because linux/bitops.h cannot be included in assembly */
   7 #define BIT(nr)                 (1 << (nr))
   8 
   9 #include <linux/linkage.h>
  10 #include <asm/assembler.h>
  11 #include "psc.h"
  12 #include "ddr2.h"
  13 
  14 #include "clock.h"
  15 
  16 /* Arbitrary, hardware currently does not update PHYRDY correctly */
  17 #define PHYRDY_CYCLES           0x1000
  18 
  19 /* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */
  20 #define PLL_BYPASS_CYCLES       (PLL_BYPASS_TIME * 25)
  21 #define PLL_RESET_CYCLES        (PLL_RESET_TIME * 25)
  22 #define PLL_LOCK_CYCLES         (PLL_LOCK_TIME * 25)
  23 
  24 #define DEEPSLEEP_SLEEPENABLE_BIT       BIT(31)
  25 
  26         .text
  27         .arch   armv5te
  28 /*
  29  * Move DaVinci into deep sleep state
  30  *
  31  * Note: This code is copied to internal SRAM by PM code. When the DaVinci
  32  *       wakes up it continues execution at the point it went to sleep.
  33  * Register Usage:
  34  *      r0: contains virtual base for DDR2 controller
  35  *      r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
  36  *      r2: contains PSC number for DDR2
  37  *      r3: contains virtual base DDR2 PLL controller
  38  *      r4: contains virtual address of the DEEPSLEEP register
  39  */
  40 ENTRY(davinci_cpu_suspend)
  41         stmfd   sp!, {r0-r12, lr}               @ save registers on stack
  42 
  43         ldr     ip, CACHE_FLUSH
  44         blx     ip
  45 
  46         ldmia   r0, {r0-r4}
  47 
  48         /*
  49          * Switch DDR to self-refresh mode.
  50          */
  51 
  52         /* calculate SDRCR address */
  53         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
  54         bic     ip, ip, #DDR2_SRPD_BIT
  55         orr     ip, ip, #DDR2_LPMODEN_BIT
  56         str     ip, [r0, #DDR2_SDRCR_OFFSET]
  57 
  58         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
  59         orr     ip, ip, #DDR2_MCLKSTOPEN_BIT
  60         str     ip, [r0, #DDR2_SDRCR_OFFSET]
  61 
  62        mov      ip, #PHYRDY_CYCLES
  63 1:     subs     ip, ip, #0x1
  64        bne      1b
  65 
  66        /* Disable DDR2 LPSC */
  67         mov     r7, r0
  68         mov     r0, #0x2
  69         bl davinci_ddr_psc_config
  70         mov     r0, r7
  71 
  72         /* Disable clock to DDR PHY */
  73         ldr     ip, [r3, #PLLDIV1]
  74         bic     ip, ip, #PLLDIV_EN
  75         str     ip, [r3, #PLLDIV1]
  76 
  77         /* Put the DDR PLL in bypass and power down */
  78         ldr     ip, [r3, #PLLCTL]
  79         bic     ip, ip, #PLLCTL_PLLENSRC
  80         bic     ip, ip, #PLLCTL_PLLEN
  81         str     ip, [r3, #PLLCTL]
  82 
  83         /* Wait for PLL to switch to bypass */
  84        mov      ip, #PLL_BYPASS_CYCLES
  85 2:     subs     ip, ip, #0x1
  86        bne      2b
  87 
  88        /* Power down the PLL */
  89         ldr     ip, [r3, #PLLCTL]
  90         orr     ip, ip, #PLLCTL_PLLPWRDN
  91         str     ip, [r3, #PLLCTL]
  92 
  93         /* Go to deep sleep */
  94         ldr     ip, [r4]
  95         orr     ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
  96         /* System goes to sleep beyond after this instruction */
  97         str     ip, [r4]
  98 
  99         /* Wake up from sleep */
 100 
 101         /* Clear sleep enable */
 102         ldr     ip, [r4]
 103         bic     ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
 104         str     ip, [r4]
 105 
 106         /* initialize the DDR PLL controller */
 107 
 108         /* Put PLL in reset */
 109         ldr     ip, [r3, #PLLCTL]
 110         bic     ip, ip, #PLLCTL_PLLRST
 111         str     ip, [r3, #PLLCTL]
 112 
 113         /* Clear PLL power down */
 114         ldr     ip, [r3, #PLLCTL]
 115         bic     ip, ip, #PLLCTL_PLLPWRDN
 116         str     ip, [r3, #PLLCTL]
 117 
 118        mov      ip, #PLL_RESET_CYCLES
 119 3:     subs     ip, ip, #0x1
 120        bne      3b
 121 
 122        /* Bring PLL out of reset */
 123         ldr     ip, [r3, #PLLCTL]
 124         orr     ip, ip, #PLLCTL_PLLRST
 125         str     ip, [r3, #PLLCTL]
 126 
 127         /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
 128        mov      ip, #PLL_LOCK_CYCLES
 129 4:     subs     ip, ip, #0x1
 130        bne      4b
 131 
 132        /* Remove PLL from bypass mode */
 133         ldr     ip, [r3, #PLLCTL]
 134         bic     ip, ip, #PLLCTL_PLLENSRC
 135         orr     ip, ip, #PLLCTL_PLLEN
 136         str     ip, [r3, #PLLCTL]
 137 
 138         /* Start 2x clock to DDR2 */
 139 
 140         ldr     ip, [r3, #PLLDIV1]
 141         orr     ip, ip, #PLLDIV_EN
 142         str     ip, [r3, #PLLDIV1]
 143 
 144         /* Enable VCLK */
 145 
 146        /* Enable DDR2 LPSC */
 147         mov     r7, r0
 148         mov     r0, #0x3
 149         bl davinci_ddr_psc_config
 150         mov     r0, r7
 151 
 152         /* clear  MCLKSTOPEN */
 153 
 154         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
 155         bic     ip, ip, #DDR2_MCLKSTOPEN_BIT
 156         str     ip, [r0, #DDR2_SDRCR_OFFSET]
 157 
 158         ldr     ip, [r0, #DDR2_SDRCR_OFFSET]
 159         bic     ip, ip, #DDR2_LPMODEN_BIT
 160         str     ip, [r0, #DDR2_SDRCR_OFFSET]
 161 
 162         /* Restore registers and return */
 163         ldmfd   sp!, {r0-r12, pc}
 164 
 165 ENDPROC(davinci_cpu_suspend)
 166 
 167 /*
 168  * Disables or Enables DDR2 LPSC
 169  * Register Usage:
 170  *      r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
 171  *      r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
 172  *      r2: contains PSC number for DDR2
 173  */
 174 ENTRY(davinci_ddr_psc_config)
 175         /* Set next state in mdctl for DDR2 */
 176         mov     r6, #MDCTL
 177         add     r6, r6, r2, lsl #2
 178         ldr     ip, [r1, r6]
 179         bic     ip, ip, #MDSTAT_STATE_MASK
 180         orr     ip, ip, r0
 181         str     ip, [r1, r6]
 182 
 183         /* Enable the Power Domain Transition Command */
 184         ldr     ip, [r1, #PTCMD]
 185         orr     ip, ip, #0x1
 186         str     ip, [r1, #PTCMD]
 187 
 188         /* Check for Transition Complete (PTSTAT) */
 189 ptstat_done:
 190         ldr     ip, [r1, #PTSTAT]
 191         and     ip, ip, #0x1
 192         cmp     ip, #0x0
 193         bne     ptstat_done
 194 
 195         /* Check for DDR2 clock disable completion; */
 196         mov     r6, #MDSTAT
 197         add     r6, r6, r2, lsl #2
 198 ddr2clk_stop_done:
 199         ldr     ip, [r1, r6]
 200         and     ip, ip, #MDSTAT_STATE_MASK
 201         cmp     ip, r0
 202         bne     ddr2clk_stop_done
 203 
 204         ret     lr
 205 ENDPROC(davinci_ddr_psc_config)
 206 
 207 CACHE_FLUSH:
 208 #ifdef CONFIG_CPU_V6
 209         .word   v6_flush_kern_cache_all
 210 #else
 211         .word   arm926_flush_kern_cache_all
 212 #endif
 213 
 214 ENTRY(davinci_cpu_suspend_sz)
 215         .word   . - davinci_cpu_suspend
 216 ENDPROC(davinci_cpu_suspend_sz)

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