pm: at91: Workaround DDRSDRC self-refresh bug with LPDDR1 memories.
The DDRSDR controller fails miserably to put LPDDR1 memories in self-refresh. Force the controller to think it has DDR2 memories during the self-refresh period, as the DDR2 self-refresh spec is equivalent to LPDDR1, and is correctly implemented in the controller. Assume that the second controller has the same fault, but that is untested. Signed-off-by: Peter Rosin <peda@axentia.se> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
This commit is contained in:
committed by
Nicolas Ferre
parent
ad4a38d218
commit
02f513a097
@@ -109,6 +109,16 @@ ddr_sr_enable:
|
|||||||
cmp memctrl, #AT91_MEMCTRL_DDRSDR
|
cmp memctrl, #AT91_MEMCTRL_DDRSDR
|
||||||
bne sdr_sr_enable
|
bne sdr_sr_enable
|
||||||
|
|
||||||
|
/* LPDDR1 --> force DDR2 mode during self-refresh */
|
||||||
|
ldr tmp1, [sdramc, #AT91_DDRSDRC_MDR]
|
||||||
|
str tmp1, .saved_sam9_mdr
|
||||||
|
bic tmp1, tmp1, #~AT91_DDRSDRC_MD
|
||||||
|
cmp tmp1, #AT91_DDRSDRC_MD_LOW_POWER_DDR
|
||||||
|
ldreq tmp1, [sdramc, #AT91_DDRSDRC_MDR]
|
||||||
|
biceq tmp1, tmp1, #AT91_DDRSDRC_MD
|
||||||
|
orreq tmp1, tmp1, #AT91_DDRSDRC_MD_DDR2
|
||||||
|
streq tmp1, [sdramc, #AT91_DDRSDRC_MDR]
|
||||||
|
|
||||||
/* prepare for DDRAM self-refresh mode */
|
/* prepare for DDRAM self-refresh mode */
|
||||||
ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
|
ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
|
||||||
str tmp1, .saved_sam9_lpr
|
str tmp1, .saved_sam9_lpr
|
||||||
@@ -117,14 +127,26 @@ ddr_sr_enable:
|
|||||||
|
|
||||||
/* figure out if we use the second ram controller */
|
/* figure out if we use the second ram controller */
|
||||||
cmp ramc1, #0
|
cmp ramc1, #0
|
||||||
ldrne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
|
beq ddr_no_2nd_ctrl
|
||||||
strne tmp2, .saved_sam9_lpr1
|
|
||||||
bicne tmp2, #AT91_DDRSDRC_LPCB
|
ldr tmp2, [ramc1, #AT91_DDRSDRC_MDR]
|
||||||
orrne tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
|
str tmp2, .saved_sam9_mdr1
|
||||||
|
bic tmp2, tmp2, #~AT91_DDRSDRC_MD
|
||||||
|
cmp tmp2, #AT91_DDRSDRC_MD_LOW_POWER_DDR
|
||||||
|
ldreq tmp2, [ramc1, #AT91_DDRSDRC_MDR]
|
||||||
|
biceq tmp2, tmp2, #AT91_DDRSDRC_MD
|
||||||
|
orreq tmp2, tmp2, #AT91_DDRSDRC_MD_DDR2
|
||||||
|
streq tmp2, [ramc1, #AT91_DDRSDRC_MDR]
|
||||||
|
|
||||||
|
ldr tmp2, [ramc1, #AT91_DDRSDRC_LPR]
|
||||||
|
str tmp2, .saved_sam9_lpr1
|
||||||
|
bic tmp2, #AT91_DDRSDRC_LPCB
|
||||||
|
orr tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
|
||||||
|
|
||||||
/* Enable DDRAM self-refresh mode */
|
/* Enable DDRAM self-refresh mode */
|
||||||
|
str tmp2, [ramc1, #AT91_DDRSDRC_LPR]
|
||||||
|
ddr_no_2nd_ctrl:
|
||||||
str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
|
str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
|
||||||
strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
|
|
||||||
|
|
||||||
b sdr_sr_done
|
b sdr_sr_done
|
||||||
|
|
||||||
@@ -255,12 +277,17 @@ sdr_sr_done:
|
|||||||
*/
|
*/
|
||||||
cmp memctrl, #AT91_MEMCTRL_DDRSDR
|
cmp memctrl, #AT91_MEMCTRL_DDRSDR
|
||||||
bne sdr_en_restore
|
bne sdr_en_restore
|
||||||
|
/* Restore MDR in case of LPDDR1 */
|
||||||
|
ldr tmp1, .saved_sam9_mdr
|
||||||
|
str tmp1, [sdramc, #AT91_DDRSDRC_MDR]
|
||||||
/* Restore LPR on AT91 with DDRAM */
|
/* Restore LPR on AT91 with DDRAM */
|
||||||
ldr tmp1, .saved_sam9_lpr
|
ldr tmp1, .saved_sam9_lpr
|
||||||
str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
|
str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
|
||||||
|
|
||||||
/* if we use the second ram controller */
|
/* if we use the second ram controller */
|
||||||
cmp ramc1, #0
|
cmp ramc1, #0
|
||||||
|
ldrne tmp2, .saved_sam9_mdr1
|
||||||
|
strne tmp2, [ramc1, #AT91_DDRSDRC_MDR]
|
||||||
ldrne tmp2, .saved_sam9_lpr1
|
ldrne tmp2, .saved_sam9_lpr1
|
||||||
strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
|
strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
|
||||||
|
|
||||||
@@ -294,5 +321,11 @@ ram_restored:
|
|||||||
.saved_sam9_lpr1:
|
.saved_sam9_lpr1:
|
||||||
.word 0
|
.word 0
|
||||||
|
|
||||||
|
.saved_sam9_mdr:
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
.saved_sam9_mdr1:
|
||||||
|
.word 0
|
||||||
|
|
||||||
ENTRY(at91_slow_clock_sz)
|
ENTRY(at91_slow_clock_sz)
|
||||||
.word .-at91_slow_clock
|
.word .-at91_slow_clock
|
||||||
|
|||||||
@@ -92,7 +92,7 @@
|
|||||||
#define AT91_DDRSDRC_UPD_MR (3 << 20) /* Update load mode register and extended mode register */
|
#define AT91_DDRSDRC_UPD_MR (3 << 20) /* Update load mode register and extended mode register */
|
||||||
|
|
||||||
#define AT91_DDRSDRC_MDR 0x20 /* Memory Device Register */
|
#define AT91_DDRSDRC_MDR 0x20 /* Memory Device Register */
|
||||||
#define AT91_DDRSDRC_MD (3 << 0) /* Memory Device Type */
|
#define AT91_DDRSDRC_MD (7 << 0) /* Memory Device Type */
|
||||||
#define AT91_DDRSDRC_MD_SDR 0
|
#define AT91_DDRSDRC_MD_SDR 0
|
||||||
#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1
|
#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1
|
||||||
#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3
|
#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3
|
||||||
|
|||||||
Reference in New Issue
Block a user