3b59430c9e107bec8753a7e9db8b229b9717b7a1
[openwrt/staging/jow.git] / target / linux / at91 / patches-5.10 / 203-ARM-at91-pm-avoid-push-and-pop-on-stack-while-memory.patch
1 From 892f6d2fb9c42d4ac451236639599f533c37b507 Mon Sep 17 00:00:00 2001
2 From: Claudiu Beznea <claudiu.beznea@microchip.com>
3 Date: Thu, 15 Apr 2021 13:49:53 +0300
4 Subject: [PATCH 203/247] ARM: at91: pm: avoid push and pop on stack while
5 memory is in self-refersh
6
7 For the previous AT91 RAM controller and self-refresh procedure this
8 had no side effects. However, for SAMA7G5 the self-refresh procedure
9 doesn't allow this anymore as the RAM controller ports are closed
10 before switching it to self-refresh. This commits prepares the code
11 for the following ones adding self-refresh and PM support for SAMA7G5.
12
13 Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
14 Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
15 Link: https://lore.kernel.org/r/20210415105010.569620-8-claudiu.beznea@microchip.com
16 ---
17 arch/arm/mach-at91/pm_suspend.S | 397 +++++++++++++++++---------------
18 1 file changed, 205 insertions(+), 192 deletions(-)
19
20 diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
21 index 3d20c9880fee..960ad29cce51 100644
22 --- a/arch/arm/mach-at91/pm_suspend.S
23 +++ b/arch/arm/mach-at91/pm_suspend.S
24 @@ -75,98 +75,147 @@ tmp3 .req r6
25
26 .arm
27
28 -/*
29 - * void at91_suspend_sram_fn(struct at91_pm_data*)
30 - * @input param:
31 - * @r0: base address of struct at91_pm_data
32 +/**
33 + * Enable self-refresh
34 + *
35 + * register usage:
36 + * @r1: memory type
37 + * @r2: base address of the sram controller
38 + * @r3: temporary
39 */
40 -/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
41 - .align 3
42 -ENTRY(at91_pm_suspend_in_sram)
43 - /* Save registers on stack */
44 - stmfd sp!, {r4 - r12, lr}
45 +.macro at91_sramc_self_refresh_ena
46 + ldr r1, .memtype
47 + ldr r2, .sramc_base
48
49 - /* Drain write buffer */
50 - mov tmp1, #0
51 - mcr p15, 0, tmp1, c7, c10, 4
52 + cmp r1, #AT91_MEMCTRL_MC
53 + bne sr_ena_ddrc_sf
54
55 - ldr tmp1, [r0, #PM_DATA_PMC]
56 - str tmp1, .pmc_base
57 - ldr tmp1, [r0, #PM_DATA_RAMC0]
58 - str tmp1, .sramc_base
59 - ldr tmp1, [r0, #PM_DATA_RAMC1]
60 - str tmp1, .sramc1_base
61 - ldr tmp1, [r0, #PM_DATA_MEMCTRL]
62 - str tmp1, .memtype
63 - ldr tmp1, [r0, #PM_DATA_MODE]
64 - str tmp1, .pm_mode
65 - ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
66 - str tmp1, .mckr_offset
67 - ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
68 - str tmp1, .pmc_version
69 - /* Both ldrne below are here to preload their address in the TLB */
70 - ldr tmp1, [r0, #PM_DATA_SHDWC]
71 - str tmp1, .shdwc
72 - cmp tmp1, #0
73 - ldrne tmp2, [tmp1, #0]
74 - ldr tmp1, [r0, #PM_DATA_SFRBU]
75 - str tmp1, .sfrbu
76 - cmp tmp1, #0
77 - ldrne tmp2, [tmp1, #0x10]
78 + /* Active SDRAM self-refresh mode */
79 + mov r3, #1
80 + str r3, [r2, #AT91_MC_SDRAMC_SRR]
81 + b sr_ena_exit
82
83 - /* Active the self-refresh mode */
84 - mov r0, #SRAMC_SELF_FRESH_ACTIVE
85 - bl at91_sramc_self_refresh
86 +sr_ena_ddrc_sf:
87 + cmp r1, #AT91_MEMCTRL_DDRSDR
88 + bne sr_ena_sdramc_sf
89
90 - ldr r0, .pm_mode
91 - cmp r0, #AT91_PM_STANDBY
92 - beq standby
93 - cmp r0, #AT91_PM_BACKUP
94 - beq backup_mode
95 + /*
96 + * DDR Memory controller
97 + */
98
99 - bl at91_ulp_mode
100 - b exit_suspend
101 + /* LPDDR1 --> force DDR2 mode during self-refresh */
102 + ldr r3, [r2, #AT91_DDRSDRC_MDR]
103 + str r3, .saved_sam9_mdr
104 + bic r3, r3, #~AT91_DDRSDRC_MD
105 + cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
106 + ldreq r3, [r2, #AT91_DDRSDRC_MDR]
107 + biceq r3, r3, #AT91_DDRSDRC_MD
108 + orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
109 + streq r3, [r2, #AT91_DDRSDRC_MDR]
110
111 -standby:
112 - /* Wait for interrupt */
113 - ldr pmc, .pmc_base
114 - at91_cpu_idle
115 - b exit_suspend
116 + /* Active DDRC self-refresh mode */
117 + ldr r3, [r2, #AT91_DDRSDRC_LPR]
118 + str r3, .saved_sam9_lpr
119 + bic r3, r3, #AT91_DDRSDRC_LPCB
120 + orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
121 + str r3, [r2, #AT91_DDRSDRC_LPR]
122
123 -backup_mode:
124 - bl at91_backup_mode
125 - b exit_suspend
126 + /* If using the 2nd ddr controller */
127 + ldr r2, .sramc1_base
128 + cmp r2, #0
129 + beq sr_ena_no_2nd_ddrc
130
131 -exit_suspend:
132 - /* Exit the self-refresh mode */
133 - mov r0, #SRAMC_SELF_FRESH_EXIT
134 - bl at91_sramc_self_refresh
135 + ldr r3, [r2, #AT91_DDRSDRC_MDR]
136 + str r3, .saved_sam9_mdr1
137 + bic r3, r3, #~AT91_DDRSDRC_MD
138 + cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
139 + ldreq r3, [r2, #AT91_DDRSDRC_MDR]
140 + biceq r3, r3, #AT91_DDRSDRC_MD
141 + orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
142 + streq r3, [r2, #AT91_DDRSDRC_MDR]
143
144 - /* Restore registers, and return */
145 - ldmfd sp!, {r4 - r12, pc}
146 -ENDPROC(at91_pm_suspend_in_sram)
147 + /* Active DDRC self-refresh mode */
148 + ldr r3, [r2, #AT91_DDRSDRC_LPR]
149 + str r3, .saved_sam9_lpr1
150 + bic r3, r3, #AT91_DDRSDRC_LPCB
151 + orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
152 + str r3, [r2, #AT91_DDRSDRC_LPR]
153
154 -ENTRY(at91_backup_mode)
155 - /* Switch the master clock source to slow clock. */
156 - ldr pmc, .pmc_base
157 - ldr tmp2, .mckr_offset
158 - ldr tmp1, [pmc, tmp2]
159 - bic tmp1, tmp1, #AT91_PMC_CSS
160 - str tmp1, [pmc, tmp2]
161 +sr_ena_no_2nd_ddrc:
162 + b sr_ena_exit
163
164 - wait_mckrdy
165 + /*
166 + * SDRAMC Memory controller
167 + */
168 +sr_ena_sdramc_sf:
169 + /* Active SDRAMC self-refresh mode */
170 + ldr r3, [r2, #AT91_SDRAMC_LPR]
171 + str r3, .saved_sam9_lpr
172 + bic r3, r3, #AT91_SDRAMC_LPCB
173 + orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
174 + str r3, [r2, #AT91_SDRAMC_LPR]
175
176 - /*BUMEN*/
177 - ldr r0, .sfrbu
178 - mov tmp1, #0x1
179 - str tmp1, [r0, #0x10]
180 + ldr r3, .saved_sam9_lpr
181 + str r3, [r2, #AT91_SDRAMC_LPR]
182
183 - /* Shutdown */
184 - ldr r0, .shdwc
185 - mov tmp1, #0xA5000000
186 - add tmp1, tmp1, #0x1
187 - str tmp1, [r0, #0]
188 -ENDPROC(at91_backup_mode)
189 +sr_ena_exit:
190 +.endm
191 +
192 +/**
193 + * Disable self-refresh
194 + *
195 + * register usage:
196 + * @r1: memory type
197 + * @r2: base address of the sram controller
198 + * @r3: temporary
199 + */
200 +.macro at91_sramc_self_refresh_dis
201 + ldr r1, .memtype
202 + ldr r2, .sramc_base
203 +
204 + cmp r1, #AT91_MEMCTRL_MC
205 + bne sr_dis_ddrc_exit_sf
206 +
207 + /*
208 + * at91rm9200 Memory controller
209 + */
210 +
211 + /*
212 + * For exiting the self-refresh mode, do nothing,
213 + * automatically exit the self-refresh mode.
214 + */
215 + b sr_dis_exit
216 +
217 +sr_dis_ddrc_exit_sf:
218 + cmp r1, #AT91_MEMCTRL_DDRSDR
219 + bne sdramc_exit_sf
220 +
221 + /* DDR Memory controller */
222 +
223 + /* Restore MDR in case of LPDDR1 */
224 + ldr r3, .saved_sam9_mdr
225 + str r3, [r2, #AT91_DDRSDRC_MDR]
226 + /* Restore LPR on AT91 with DDRAM */
227 + ldr r3, .saved_sam9_lpr
228 + str r3, [r2, #AT91_DDRSDRC_LPR]
229 +
230 + /* If using the 2nd ddr controller */
231 + ldr r2, .sramc1_base
232 + cmp r2, #0
233 + ldrne r3, .saved_sam9_mdr1
234 + strne r3, [r2, #AT91_DDRSDRC_MDR]
235 + ldrne r3, .saved_sam9_lpr1
236 + strne r3, [r2, #AT91_DDRSDRC_LPR]
237 +
238 + b sr_dis_exit
239 +
240 +sdramc_exit_sf:
241 + /* SDRAMC Memory controller */
242 + ldr r3, .saved_sam9_lpr
243 + str r3, [r2, #AT91_SDRAMC_LPR]
244 +
245 +sr_dis_exit:
246 +.endm
247
248 .macro at91_pm_ulp0_mode
249 ldr pmc, .pmc_base
250 @@ -503,7 +552,7 @@ ENDPROC(at91_backup_mode)
251 2:
252 .endm
253
254 -ENTRY(at91_ulp_mode)
255 +.macro at91_ulp_mode
256 ldr pmc, .pmc_base
257 ldr tmp2, .mckr_offset
258 ldr tmp3, .pm_mode
259 @@ -552,133 +601,97 @@ ulp_exit:
260
261 wait_mckrdy
262
263 - mov pc, lr
264 -ENDPROC(at91_ulp_mode)
265 -
266 -/*
267 - * void at91_sramc_self_refresh(unsigned int is_active)
268 - *
269 - * @input param:
270 - * @r0: 1 - active self-refresh mode
271 - * 0 - exit self-refresh mode
272 - * register usage:
273 - * @r1: memory type
274 - * @r2: base address of the sram controller
275 - */
276 -
277 -ENTRY(at91_sramc_self_refresh)
278 - ldr r1, .memtype
279 - ldr r2, .sramc_base
280 -
281 - cmp r1, #AT91_MEMCTRL_MC
282 - bne ddrc_sf
283 -
284 - /*
285 - * at91rm9200 Memory controller
286 - */
287 -
288 - /*
289 - * For exiting the self-refresh mode, do nothing,
290 - * automatically exit the self-refresh mode.
291 - */
292 - tst r0, #SRAMC_SELF_FRESH_ACTIVE
293 - beq exit_sramc_sf
294 -
295 - /* Active SDRAM self-refresh mode */
296 - mov r3, #1
297 - str r3, [r2, #AT91_MC_SDRAMC_SRR]
298 - b exit_sramc_sf
299 -
300 -ddrc_sf:
301 - cmp r1, #AT91_MEMCTRL_DDRSDR
302 - bne sdramc_sf
303 +.endm
304
305 - /*
306 - * DDR Memory controller
307 - */
308 - tst r0, #SRAMC_SELF_FRESH_ACTIVE
309 - beq ddrc_exit_sf
310 +.macro at91_backup_mode
311 + /* Switch the master clock source to slow clock. */
312 + ldr pmc, .pmc_base
313 + ldr tmp2, .mckr_offset
314 + ldr tmp1, [pmc, tmp2]
315 + bic tmp1, tmp1, #AT91_PMC_CSS
316 + str tmp1, [pmc, tmp2]
317
318 - /* LPDDR1 --> force DDR2 mode during self-refresh */
319 - ldr r3, [r2, #AT91_DDRSDRC_MDR]
320 - str r3, .saved_sam9_mdr
321 - bic r3, r3, #~AT91_DDRSDRC_MD
322 - cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
323 - ldreq r3, [r2, #AT91_DDRSDRC_MDR]
324 - biceq r3, r3, #AT91_DDRSDRC_MD
325 - orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
326 - streq r3, [r2, #AT91_DDRSDRC_MDR]
327 + wait_mckrdy
328
329 - /* Active DDRC self-refresh mode */
330 - ldr r3, [r2, #AT91_DDRSDRC_LPR]
331 - str r3, .saved_sam9_lpr
332 - bic r3, r3, #AT91_DDRSDRC_LPCB
333 - orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
334 - str r3, [r2, #AT91_DDRSDRC_LPR]
335 + /*BUMEN*/
336 + ldr r0, .sfrbu
337 + mov tmp1, #0x1
338 + str tmp1, [r0, #0x10]
339
340 - /* If using the 2nd ddr controller */
341 - ldr r2, .sramc1_base
342 - cmp r2, #0
343 - beq no_2nd_ddrc
344 + /* Shutdown */
345 + ldr r0, .shdwc
346 + mov tmp1, #0xA5000000
347 + add tmp1, tmp1, #0x1
348 + str tmp1, [r0, #0]
349 +.endm
350
351 - ldr r3, [r2, #AT91_DDRSDRC_MDR]
352 - str r3, .saved_sam9_mdr1
353 - bic r3, r3, #~AT91_DDRSDRC_MD
354 - cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
355 - ldreq r3, [r2, #AT91_DDRSDRC_MDR]
356 - biceq r3, r3, #AT91_DDRSDRC_MD
357 - orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
358 - streq r3, [r2, #AT91_DDRSDRC_MDR]
359 +/*
360 + * void at91_suspend_sram_fn(struct at91_pm_data*)
361 + * @input param:
362 + * @r0: base address of struct at91_pm_data
363 + */
364 +/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
365 + .align 3
366 +ENTRY(at91_pm_suspend_in_sram)
367 + /* Save registers on stack */
368 + stmfd sp!, {r4 - r12, lr}
369
370 - /* Active DDRC self-refresh mode */
371 - ldr r3, [r2, #AT91_DDRSDRC_LPR]
372 - str r3, .saved_sam9_lpr1
373 - bic r3, r3, #AT91_DDRSDRC_LPCB
374 - orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
375 - str r3, [r2, #AT91_DDRSDRC_LPR]
376 + /* Drain write buffer */
377 + mov tmp1, #0
378 + mcr p15, 0, tmp1, c7, c10, 4
379
380 -no_2nd_ddrc:
381 - b exit_sramc_sf
382 + ldr tmp1, [r0, #PM_DATA_PMC]
383 + str tmp1, .pmc_base
384 + ldr tmp1, [r0, #PM_DATA_RAMC0]
385 + str tmp1, .sramc_base
386 + ldr tmp1, [r0, #PM_DATA_RAMC1]
387 + str tmp1, .sramc1_base
388 + ldr tmp1, [r0, #PM_DATA_MEMCTRL]
389 + str tmp1, .memtype
390 + ldr tmp1, [r0, #PM_DATA_MODE]
391 + str tmp1, .pm_mode
392 + ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
393 + str tmp1, .mckr_offset
394 + ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
395 + str tmp1, .pmc_version
396 + /* Both ldrne below are here to preload their address in the TLB */
397 + ldr tmp1, [r0, #PM_DATA_SHDWC]
398 + str tmp1, .shdwc
399 + cmp tmp1, #0
400 + ldrne tmp2, [tmp1, #0]
401 + ldr tmp1, [r0, #PM_DATA_SFRBU]
402 + str tmp1, .sfrbu
403 + cmp tmp1, #0
404 + ldrne tmp2, [tmp1, #0x10]
405
406 -ddrc_exit_sf:
407 - /* Restore MDR in case of LPDDR1 */
408 - ldr r3, .saved_sam9_mdr
409 - str r3, [r2, #AT91_DDRSDRC_MDR]
410 - /* Restore LPR on AT91 with DDRAM */
411 - ldr r3, .saved_sam9_lpr
412 - str r3, [r2, #AT91_DDRSDRC_LPR]
413 + /* Active the self-refresh mode */
414 + at91_sramc_self_refresh_ena
415
416 - /* If using the 2nd ddr controller */
417 - ldr r2, .sramc1_base
418 - cmp r2, #0
419 - ldrne r3, .saved_sam9_mdr1
420 - strne r3, [r2, #AT91_DDRSDRC_MDR]
421 - ldrne r3, .saved_sam9_lpr1
422 - strne r3, [r2, #AT91_DDRSDRC_LPR]
423 + ldr r0, .pm_mode
424 + cmp r0, #AT91_PM_STANDBY
425 + beq standby
426 + cmp r0, #AT91_PM_BACKUP
427 + beq backup_mode
428
429 - b exit_sramc_sf
430 + at91_ulp_mode
431 + b exit_suspend
432
433 - /*
434 - * SDRAMC Memory controller
435 - */
436 -sdramc_sf:
437 - tst r0, #SRAMC_SELF_FRESH_ACTIVE
438 - beq sdramc_exit_sf
439 +standby:
440 + /* Wait for interrupt */
441 + ldr pmc, .pmc_base
442 + at91_cpu_idle
443 + b exit_suspend
444
445 - /* Active SDRAMC self-refresh mode */
446 - ldr r3, [r2, #AT91_SDRAMC_LPR]
447 - str r3, .saved_sam9_lpr
448 - bic r3, r3, #AT91_SDRAMC_LPCB
449 - orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
450 - str r3, [r2, #AT91_SDRAMC_LPR]
451 +backup_mode:
452 + at91_backup_mode
453
454 -sdramc_exit_sf:
455 - ldr r3, .saved_sam9_lpr
456 - str r3, [r2, #AT91_SDRAMC_LPR]
457 +exit_suspend:
458 + /* Exit the self-refresh mode */
459 + at91_sramc_self_refresh_dis
460
461 -exit_sramc_sf:
462 - mov pc, lr
463 -ENDPROC(at91_sramc_self_refresh)
464 + /* Restore registers, and return */
465 + ldmfd sp!, {r4 - r12, pc}
466 +ENDPROC(at91_pm_suspend_in_sram)
467
468 .pmc_base:
469 .word 0
470 --
471 2.32.0
472