1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * (C) Copyright 2009, Texas Instruments, Inc. https://www.ti.com/
6 /* replicated define because linux/bitops.h cannot be included in assembly */
7 #define BIT(nr) (1 << (nr))
9 #include <linux/linkage.h>
10 #include <asm/assembler.h>
16 /* Arbitrary, hardware currently does not update PHYRDY correctly */
17 #define PHYRDY_CYCLES 0x1000
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)
24 #define DEEPSLEEP_SLEEPENABLE_BIT BIT(31)
29 * Move DaVinci into deep sleep state
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.
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
40 ENTRY(davinci_cpu_suspend)
41 stmfd sp!, {r0-r12, lr} @ save registers on stack
49 * Switch DDR to self-refresh mode.
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]
58 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
59 orr ip, ip, #DDR2_MCLKSTOPEN_BIT
60 str ip, [r0, #DDR2_SDRCR_OFFSET]
62 mov ip, #PHYRDY_CYCLES
66 /* Disable DDR2 LPSC */
69 bl davinci_ddr_psc_config
72 /* Disable clock to DDR PHY */
73 ldr ip, [r3, #PLLDIV1]
74 bic ip, ip, #PLLDIV_EN
75 str ip, [r3, #PLLDIV1]
77 /* Put the DDR PLL in bypass and power down */
79 bic ip, ip, #PLLCTL_PLLENSRC
80 bic ip, ip, #PLLCTL_PLLEN
83 /* Wait for PLL to switch to bypass */
84 mov ip, #PLL_BYPASS_CYCLES
88 /* Power down the PLL */
90 orr ip, ip, #PLLCTL_PLLPWRDN
93 /* Go to deep sleep */
95 orr ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
96 /* System goes to sleep beyond after this instruction */
99 /* Wake up from sleep */
101 /* Clear sleep enable */
103 bic ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
106 /* initialize the DDR PLL controller */
108 /* Put PLL in reset */
109 ldr ip, [r3, #PLLCTL]
110 bic ip, ip, #PLLCTL_PLLRST
111 str ip, [r3, #PLLCTL]
113 /* Clear PLL power down */
114 ldr ip, [r3, #PLLCTL]
115 bic ip, ip, #PLLCTL_PLLPWRDN
116 str ip, [r3, #PLLCTL]
118 mov ip, #PLL_RESET_CYCLES
122 /* Bring PLL out of reset */
123 ldr ip, [r3, #PLLCTL]
124 orr ip, ip, #PLLCTL_PLLRST
125 str ip, [r3, #PLLCTL]
127 /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
128 mov ip, #PLL_LOCK_CYCLES
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]
138 /* Start 2x clock to DDR2 */
140 ldr ip, [r3, #PLLDIV1]
141 orr ip, ip, #PLLDIV_EN
142 str ip, [r3, #PLLDIV1]
146 /* Enable DDR2 LPSC */
149 bl davinci_ddr_psc_config
152 /* clear MCLKSTOPEN */
154 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
155 bic ip, ip, #DDR2_MCLKSTOPEN_BIT
156 str ip, [r0, #DDR2_SDRCR_OFFSET]
158 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
159 bic ip, ip, #DDR2_LPMODEN_BIT
160 str ip, [r0, #DDR2_SDRCR_OFFSET]
162 /* Restore registers and return */
163 ldmfd sp!, {r0-r12, pc}
165 ENDPROC(davinci_cpu_suspend)
168 * Disables or Enables DDR2 LPSC
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
174 ENTRY(davinci_ddr_psc_config)
175 /* Set next state in mdctl for DDR2 */
177 add r6, r6, r2, lsl #2
179 bic ip, ip, #MDSTAT_STATE_MASK
183 /* Enable the Power Domain Transition Command */
188 /* Check for Transition Complete (PTSTAT) */
190 ldr ip, [r1, #PTSTAT]
195 /* Check for DDR2 clock disable completion; */
197 add r6, r6, r2, lsl #2
200 and ip, ip, #MDSTAT_STATE_MASK
202 bne ddr2clk_stop_done
205 ENDPROC(davinci_ddr_psc_config)
209 .word v6_flush_kern_cache_all
211 .word arm926_flush_kern_cache_all
214 ENTRY(davinci_cpu_suspend_sz)
215 .word . - davinci_cpu_suspend
216 ENDPROC(davinci_cpu_suspend_sz)