Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * (C) Copyright 2009, Texas Instruments, Inc. https://www.ti.com/
0004  */
0005 
0006 /* replicated define because linux/bitops.h cannot be included in assembly */
0007 #define BIT(nr)         (1 << (nr))
0008 
0009 #include <linux/linkage.h>
0010 #include <asm/assembler.h>
0011 #include "psc.h"
0012 #include "ddr2.h"
0013 
0014 #include "clock.h"
0015 
0016 /* Arbitrary, hardware currently does not update PHYRDY correctly */
0017 #define PHYRDY_CYCLES       0x1000
0018 
0019 /* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */
0020 #define PLL_BYPASS_CYCLES   (PLL_BYPASS_TIME * 25)
0021 #define PLL_RESET_CYCLES    (PLL_RESET_TIME * 25)
0022 #define PLL_LOCK_CYCLES     (PLL_LOCK_TIME * 25)
0023 
0024 #define DEEPSLEEP_SLEEPENABLE_BIT   BIT(31)
0025 
0026     .text
0027     .arch   armv5te
0028 /*
0029  * Move DaVinci into deep sleep state
0030  *
0031  * Note: This code is copied to internal SRAM by PM code. When the DaVinci
0032  *   wakes up it continues execution at the point it went to sleep.
0033  * Register Usage:
0034  *  r0: contains virtual base for DDR2 controller
0035  *  r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
0036  *  r2: contains PSC number for DDR2
0037  *  r3: contains virtual base DDR2 PLL controller
0038  *  r4: contains virtual address of the DEEPSLEEP register
0039  */
0040 ENTRY(davinci_cpu_suspend)
0041     stmfd   sp!, {r0-r12, lr}       @ save registers on stack
0042 
0043     ldr     ip, CACHE_FLUSH
0044     blx ip
0045 
0046     ldmia   r0, {r0-r4}
0047 
0048     /*
0049      * Switch DDR to self-refresh mode.
0050      */
0051 
0052     /* calculate SDRCR address */
0053     ldr ip, [r0, #DDR2_SDRCR_OFFSET]
0054     bic ip, ip, #DDR2_SRPD_BIT
0055     orr ip, ip, #DDR2_LPMODEN_BIT
0056     str ip, [r0, #DDR2_SDRCR_OFFSET]
0057 
0058     ldr ip, [r0, #DDR2_SDRCR_OFFSET]
0059     orr ip, ip, #DDR2_MCLKSTOPEN_BIT
0060     str ip, [r0, #DDR2_SDRCR_OFFSET]
0061 
0062        mov  ip, #PHYRDY_CYCLES
0063 1:     subs ip, ip, #0x1
0064        bne  1b
0065 
0066        /* Disable DDR2 LPSC */
0067     mov r7, r0
0068     mov r0, #0x2
0069     bl davinci_ddr_psc_config
0070     mov r0, r7
0071 
0072     /* Disable clock to DDR PHY */
0073     ldr ip, [r3, #PLLDIV1]
0074     bic ip, ip, #PLLDIV_EN
0075     str ip, [r3, #PLLDIV1]
0076 
0077     /* Put the DDR PLL in bypass and power down */
0078     ldr ip, [r3, #PLLCTL]
0079     bic ip, ip, #PLLCTL_PLLENSRC
0080     bic ip, ip, #PLLCTL_PLLEN
0081     str ip, [r3, #PLLCTL]
0082 
0083     /* Wait for PLL to switch to bypass */
0084        mov  ip, #PLL_BYPASS_CYCLES
0085 2:     subs ip, ip, #0x1
0086        bne  2b
0087 
0088        /* Power down the PLL */
0089     ldr ip, [r3, #PLLCTL]
0090     orr ip, ip, #PLLCTL_PLLPWRDN
0091     str ip, [r3, #PLLCTL]
0092 
0093     /* Go to deep sleep */
0094     ldr ip, [r4]
0095     orr ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
0096     /* System goes to sleep beyond after this instruction */
0097     str ip, [r4]
0098 
0099     /* Wake up from sleep */
0100 
0101     /* Clear sleep enable */
0102     ldr ip, [r4]
0103     bic ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
0104     str ip, [r4]
0105 
0106     /* initialize the DDR PLL controller */
0107 
0108     /* Put PLL in reset */
0109     ldr ip, [r3, #PLLCTL]
0110     bic ip, ip, #PLLCTL_PLLRST
0111     str ip, [r3, #PLLCTL]
0112 
0113     /* Clear PLL power down */
0114     ldr ip, [r3, #PLLCTL]
0115     bic ip, ip, #PLLCTL_PLLPWRDN
0116     str ip, [r3, #PLLCTL]
0117 
0118        mov  ip, #PLL_RESET_CYCLES
0119 3:     subs ip, ip, #0x1
0120        bne  3b
0121 
0122        /* Bring PLL out of reset */
0123     ldr ip, [r3, #PLLCTL]
0124     orr ip, ip, #PLLCTL_PLLRST
0125     str ip, [r3, #PLLCTL]
0126 
0127     /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
0128        mov  ip, #PLL_LOCK_CYCLES
0129 4:     subs ip, ip, #0x1
0130        bne  4b
0131 
0132        /* Remove PLL from bypass mode */
0133     ldr ip, [r3, #PLLCTL]
0134     bic ip, ip, #PLLCTL_PLLENSRC
0135     orr ip, ip, #PLLCTL_PLLEN
0136     str ip, [r3, #PLLCTL]
0137 
0138     /* Start 2x clock to DDR2 */
0139 
0140     ldr ip, [r3, #PLLDIV1]
0141     orr ip, ip, #PLLDIV_EN
0142     str ip, [r3, #PLLDIV1]
0143 
0144     /* Enable VCLK */
0145 
0146        /* Enable DDR2 LPSC */
0147     mov r7, r0
0148     mov r0, #0x3
0149     bl davinci_ddr_psc_config
0150     mov r0, r7
0151 
0152     /* clear  MCLKSTOPEN */
0153 
0154     ldr ip, [r0, #DDR2_SDRCR_OFFSET]
0155     bic ip, ip, #DDR2_MCLKSTOPEN_BIT
0156     str ip, [r0, #DDR2_SDRCR_OFFSET]
0157 
0158     ldr ip, [r0, #DDR2_SDRCR_OFFSET]
0159     bic ip, ip, #DDR2_LPMODEN_BIT
0160     str ip, [r0, #DDR2_SDRCR_OFFSET]
0161 
0162     /* Restore registers and return */
0163     ldmfd   sp!, {r0-r12, pc}
0164 
0165 ENDPROC(davinci_cpu_suspend)
0166 
0167 /*
0168  * Disables or Enables DDR2 LPSC
0169  * Register Usage:
0170  *  r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
0171  *  r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
0172  *  r2: contains PSC number for DDR2
0173  */
0174 ENTRY(davinci_ddr_psc_config)
0175     /* Set next state in mdctl for DDR2 */
0176     mov r6, #MDCTL
0177     add r6, r6, r2, lsl #2
0178     ldr ip, [r1, r6]
0179     bic ip, ip, #MDSTAT_STATE_MASK
0180     orr ip, ip, r0
0181     str ip, [r1, r6]
0182 
0183     /* Enable the Power Domain Transition Command */
0184     ldr ip, [r1, #PTCMD]
0185     orr ip, ip, #0x1
0186     str ip, [r1, #PTCMD]
0187 
0188     /* Check for Transition Complete (PTSTAT) */
0189 ptstat_done:
0190     ldr ip, [r1, #PTSTAT]
0191     and ip, ip, #0x1
0192     cmp     ip, #0x0
0193     bne ptstat_done
0194 
0195     /* Check for DDR2 clock disable completion; */
0196     mov r6, #MDSTAT
0197     add r6, r6, r2, lsl #2
0198 ddr2clk_stop_done:
0199     ldr ip, [r1, r6]
0200     and ip, ip, #MDSTAT_STATE_MASK
0201     cmp ip, r0
0202     bne ddr2clk_stop_done
0203 
0204     ret lr
0205 ENDPROC(davinci_ddr_psc_config)
0206 
0207 CACHE_FLUSH:
0208 #ifdef CONFIG_CPU_V6
0209     .word   v6_flush_kern_cache_all
0210 #else
0211     .word   arm926_flush_kern_cache_all
0212 #endif
0213 
0214 ENTRY(davinci_cpu_suspend_sz)
0215     .word   . - davinci_cpu_suspend
0216 ENDPROC(davinci_cpu_suspend_sz)