Commit 87e1b30c authored by Claudiu Beznea's avatar Claudiu Beznea Committed by Nicolas Ferre

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: default avatarClaudiu Beznea <claudiu.beznea@microchip.com>
Signed-off-by: default avatarNicolas Ferre <nicolas.ferre@microchip.com>
Link: https://lore.kernel.org/r/20210415105010.569620-8-claudiu.beznea@microchip.com
parent 29cdf077
...@@ -75,98 +75,147 @@ tmp3 .req r6 ...@@ -75,98 +75,147 @@ tmp3 .req r6
.arm .arm
/* /**
* void at91_suspend_sram_fn(struct at91_pm_data*) * Enable self-refresh
* @input param: *
* @r0: base address of struct at91_pm_data * 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() */ .macro at91_sramc_self_refresh_ena
.align 3 ldr r1, .memtype
ENTRY(at91_pm_suspend_in_sram) ldr r2, .sramc_base
/* Save registers on stack */
stmfd sp!, {r4 - r12, lr}
/* Drain write buffer */ cmp r1, #AT91_MEMCTRL_MC
mov tmp1, #0 bne sr_ena_ddrc_sf
mcr p15, 0, tmp1, c7, c10, 4
ldr tmp1, [r0, #PM_DATA_PMC] /* Active SDRAM self-refresh mode */
str tmp1, .pmc_base mov r3, #1
ldr tmp1, [r0, #PM_DATA_RAMC0] str r3, [r2, #AT91_MC_SDRAMC_SRR]
str tmp1, .sramc_base b sr_ena_exit
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 the self-refresh mode */ sr_ena_ddrc_sf:
mov r0, #SRAMC_SELF_FRESH_ACTIVE cmp r1, #AT91_MEMCTRL_DDRSDR
bl at91_sramc_self_refresh bne sr_ena_sdramc_sf
ldr r0, .pm_mode /*
cmp r0, #AT91_PM_STANDBY * DDR Memory controller
beq standby */
cmp r0, #AT91_PM_BACKUP
beq backup_mode
bl at91_ulp_mode /* LPDDR1 --> force DDR2 mode during self-refresh */
b exit_suspend 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: /* Active DDRC self-refresh mode */
/* Wait for interrupt */ ldr r3, [r2, #AT91_DDRSDRC_LPR]
ldr pmc, .pmc_base str r3, .saved_sam9_lpr
at91_cpu_idle bic r3, r3, #AT91_DDRSDRC_LPCB
b exit_suspend orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
str r3, [r2, #AT91_DDRSDRC_LPR]
backup_mode: /* If using the 2nd ddr controller */
bl at91_backup_mode ldr r2, .sramc1_base
b exit_suspend cmp r2, #0
beq sr_ena_no_2nd_ddrc
exit_suspend: ldr r3, [r2, #AT91_DDRSDRC_MDR]
/* Exit the self-refresh mode */ str r3, .saved_sam9_mdr1
mov r0, #SRAMC_SELF_FRESH_EXIT bic r3, r3, #~AT91_DDRSDRC_MD
bl at91_sramc_self_refresh 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 */ /* Active DDRC self-refresh mode */
ldmfd sp!, {r4 - r12, pc} ldr r3, [r2, #AT91_DDRSDRC_LPR]
ENDPROC(at91_pm_suspend_in_sram) 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) sr_ena_no_2nd_ddrc:
/* Switch the master clock source to slow clock. */ b sr_ena_exit
ldr pmc, .pmc_base
ldr tmp2, .mckr_offset
ldr tmp1, [pmc, tmp2]
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
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 r3, .saved_sam9_lpr
ldr r0, .sfrbu str r3, [r2, #AT91_SDRAMC_LPR]
mov tmp1, #0x1
str tmp1, [r0, #0x10]
/* Shutdown */ sr_ena_exit:
ldr r0, .shdwc .endm
mov tmp1, #0xA5000000
add tmp1, tmp1, #0x1 /**
str tmp1, [r0, #0] * Disable self-refresh
ENDPROC(at91_backup_mode) *
* 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 .macro at91_pm_ulp0_mode
ldr pmc, .pmc_base ldr pmc, .pmc_base
...@@ -503,7 +552,7 @@ ENDPROC(at91_backup_mode) ...@@ -503,7 +552,7 @@ ENDPROC(at91_backup_mode)
2: 2:
.endm .endm
ENTRY(at91_ulp_mode) .macro at91_ulp_mode
ldr pmc, .pmc_base ldr pmc, .pmc_base
ldr tmp2, .mckr_offset ldr tmp2, .mckr_offset
ldr tmp3, .pm_mode ldr tmp3, .pm_mode
...@@ -552,133 +601,97 @@ ulp_exit: ...@@ -552,133 +601,97 @@ ulp_exit:
wait_mckrdy wait_mckrdy
mov pc, lr .endm
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
/* .macro at91_backup_mode
* DDR Memory controller /* Switch the master clock source to slow clock. */
*/ ldr pmc, .pmc_base
tst r0, #SRAMC_SELF_FRESH_ACTIVE ldr tmp2, .mckr_offset
beq ddrc_exit_sf ldr tmp1, [pmc, tmp2]
bic tmp1, tmp1, #AT91_PMC_CSS
str tmp1, [pmc, tmp2]
/* LPDDR1 --> force DDR2 mode during self-refresh */ wait_mckrdy
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]
/* Active DDRC self-refresh mode */ /*BUMEN*/
ldr r3, [r2, #AT91_DDRSDRC_LPR] ldr r0, .sfrbu
str r3, .saved_sam9_lpr mov tmp1, #0x1
bic r3, r3, #AT91_DDRSDRC_LPCB str tmp1, [r0, #0x10]
orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
str r3, [r2, #AT91_DDRSDRC_LPR]
/* If using the 2nd ddr controller */ /* Shutdown */
ldr r2, .sramc1_base ldr r0, .shdwc
cmp r2, #0 mov tmp1, #0xA5000000
beq no_2nd_ddrc add tmp1, tmp1, #0x1
str tmp1, [r0, #0]
.endm
ldr r3, [r2, #AT91_DDRSDRC_MDR] /*
str r3, .saved_sam9_mdr1 * void at91_suspend_sram_fn(struct at91_pm_data*)
bic r3, r3, #~AT91_DDRSDRC_MD * @input param:
cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR * @r0: base address of struct at91_pm_data
ldreq r3, [r2, #AT91_DDRSDRC_MDR] */
biceq r3, r3, #AT91_DDRSDRC_MD /* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 .align 3
streq r3, [r2, #AT91_DDRSDRC_MDR] ENTRY(at91_pm_suspend_in_sram)
/* Save registers on stack */
stmfd sp!, {r4 - r12, lr}
/* Active DDRC self-refresh mode */ /* Drain write buffer */
ldr r3, [r2, #AT91_DDRSDRC_LPR] mov tmp1, #0
str r3, .saved_sam9_lpr1 mcr p15, 0, tmp1, c7, c10, 4
bic r3, r3, #AT91_DDRSDRC_LPCB
orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH
str r3, [r2, #AT91_DDRSDRC_LPR]
no_2nd_ddrc: ldr tmp1, [r0, #PM_DATA_PMC]
b exit_sramc_sf 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: /* Active the self-refresh mode */
/* Restore MDR in case of LPDDR1 */ at91_sramc_self_refresh_ena
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 r0, .pm_mode
ldr r2, .sramc1_base cmp r0, #AT91_PM_STANDBY
cmp r2, #0 beq standby
ldrne r3, .saved_sam9_mdr1 cmp r0, #AT91_PM_BACKUP
strne r3, [r2, #AT91_DDRSDRC_MDR] beq backup_mode
ldrne r3, .saved_sam9_lpr1
strne r3, [r2, #AT91_DDRSDRC_LPR]
b exit_sramc_sf at91_ulp_mode
b exit_suspend
/* standby:
* SDRAMC Memory controller /* Wait for interrupt */
*/ ldr pmc, .pmc_base
sdramc_sf: at91_cpu_idle
tst r0, #SRAMC_SELF_FRESH_ACTIVE b exit_suspend
beq sdramc_exit_sf
/* Active SDRAMC self-refresh mode */ backup_mode:
ldr r3, [r2, #AT91_SDRAMC_LPR] at91_backup_mode
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]
sdramc_exit_sf: exit_suspend:
ldr r3, .saved_sam9_lpr /* Exit the self-refresh mode */
str r3, [r2, #AT91_SDRAMC_LPR] at91_sramc_self_refresh_dis
exit_sramc_sf: /* Restore registers, and return */
mov pc, lr ldmfd sp!, {r4 - r12, pc}
ENDPROC(at91_sramc_self_refresh) ENDPROC(at91_pm_suspend_in_sram)
.pmc_base: .pmc_base:
.word 0 .word 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment