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
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.
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
17 arch/arm/mach-at91/pm_suspend.S | 397 +++++++++++++++++---------------
18 1 file changed, 205 insertions(+), 192 deletions(-)
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
29 - * void at91_suspend_sram_fn(struct at91_pm_data*)
31 - * @r0: base address of struct at91_pm_data
33 + * Enable self-refresh
37 + * @r2: base address of the sram controller
40 -/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
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
49 - /* Drain write buffer */
51 - mcr p15, 0, tmp1, c7, c10, 4
52 + cmp r1, #AT91_MEMCTRL_MC
55 - ldr tmp1, [r0, #PM_DATA_PMC]
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]
63 - ldr tmp1, [r0, #PM_DATA_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]
73 - ldrne tmp2, [tmp1, #0]
74 - ldr tmp1, [r0, #PM_DATA_SFRBU]
77 - ldrne tmp2, [tmp1, #0x10]
78 + /* Active SDRAM self-refresh mode */
80 + str r3, [r2, #AT91_MC_SDRAMC_SRR]
83 - /* Active the self-refresh mode */
84 - mov r0, #SRAMC_SELF_FRESH_ACTIVE
85 - bl at91_sramc_self_refresh
87 + cmp r1, #AT91_MEMCTRL_DDRSDR
88 + bne sr_ena_sdramc_sf
91 - cmp r0, #AT91_PM_STANDBY
93 - cmp r0, #AT91_PM_BACKUP
96 + * DDR Memory controller
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]
112 - /* Wait for interrupt */
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]
124 - bl at91_backup_mode
126 + /* If using the 2nd ddr controller */
127 + ldr r2, .sramc1_base
129 + beq sr_ena_no_2nd_ddrc
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]
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]
154 -ENTRY(at91_backup_mode)
155 - /* Switch the master clock source to slow clock. */
157 - ldr tmp2, .mckr_offset
158 - ldr tmp1, [pmc, tmp2]
159 - bic tmp1, tmp1, #AT91_PMC_CSS
160 - str tmp1, [pmc, tmp2]
166 + * SDRAMC Memory controller
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]
179 - str tmp1, [r0, #0x10]
180 + ldr r3, .saved_sam9_lpr
181 + str r3, [r2, #AT91_SDRAMC_LPR]
185 - mov tmp1, #0xA5000000
186 - add tmp1, tmp1, #0x1
188 -ENDPROC(at91_backup_mode)
193 + * Disable self-refresh
197 + * @r2: base address of the sram controller
200 +.macro at91_sramc_self_refresh_dis
202 + ldr r2, .sramc_base
204 + cmp r1, #AT91_MEMCTRL_MC
205 + bne sr_dis_ddrc_exit_sf
208 + * at91rm9200 Memory controller
212 + * For exiting the self-refresh mode, do nothing,
213 + * automatically exit the self-refresh mode.
217 +sr_dis_ddrc_exit_sf:
218 + cmp r1, #AT91_MEMCTRL_DDRSDR
221 + /* DDR Memory controller */
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]
230 + /* If using the 2nd ddr controller */
231 + ldr r2, .sramc1_base
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]
241 + /* SDRAMC Memory controller */
242 + ldr r3, .saved_sam9_lpr
243 + str r3, [r2, #AT91_SDRAMC_LPR]
248 .macro at91_pm_ulp0_mode
250 @@ -503,7 +552,7 @@ ENDPROC(at91_backup_mode)
254 -ENTRY(at91_ulp_mode)
255 +.macro at91_ulp_mode
257 ldr tmp2, .mckr_offset
259 @@ -552,133 +601,97 @@ ulp_exit:
264 -ENDPROC(at91_ulp_mode)
267 - * void at91_sramc_self_refresh(unsigned int is_active)
270 - * @r0: 1 - active self-refresh mode
271 - * 0 - exit self-refresh mode
274 - * @r2: base address of the sram controller
277 -ENTRY(at91_sramc_self_refresh)
279 - ldr r2, .sramc_base
281 - cmp r1, #AT91_MEMCTRL_MC
285 - * at91rm9200 Memory controller
289 - * For exiting the self-refresh mode, do nothing,
290 - * automatically exit the self-refresh mode.
292 - tst r0, #SRAMC_SELF_FRESH_ACTIVE
295 - /* Active SDRAM self-refresh mode */
297 - str r3, [r2, #AT91_MC_SDRAMC_SRR]
301 - cmp r1, #AT91_MEMCTRL_DDRSDR
306 - * DDR Memory controller
308 - tst r0, #SRAMC_SELF_FRESH_ACTIVE
310 +.macro at91_backup_mode
311 + /* Switch the master clock source to slow clock. */
313 + ldr tmp2, .mckr_offset
314 + ldr tmp1, [pmc, tmp2]
315 + bic tmp1, tmp1, #AT91_PMC_CSS
316 + str tmp1, [pmc, tmp2]
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]
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]
338 + str tmp1, [r0, #0x10]
340 - /* If using the 2nd ddr controller */
341 - ldr r2, .sramc1_base
346 + mov tmp1, #0xA5000000
347 + add tmp1, tmp1, #0x1
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]
360 + * void at91_suspend_sram_fn(struct at91_pm_data*)
362 + * @r0: base address of struct at91_pm_data
364 +/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
366 +ENTRY(at91_pm_suspend_in_sram)
367 + /* Save registers on stack */
368 + stmfd sp!, {r4 - r12, lr}
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 */
378 + mcr p15, 0, tmp1, c7, c10, 4
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]
390 + ldr tmp1, [r0, #PM_DATA_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]
400 + ldrne tmp2, [tmp1, #0]
401 + ldr tmp1, [r0, #PM_DATA_SFRBU]
404 + ldrne tmp2, [tmp1, #0x10]
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
416 - /* If using the 2nd ddr controller */
417 - ldr r2, .sramc1_base
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]
424 + cmp r0, #AT91_PM_STANDBY
426 + cmp r0, #AT91_PM_BACKUP
434 - * SDRAMC Memory controller
437 - tst r0, #SRAMC_SELF_FRESH_ACTIVE
440 + /* Wait for interrupt */
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]
455 - ldr r3, .saved_sam9_lpr
456 - str r3, [r2, #AT91_SDRAMC_LPR]
458 + /* Exit the self-refresh mode */
459 + at91_sramc_self_refresh_dis
463 -ENDPROC(at91_sramc_self_refresh)
464 + /* Restore registers, and return */
465 + ldmfd sp!, {r4 - r12, pc}
466 +ENDPROC(at91_pm_suspend_in_sram)