diff options
Diffstat (limited to 'target/linux/at91/patches-5.10/203-ARM-at91-pm-avoid-push-and-pop-on-stack-while-memory.patch')
-rw-r--r-- | target/linux/at91/patches-5.10/203-ARM-at91-pm-avoid-push-and-pop-on-stack-while-memory.patch | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/target/linux/at91/patches-5.10/203-ARM-at91-pm-avoid-push-and-pop-on-stack-while-memory.patch b/target/linux/at91/patches-5.10/203-ARM-at91-pm-avoid-push-and-pop-on-stack-while-memory.patch new file mode 100644 index 0000000000..3b59430c9e --- /dev/null +++ b/target/linux/at91/patches-5.10/203-ARM-at91-pm-avoid-push-and-pop-on-stack-while-memory.patch @@ -0,0 +1,472 @@ +From 892f6d2fb9c42d4ac451236639599f533c37b507 Mon Sep 17 00:00:00 2001 +From: Claudiu Beznea <claudiu.beznea@microchip.com> +Date: Thu, 15 Apr 2021 13:49:53 +0300 +Subject: [PATCH 203/247] ARM: at91: pm: avoid push and pop on stack while + memory is in self-refersh + +For the previous AT91 RAM controller and self-refresh procedure this +had no side effects. However, for SAMA7G5 the self-refresh procedure +doesn't allow this anymore as the RAM controller ports are closed +before switching it to self-refresh. This commits prepares the code +for the following ones adding self-refresh and PM support for SAMA7G5. + +Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com> +Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com> +Link: https://lore.kernel.org/r/20210415105010.569620-8-claudiu.beznea@microchip.com +--- + arch/arm/mach-at91/pm_suspend.S | 397 +++++++++++++++++--------------- + 1 file changed, 205 insertions(+), 192 deletions(-) + +diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S +index 3d20c9880fee..960ad29cce51 100644 +--- a/arch/arm/mach-at91/pm_suspend.S ++++ b/arch/arm/mach-at91/pm_suspend.S +@@ -75,98 +75,147 @@ tmp3 .req r6 + + .arm + +-/* +- * void at91_suspend_sram_fn(struct at91_pm_data*) +- * @input param: +- * @r0: base address of struct at91_pm_data ++/** ++ * Enable self-refresh ++ * ++ * register usage: ++ * @r1: memory type ++ * @r2: base address of the sram controller ++ * @r3: temporary + */ +-/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */ +- .align 3 +-ENTRY(at91_pm_suspend_in_sram) +- /* Save registers on stack */ +- stmfd sp!, {r4 - r12, lr} ++.macro at91_sramc_self_refresh_ena ++ ldr r1, .memtype ++ ldr r2, .sramc_base + +- /* Drain write buffer */ +- mov tmp1, #0 +- mcr p15, 0, tmp1, c7, c10, 4 ++ cmp r1, #AT91_MEMCTRL_MC ++ bne sr_ena_ddrc_sf + +- ldr tmp1, [r0, #PM_DATA_PMC] +- str tmp1, .pmc_base +- ldr tmp1, [r0, #PM_DATA_RAMC0] +- str tmp1, .sramc_base +- ldr tmp1, [r0, #PM_DATA_RAMC1] +- str tmp1, .sramc1_base +- ldr tmp1, [r0, #PM_DATA_MEMCTRL] +- str tmp1, .memtype +- ldr tmp1, [r0, #PM_DATA_MODE] +- str tmp1, .pm_mode +- ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET] +- str tmp1, .mckr_offset +- ldr tmp1, [r0, #PM_DATA_PMC_VERSION] +- str tmp1, .pmc_version +- /* Both ldrne below are here to preload their address in the TLB */ +- ldr tmp1, [r0, #PM_DATA_SHDWC] +- str tmp1, .shdwc +- cmp tmp1, #0 +- ldrne tmp2, [tmp1, #0] +- ldr tmp1, [r0, #PM_DATA_SFRBU] +- str tmp1, .sfrbu +- cmp tmp1, #0 +- ldrne tmp2, [tmp1, #0x10] ++ /* Active SDRAM self-refresh mode */ ++ mov r3, #1 ++ str r3, [r2, #AT91_MC_SDRAMC_SRR] ++ b sr_ena_exit + +- /* Active the self-refresh mode */ +- mov r0, #SRAMC_SELF_FRESH_ACTIVE +- bl at91_sramc_self_refresh ++sr_ena_ddrc_sf: ++ cmp r1, #AT91_MEMCTRL_DDRSDR ++ bne sr_ena_sdramc_sf + +- ldr r0, .pm_mode +- cmp r0, #AT91_PM_STANDBY +- beq standby +- cmp r0, #AT91_PM_BACKUP +- beq backup_mode ++ /* ++ * DDR Memory controller ++ */ + +- bl at91_ulp_mode +- b exit_suspend ++ /* LPDDR1 --> force DDR2 mode during self-refresh */ ++ ldr r3, [r2, #AT91_DDRSDRC_MDR] ++ str r3, .saved_sam9_mdr ++ bic r3, r3, #~AT91_DDRSDRC_MD ++ cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR ++ ldreq r3, [r2, #AT91_DDRSDRC_MDR] ++ biceq r3, r3, #AT91_DDRSDRC_MD ++ orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 ++ streq r3, [r2, #AT91_DDRSDRC_MDR] + +-standby: +- /* Wait for interrupt */ +- ldr pmc, .pmc_base +- at91_cpu_idle +- b exit_suspend ++ /* Active DDRC self-refresh mode */ ++ ldr r3, [r2, #AT91_DDRSDRC_LPR] ++ str r3, .saved_sam9_lpr ++ bic r3, r3, #AT91_DDRSDRC_LPCB ++ orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH ++ str r3, [r2, #AT91_DDRSDRC_LPR] + +-backup_mode: +- bl at91_backup_mode +- b exit_suspend ++ /* If using the 2nd ddr controller */ ++ ldr r2, .sramc1_base ++ cmp r2, #0 ++ beq sr_ena_no_2nd_ddrc + +-exit_suspend: +- /* Exit the self-refresh mode */ +- mov r0, #SRAMC_SELF_FRESH_EXIT +- bl at91_sramc_self_refresh ++ ldr r3, [r2, #AT91_DDRSDRC_MDR] ++ str r3, .saved_sam9_mdr1 ++ bic r3, r3, #~AT91_DDRSDRC_MD ++ cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR ++ ldreq r3, [r2, #AT91_DDRSDRC_MDR] ++ biceq r3, r3, #AT91_DDRSDRC_MD ++ orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 ++ streq r3, [r2, #AT91_DDRSDRC_MDR] + +- /* Restore registers, and return */ +- ldmfd sp!, {r4 - r12, pc} +-ENDPROC(at91_pm_suspend_in_sram) ++ /* Active DDRC self-refresh mode */ ++ ldr r3, [r2, #AT91_DDRSDRC_LPR] ++ str r3, .saved_sam9_lpr1 ++ bic r3, r3, #AT91_DDRSDRC_LPCB ++ orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH ++ str r3, [r2, #AT91_DDRSDRC_LPR] + +-ENTRY(at91_backup_mode) +- /* Switch the master clock source to slow clock. */ +- ldr pmc, .pmc_base +- ldr tmp2, .mckr_offset +- ldr tmp1, [pmc, tmp2] +- bic tmp1, tmp1, #AT91_PMC_CSS +- str tmp1, [pmc, tmp2] ++sr_ena_no_2nd_ddrc: ++ b sr_ena_exit + +- wait_mckrdy ++ /* ++ * SDRAMC Memory controller ++ */ ++sr_ena_sdramc_sf: ++ /* Active SDRAMC self-refresh mode */ ++ ldr r3, [r2, #AT91_SDRAMC_LPR] ++ str r3, .saved_sam9_lpr ++ bic r3, r3, #AT91_SDRAMC_LPCB ++ orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH ++ str r3, [r2, #AT91_SDRAMC_LPR] + +- /*BUMEN*/ +- ldr r0, .sfrbu +- mov tmp1, #0x1 +- str tmp1, [r0, #0x10] ++ ldr r3, .saved_sam9_lpr ++ str r3, [r2, #AT91_SDRAMC_LPR] + +- /* Shutdown */ +- ldr r0, .shdwc +- mov tmp1, #0xA5000000 +- add tmp1, tmp1, #0x1 +- str tmp1, [r0, #0] +-ENDPROC(at91_backup_mode) ++sr_ena_exit: ++.endm ++ ++/** ++ * Disable self-refresh ++ * ++ * register usage: ++ * @r1: memory type ++ * @r2: base address of the sram controller ++ * @r3: temporary ++ */ ++.macro at91_sramc_self_refresh_dis ++ ldr r1, .memtype ++ ldr r2, .sramc_base ++ ++ cmp r1, #AT91_MEMCTRL_MC ++ bne sr_dis_ddrc_exit_sf ++ ++ /* ++ * at91rm9200 Memory controller ++ */ ++ ++ /* ++ * For exiting the self-refresh mode, do nothing, ++ * automatically exit the self-refresh mode. ++ */ ++ b sr_dis_exit ++ ++sr_dis_ddrc_exit_sf: ++ cmp r1, #AT91_MEMCTRL_DDRSDR ++ bne sdramc_exit_sf ++ ++ /* DDR Memory controller */ ++ ++ /* Restore MDR in case of LPDDR1 */ ++ ldr r3, .saved_sam9_mdr ++ str r3, [r2, #AT91_DDRSDRC_MDR] ++ /* Restore LPR on AT91 with DDRAM */ ++ ldr r3, .saved_sam9_lpr ++ str r3, [r2, #AT91_DDRSDRC_LPR] ++ ++ /* If using the 2nd ddr controller */ ++ ldr r2, .sramc1_base ++ cmp r2, #0 ++ ldrne r3, .saved_sam9_mdr1 ++ strne r3, [r2, #AT91_DDRSDRC_MDR] ++ ldrne r3, .saved_sam9_lpr1 ++ strne r3, [r2, #AT91_DDRSDRC_LPR] ++ ++ b sr_dis_exit ++ ++sdramc_exit_sf: ++ /* SDRAMC Memory controller */ ++ ldr r3, .saved_sam9_lpr ++ str r3, [r2, #AT91_SDRAMC_LPR] ++ ++sr_dis_exit: ++.endm + + .macro at91_pm_ulp0_mode + ldr pmc, .pmc_base +@@ -503,7 +552,7 @@ ENDPROC(at91_backup_mode) + 2: + .endm + +-ENTRY(at91_ulp_mode) ++.macro at91_ulp_mode + ldr pmc, .pmc_base + ldr tmp2, .mckr_offset + ldr tmp3, .pm_mode +@@ -552,133 +601,97 @@ ulp_exit: + + wait_mckrdy + +- mov pc, lr +-ENDPROC(at91_ulp_mode) +- +-/* +- * void at91_sramc_self_refresh(unsigned int is_active) +- * +- * @input param: +- * @r0: 1 - active self-refresh mode +- * 0 - exit self-refresh mode +- * register usage: +- * @r1: memory type +- * @r2: base address of the sram controller +- */ +- +-ENTRY(at91_sramc_self_refresh) +- ldr r1, .memtype +- ldr r2, .sramc_base +- +- cmp r1, #AT91_MEMCTRL_MC +- bne ddrc_sf +- +- /* +- * at91rm9200 Memory controller +- */ +- +- /* +- * For exiting the self-refresh mode, do nothing, +- * automatically exit the self-refresh mode. +- */ +- tst r0, #SRAMC_SELF_FRESH_ACTIVE +- beq exit_sramc_sf +- +- /* Active SDRAM self-refresh mode */ +- mov r3, #1 +- str r3, [r2, #AT91_MC_SDRAMC_SRR] +- b exit_sramc_sf +- +-ddrc_sf: +- cmp r1, #AT91_MEMCTRL_DDRSDR +- bne sdramc_sf ++.endm + +- /* +- * DDR Memory controller +- */ +- tst r0, #SRAMC_SELF_FRESH_ACTIVE +- beq ddrc_exit_sf ++.macro at91_backup_mode ++ /* Switch the master clock source to slow clock. */ ++ ldr pmc, .pmc_base ++ ldr tmp2, .mckr_offset ++ ldr tmp1, [pmc, tmp2] ++ bic tmp1, tmp1, #AT91_PMC_CSS ++ str tmp1, [pmc, tmp2] + +- /* LPDDR1 --> force DDR2 mode during self-refresh */ +- ldr r3, [r2, #AT91_DDRSDRC_MDR] +- str r3, .saved_sam9_mdr +- bic r3, r3, #~AT91_DDRSDRC_MD +- cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR +- ldreq r3, [r2, #AT91_DDRSDRC_MDR] +- biceq r3, r3, #AT91_DDRSDRC_MD +- orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 +- streq r3, [r2, #AT91_DDRSDRC_MDR] ++ wait_mckrdy + +- /* Active DDRC self-refresh mode */ +- ldr r3, [r2, #AT91_DDRSDRC_LPR] +- str r3, .saved_sam9_lpr +- bic r3, r3, #AT91_DDRSDRC_LPCB +- orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH +- str r3, [r2, #AT91_DDRSDRC_LPR] ++ /*BUMEN*/ ++ ldr r0, .sfrbu ++ mov tmp1, #0x1 ++ str tmp1, [r0, #0x10] + +- /* If using the 2nd ddr controller */ +- ldr r2, .sramc1_base +- cmp r2, #0 +- beq no_2nd_ddrc ++ /* Shutdown */ ++ ldr r0, .shdwc ++ mov tmp1, #0xA5000000 ++ add tmp1, tmp1, #0x1 ++ str tmp1, [r0, #0] ++.endm + +- ldr r3, [r2, #AT91_DDRSDRC_MDR] +- str r3, .saved_sam9_mdr1 +- bic r3, r3, #~AT91_DDRSDRC_MD +- cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR +- ldreq r3, [r2, #AT91_DDRSDRC_MDR] +- biceq r3, r3, #AT91_DDRSDRC_MD +- orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 +- streq r3, [r2, #AT91_DDRSDRC_MDR] ++/* ++ * void at91_suspend_sram_fn(struct at91_pm_data*) ++ * @input param: ++ * @r0: base address of struct at91_pm_data ++ */ ++/* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */ ++ .align 3 ++ENTRY(at91_pm_suspend_in_sram) ++ /* Save registers on stack */ ++ stmfd sp!, {r4 - r12, lr} + +- /* Active DDRC self-refresh mode */ +- ldr r3, [r2, #AT91_DDRSDRC_LPR] +- str r3, .saved_sam9_lpr1 +- bic r3, r3, #AT91_DDRSDRC_LPCB +- orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH +- str r3, [r2, #AT91_DDRSDRC_LPR] ++ /* Drain write buffer */ ++ mov tmp1, #0 ++ mcr p15, 0, tmp1, c7, c10, 4 + +-no_2nd_ddrc: +- b exit_sramc_sf ++ ldr tmp1, [r0, #PM_DATA_PMC] ++ str tmp1, .pmc_base ++ ldr tmp1, [r0, #PM_DATA_RAMC0] ++ str tmp1, .sramc_base ++ ldr tmp1, [r0, #PM_DATA_RAMC1] ++ str tmp1, .sramc1_base ++ ldr tmp1, [r0, #PM_DATA_MEMCTRL] ++ str tmp1, .memtype ++ ldr tmp1, [r0, #PM_DATA_MODE] ++ str tmp1, .pm_mode ++ ldr tmp1, [r0, #PM_DATA_PMC_MCKR_OFFSET] ++ str tmp1, .mckr_offset ++ ldr tmp1, [r0, #PM_DATA_PMC_VERSION] ++ str tmp1, .pmc_version ++ /* Both ldrne below are here to preload their address in the TLB */ ++ ldr tmp1, [r0, #PM_DATA_SHDWC] ++ str tmp1, .shdwc ++ cmp tmp1, #0 ++ ldrne tmp2, [tmp1, #0] ++ ldr tmp1, [r0, #PM_DATA_SFRBU] ++ str tmp1, .sfrbu ++ cmp tmp1, #0 ++ ldrne tmp2, [tmp1, #0x10] + +-ddrc_exit_sf: +- /* Restore MDR in case of LPDDR1 */ +- ldr r3, .saved_sam9_mdr +- str r3, [r2, #AT91_DDRSDRC_MDR] +- /* Restore LPR on AT91 with DDRAM */ +- ldr r3, .saved_sam9_lpr +- str r3, [r2, #AT91_DDRSDRC_LPR] ++ /* Active the self-refresh mode */ ++ at91_sramc_self_refresh_ena + +- /* If using the 2nd ddr controller */ +- ldr r2, .sramc1_base +- cmp r2, #0 +- ldrne r3, .saved_sam9_mdr1 +- strne r3, [r2, #AT91_DDRSDRC_MDR] +- ldrne r3, .saved_sam9_lpr1 +- strne r3, [r2, #AT91_DDRSDRC_LPR] ++ ldr r0, .pm_mode ++ cmp r0, #AT91_PM_STANDBY ++ beq standby ++ cmp r0, #AT91_PM_BACKUP ++ beq backup_mode + +- b exit_sramc_sf ++ at91_ulp_mode ++ b exit_suspend + +- /* +- * SDRAMC Memory controller +- */ +-sdramc_sf: +- tst r0, #SRAMC_SELF_FRESH_ACTIVE +- beq sdramc_exit_sf ++standby: ++ /* Wait for interrupt */ ++ ldr pmc, .pmc_base ++ at91_cpu_idle ++ b exit_suspend + +- /* Active SDRAMC self-refresh mode */ +- ldr r3, [r2, #AT91_SDRAMC_LPR] +- str r3, .saved_sam9_lpr +- bic r3, r3, #AT91_SDRAMC_LPCB +- orr r3, r3, #AT91_SDRAMC_LPCB_SELF_REFRESH +- str r3, [r2, #AT91_SDRAMC_LPR] ++backup_mode: ++ at91_backup_mode + +-sdramc_exit_sf: +- ldr r3, .saved_sam9_lpr +- str r3, [r2, #AT91_SDRAMC_LPR] ++exit_suspend: ++ /* Exit the self-refresh mode */ ++ at91_sramc_self_refresh_dis + +-exit_sramc_sf: +- mov pc, lr +-ENDPROC(at91_sramc_self_refresh) ++ /* Restore registers, and return */ ++ ldmfd sp!, {r4 - r12, pc} ++ENDPROC(at91_pm_suspend_in_sram) + + .pmc_base: + .word 0 +-- +2.32.0 + |