Commit | Line | Data |
---|---|---|
45051539 | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
efc1bb8a SN |
2 | /* |
3 | * (C) Copyright 2009, Texas Instruments, Inc. http://www.ti.com/ | |
efc1bb8a SN |
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> | |
3acf731c AB |
11 | #include "psc.h" |
12 | #include "ddr2.h" | |
efc1bb8a SN |
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 | |
d64b212e | 27 | .arch armv5te |
efc1bb8a SN |
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 | ||
6ebbf2ce | 204 | ret lr |
efc1bb8a SN |
205 | ENDPROC(davinci_ddr_psc_config) |
206 | ||
207 | CACHE_FLUSH: | |
897a6a1a LW |
208 | #ifdef CONFIG_CPU_V6 |
209 | .word v6_flush_kern_cache_all | |
210 | #else | |
211 | .word arm926_flush_kern_cache_all | |
212 | #endif | |
efc1bb8a SN |
213 | |
214 | ENTRY(davinci_cpu_suspend_sz) | |
215 | .word . - davinci_cpu_suspend | |
216 | ENDPROC(davinci_cpu_suspend_sz) |