1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * (C) Copyright 2009, Texas Instruments, Inc. http://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)
28 * Move DaVinci into deep sleep state
30 * Note: This code is copied to internal SRAM by PM code. When the DaVinci
31 * wakes up it continues execution at the point it went to sleep.
33 * r0: contains virtual base for DDR2 controller
34 * r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
35 * r2: contains PSC number for DDR2
36 * r3: contains virtual base DDR2 PLL controller
37 * r4: contains virtual address of the DEEPSLEEP register
39 ENTRY(davinci_cpu_suspend)
40 stmfd sp!, {r0-r12, lr} @ save registers on stack
48 * Switch DDR to self-refresh mode.
51 /* calculate SDRCR address */
52 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
53 bic ip, ip, #DDR2_SRPD_BIT
54 orr ip, ip, #DDR2_LPMODEN_BIT
55 str ip, [r0, #DDR2_SDRCR_OFFSET]
57 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
58 orr ip, ip, #DDR2_MCLKSTOPEN_BIT
59 str ip, [r0, #DDR2_SDRCR_OFFSET]
61 mov ip, #PHYRDY_CYCLES
65 /* Disable DDR2 LPSC */
68 bl davinci_ddr_psc_config
71 /* Disable clock to DDR PHY */
72 ldr ip, [r3, #PLLDIV1]
73 bic ip, ip, #PLLDIV_EN
74 str ip, [r3, #PLLDIV1]
76 /* Put the DDR PLL in bypass and power down */
78 bic ip, ip, #PLLCTL_PLLENSRC
79 bic ip, ip, #PLLCTL_PLLEN
82 /* Wait for PLL to switch to bypass */
83 mov ip, #PLL_BYPASS_CYCLES
87 /* Power down the PLL */
89 orr ip, ip, #PLLCTL_PLLPWRDN
92 /* Go to deep sleep */
94 orr ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
95 /* System goes to sleep beyond after this instruction */
98 /* Wake up from sleep */
100 /* Clear sleep enable */
102 bic ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
105 /* initialize the DDR PLL controller */
107 /* Put PLL in reset */
108 ldr ip, [r3, #PLLCTL]
109 bic ip, ip, #PLLCTL_PLLRST
110 str ip, [r3, #PLLCTL]
112 /* Clear PLL power down */
113 ldr ip, [r3, #PLLCTL]
114 bic ip, ip, #PLLCTL_PLLPWRDN
115 str ip, [r3, #PLLCTL]
117 mov ip, #PLL_RESET_CYCLES
121 /* Bring PLL out of reset */
122 ldr ip, [r3, #PLLCTL]
123 orr ip, ip, #PLLCTL_PLLRST
124 str ip, [r3, #PLLCTL]
126 /* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
127 mov ip, #PLL_LOCK_CYCLES
131 /* Remove PLL from bypass mode */
132 ldr ip, [r3, #PLLCTL]
133 bic ip, ip, #PLLCTL_PLLENSRC
134 orr ip, ip, #PLLCTL_PLLEN
135 str ip, [r3, #PLLCTL]
137 /* Start 2x clock to DDR2 */
139 ldr ip, [r3, #PLLDIV1]
140 orr ip, ip, #PLLDIV_EN
141 str ip, [r3, #PLLDIV1]
145 /* Enable DDR2 LPSC */
148 bl davinci_ddr_psc_config
151 /* clear MCLKSTOPEN */
153 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
154 bic ip, ip, #DDR2_MCLKSTOPEN_BIT
155 str ip, [r0, #DDR2_SDRCR_OFFSET]
157 ldr ip, [r0, #DDR2_SDRCR_OFFSET]
158 bic ip, ip, #DDR2_LPMODEN_BIT
159 str ip, [r0, #DDR2_SDRCR_OFFSET]
161 /* Restore registers and return */
162 ldmfd sp!, {r0-r12, pc}
164 ENDPROC(davinci_cpu_suspend)
167 * Disables or Enables DDR2 LPSC
169 * r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
170 * r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
171 * r2: contains PSC number for DDR2
173 ENTRY(davinci_ddr_psc_config)
174 /* Set next state in mdctl for DDR2 */
176 add r6, r6, r2, lsl #2
178 bic ip, ip, #MDSTAT_STATE_MASK
182 /* Enable the Power Domain Transition Command */
187 /* Check for Transition Complete (PTSTAT) */
189 ldr ip, [r1, #PTSTAT]
194 /* Check for DDR2 clock disable completion; */
196 add r6, r6, r2, lsl #2
199 and ip, ip, #MDSTAT_STATE_MASK
201 bne ddr2clk_stop_done
204 ENDPROC(davinci_ddr_psc_config)
208 .word v6_flush_kern_cache_all
210 .word arm926_flush_kern_cache_all
213 ENTRY(davinci_cpu_suspend_sz)
214 .word . - davinci_cpu_suspend
215 ENDPROC(davinci_cpu_suspend_sz)