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 --- a/arch/arm/mach-at91/pm_suspend.S
21 +++ b/arch/arm/mach-at91/pm_suspend.S
22 @@ -75,98 +75,147 @@ tmp3 .req r6
27 - * void at91_suspend_sram_fn(struct at91_pm_data*)
29 - * @r0: base address of struct at91_pm_data
31 + * Enable self-refresh
35 + * @r2: base address of the sram controller
38 -/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
40 -ENTRY(at91_pm_suspend_in_sram)
41 - /* Save registers on stack */
42 - stmfd sp!, {r4 - r12, lr}
43 +.macro at91_sramc_self_refresh_ena
47 - /* Drain write buffer */
49 - mcr p15, 0, tmp1, c7, c10, 4
50 + cmp r1, #AT91_MEMCTRL_MC
53 - ldr tmp1, [r0, #PM_DATA_PMC]
55 - ldr tmp1, [r0, #PM_DATA_RAMC0]
56 - str tmp1, .sramc_base
57 - ldr tmp1, [r0, #PM_DATA_RAMC1]
58 - str tmp1, .sramc1_base
59 - ldr tmp1, [r0, #PM_DATA_MEMCTRL]
61 - ldr tmp1, [r0, #PM_DATA_MODE]
63 - ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
64 - str tmp1, .mckr_offset
65 - ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
66 - str tmp1, .pmc_version
67 - /* Both ldrne below are here to preload their address in the TLB */
68 - ldr tmp1, [r0, #PM_DATA_SHDWC]
71 - ldrne tmp2, [tmp1, #0]
72 - ldr tmp1, [r0, #PM_DATA_SFRBU]
75 - ldrne tmp2, [tmp1, #0x10]
76 + /* Active SDRAM self-refresh mode */
78 + str r3, [r2, #AT91_MC_SDRAMC_SRR]
81 - /* Active the self-refresh mode */
82 - mov r0, #SRAMC_SELF_FRESH_ACTIVE
83 - bl at91_sramc_self_refresh
85 + cmp r1, #AT91_MEMCTRL_DDRSDR
86 + bne sr_ena_sdramc_sf
89 - cmp r0, #AT91_PM_STANDBY
91 - cmp r0, #AT91_PM_BACKUP
94 + * DDR Memory controller
99 + /* LPDDR1 --> force DDR2 mode during self-refresh */
100 + ldr r3, [r2, #AT91_DDRSDRC_MDR]
101 + str r3, .saved_sam9_mdr
102 + bic r3, r3, #~AT91_DDRSDRC_MD
103 + cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
104 + ldreq r3, [r2, #AT91_DDRSDRC_MDR]
105 + biceq r3, r3, #AT91_DDRSDRC_MD
106 + orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
107 + streq r3, [r2, #AT91_DDRSDRC_MDR]
110 - /* Wait for interrupt */
114 + /* Active DDRC self-refresh mode */
115 + ldr r3, [r2, #AT91_DDRSDRC_LPR]
116 + str r3, .saved_sam9_lpr
117 + bic r3, r3, #AT91_DDRSDRC_LPCB
118 + orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
119 + str r3, [r2, #AT91_DDRSDRC_LPR]
122 - bl at91_backup_mode
124 + /* If using the 2nd ddr controller */
125 + ldr r2, .sramc1_base
127 + beq sr_ena_no_2nd_ddrc
130 - /* Exit the self-refresh mode */
131 - mov r0, #SRAMC_SELF_FRESH_EXIT
132 - bl at91_sramc_self_refresh
133 + ldr r3, [r2, #AT91_DDRSDRC_MDR]
134 + str r3, .saved_sam9_mdr1
135 + bic r3, r3, #~AT91_DDRSDRC_MD
136 + cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
137 + ldreq r3, [r2, #AT91_DDRSDRC_MDR]
138 + biceq r3, r3, #AT91_DDRSDRC_MD
139 + orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
140 + streq r3, [r2, #AT91_DDRSDRC_MDR]
142 - /* Restore registers, and return */
143 - ldmfd sp!, {r4 - r12, pc}
144 -ENDPROC(at91_pm_suspend_in_sram)
145 + /* Active DDRC self-refresh mode */
146 + ldr r3, [r2, #AT91_DDRSDRC_LPR]
147 + str r3, .saved_sam9_lpr1
148 + bic r3, r3, #AT91_DDRSDRC_LPCB
149 + orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
150 + str r3, [r2, #AT91_DDRSDRC_LPR]
152 -ENTRY(at91_backup_mode)
153 - /* Switch the master clock source to slow clock. */
155 - ldr tmp2, .mckr_offset
156 - ldr tmp1, [pmc, tmp2]
157 - bic tmp1, tmp1, #AT91_PMC_CSS
158 - str tmp1, [pmc, tmp2]
164 + * SDRAMC Memory controller
167 + /* Active SDRAMC self-refresh mode */
168 + ldr r3, [r2, #AT91_SDRAMC_LPR]
169 + str r3, .saved_sam9_lpr
170 + bic r3, r3, #AT91_SDRAMC_LPCB
171 + orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
172 + str r3, [r2, #AT91_SDRAMC_LPR]
177 - str tmp1, [r0, #0x10]
178 + ldr r3, .saved_sam9_lpr
179 + str r3, [r2, #AT91_SDRAMC_LPR]
183 - mov tmp1, #0xA5000000
184 - add tmp1, tmp1, #0x1
186 -ENDPROC(at91_backup_mode)
191 + * Disable self-refresh
195 + * @r2: base address of the sram controller
198 +.macro at91_sramc_self_refresh_dis
200 + ldr r2, .sramc_base
202 + cmp r1, #AT91_MEMCTRL_MC
203 + bne sr_dis_ddrc_exit_sf
206 + * at91rm9200 Memory controller
210 + * For exiting the self-refresh mode, do nothing,
211 + * automatically exit the self-refresh mode.
215 +sr_dis_ddrc_exit_sf:
216 + cmp r1, #AT91_MEMCTRL_DDRSDR
219 + /* DDR Memory controller */
221 + /* Restore MDR in case of LPDDR1 */
222 + ldr r3, .saved_sam9_mdr
223 + str r3, [r2, #AT91_DDRSDRC_MDR]
224 + /* Restore LPR on AT91 with DDRAM */
225 + ldr r3, .saved_sam9_lpr
226 + str r3, [r2, #AT91_DDRSDRC_LPR]
228 + /* If using the 2nd ddr controller */
229 + ldr r2, .sramc1_base
231 + ldrne r3, .saved_sam9_mdr1
232 + strne r3, [r2, #AT91_DDRSDRC_MDR]
233 + ldrne r3, .saved_sam9_lpr1
234 + strne r3, [r2, #AT91_DDRSDRC_LPR]
239 + /* SDRAMC Memory controller */
240 + ldr r3, .saved_sam9_lpr
241 + str r3, [r2, #AT91_SDRAMC_LPR]
246 .macro at91_pm_ulp0_mode
248 @@ -503,7 +552,7 @@ ENDPROC(at91_backup_mode)
252 -ENTRY(at91_ulp_mode)
253 +.macro at91_ulp_mode
255 ldr tmp2, .mckr_offset
257 @@ -552,133 +601,97 @@ ulp_exit:
262 -ENDPROC(at91_ulp_mode)
265 - * void at91_sramc_self_refresh(unsigned int is_active)
268 - * @r0: 1 - active self-refresh mode
269 - * 0 - exit self-refresh mode
272 - * @r2: base address of the sram controller
275 -ENTRY(at91_sramc_self_refresh)
277 - ldr r2, .sramc_base
279 - cmp r1, #AT91_MEMCTRL_MC
283 - * at91rm9200 Memory controller
287 - * For exiting the self-refresh mode, do nothing,
288 - * automatically exit the self-refresh mode.
290 - tst r0, #SRAMC_SELF_FRESH_ACTIVE
293 - /* Active SDRAM self-refresh mode */
295 - str r3, [r2, #AT91_MC_SDRAMC_SRR]
299 - cmp r1, #AT91_MEMCTRL_DDRSDR
304 - * DDR Memory controller
306 - tst r0, #SRAMC_SELF_FRESH_ACTIVE
308 +.macro at91_backup_mode
309 + /* Switch the master clock source to slow clock. */
311 + ldr tmp2, .mckr_offset
312 + ldr tmp1, [pmc, tmp2]
313 + bic tmp1, tmp1, #AT91_PMC_CSS
314 + str tmp1, [pmc, tmp2]
316 - /* LPDDR1 --> force DDR2 mode during self-refresh */
317 - ldr r3, [r2, #AT91_DDRSDRC_MDR]
318 - str r3, .saved_sam9_mdr
319 - bic r3, r3, #~AT91_DDRSDRC_MD
320 - cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
321 - ldreq r3, [r2, #AT91_DDRSDRC_MDR]
322 - biceq r3, r3, #AT91_DDRSDRC_MD
323 - orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
324 - streq r3, [r2, #AT91_DDRSDRC_MDR]
327 - /* Active DDRC self-refresh mode */
328 - ldr r3, [r2, #AT91_DDRSDRC_LPR]
329 - str r3, .saved_sam9_lpr
330 - bic r3, r3, #AT91_DDRSDRC_LPCB
331 - orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
332 - str r3, [r2, #AT91_DDRSDRC_LPR]
336 + str tmp1, [r0, #0x10]
338 - /* If using the 2nd ddr controller */
339 - ldr r2, .sramc1_base
344 + mov tmp1, #0xA5000000
345 + add tmp1, tmp1, #0x1
349 - ldr r3, [r2, #AT91_DDRSDRC_MDR]
350 - str r3, .saved_sam9_mdr1
351 - bic r3, r3, #~AT91_DDRSDRC_MD
352 - cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR
353 - ldreq r3, [r2, #AT91_DDRSDRC_MDR]
354 - biceq r3, r3, #AT91_DDRSDRC_MD
355 - orreq r3, r3, #AT91_DDRSDRC_MD_DDR2
356 - streq r3, [r2, #AT91_DDRSDRC_MDR]
358 + * void at91_suspend_sram_fn(struct at91_pm_data*)
360 + * @r0: base address of struct at91_pm_data
362 +/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
364 +ENTRY(at91_pm_suspend_in_sram)
365 + /* Save registers on stack */
366 + stmfd sp!, {r4 - r12, lr}
368 - /* Active DDRC self-refresh mode */
369 - ldr r3, [r2, #AT91_DDRSDRC_LPR]
370 - str r3, .saved_sam9_lpr1
371 - bic r3, r3, #AT91_DDRSDRC_LPCB
372 - orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
373 - str r3, [r2, #AT91_DDRSDRC_LPR]
374 + /* Drain write buffer */
376 + mcr p15, 0, tmp1, c7, c10, 4
380 + ldr tmp1, [r0, #PM_DATA_PMC]
381 + str tmp1, .pmc_base
382 + ldr tmp1, [r0, #PM_DATA_RAMC0]
383 + str tmp1, .sramc_base
384 + ldr tmp1, [r0, #PM_DATA_RAMC1]
385 + str tmp1, .sramc1_base
386 + ldr tmp1, [r0, #PM_DATA_MEMCTRL]
388 + ldr tmp1, [r0, #PM_DATA_MODE]
390 + ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET]
391 + str tmp1, .mckr_offset
392 + ldr tmp1, [r0, #PM_DATA_PMC_VERSION]
393 + str tmp1, .pmc_version
394 + /* Both ldrne below are here to preload their address in the TLB */
395 + ldr tmp1, [r0, #PM_DATA_SHDWC]
398 + ldrne tmp2, [tmp1, #0]
399 + ldr tmp1, [r0, #PM_DATA_SFRBU]
402 + ldrne tmp2, [tmp1, #0x10]
405 - /* Restore MDR in case of LPDDR1 */
406 - ldr r3, .saved_sam9_mdr
407 - str r3, [r2, #AT91_DDRSDRC_MDR]
408 - /* Restore LPR on AT91 with DDRAM */
409 - ldr r3, .saved_sam9_lpr
410 - str r3, [r2, #AT91_DDRSDRC_LPR]
411 + /* Active the self-refresh mode */
412 + at91_sramc_self_refresh_ena
414 - /* If using the 2nd ddr controller */
415 - ldr r2, .sramc1_base
417 - ldrne r3, .saved_sam9_mdr1
418 - strne r3, [r2, #AT91_DDRSDRC_MDR]
419 - ldrne r3, .saved_sam9_lpr1
420 - strne r3, [r2, #AT91_DDRSDRC_LPR]
422 + cmp r0, #AT91_PM_STANDBY
424 + cmp r0, #AT91_PM_BACKUP
432 - * SDRAMC Memory controller
435 - tst r0, #SRAMC_SELF_FRESH_ACTIVE
438 + /* Wait for interrupt */
443 - /* Active SDRAMC self-refresh mode */
444 - ldr r3, [r2, #AT91_SDRAMC_LPR]
445 - str r3, .saved_sam9_lpr
446 - bic r3, r3, #AT91_SDRAMC_LPCB
447 - orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH
448 - str r3, [r2, #AT91_SDRAMC_LPR]
453 - ldr r3, .saved_sam9_lpr
454 - str r3, [r2, #AT91_SDRAMC_LPR]
456 + /* Exit the self-refresh mode */
457 + at91_sramc_self_refresh_dis
461 -ENDPROC(at91_sramc_self_refresh)
462 + /* Restore registers, and return */
463 + ldmfd sp!, {r4 - r12, pc}
464 +ENDPROC(at91_pm_suspend_in_sram)