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:
Peter Rosin 2015-02-05 14:02:09 +08:00 committed by Nicolas Ferre
parent ad4a38d218
commit 02f513a097
2 changed files with 39 additions and 6 deletions

View File

@ -109,6 +109,16 @@ ddr_sr_enable:
cmp memctrl, #AT91_MEMCTRL_DDRSDR
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 */
ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR]
str tmp1, .saved_sam9_lpr
@ -117,14 +127,26 @@ ddr_sr_enable:
/* figure out if we use the second ram controller */
cmp ramc1, #0
ldrne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
strne tmp2, .saved_sam9_lpr1
bicne tmp2, #AT91_DDRSDRC_LPCB
orrne tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH
beq ddr_no_2nd_ctrl
ldr tmp2, [ramc1, #AT91_DDRSDRC_MDR]
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 */
str tmp2, [ramc1, #AT91_DDRSDRC_LPR]
ddr_no_2nd_ctrl:
str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
b sdr_sr_done
@ -255,12 +277,17 @@ sdr_sr_done:
*/
cmp memctrl, #AT91_MEMCTRL_DDRSDR
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 */
ldr tmp1, .saved_sam9_lpr
str tmp1, [sdramc, #AT91_DDRSDRC_LPR]
/* if we use the second ram controller */
cmp ramc1, #0
ldrne tmp2, .saved_sam9_mdr1
strne tmp2, [ramc1, #AT91_DDRSDRC_MDR]
ldrne tmp2, .saved_sam9_lpr1
strne tmp2, [ramc1, #AT91_DDRSDRC_LPR]
@ -294,5 +321,11 @@ ram_restored:
.saved_sam9_lpr1:
.word 0
.saved_sam9_mdr:
.word 0
.saved_sam9_mdr1:
.word 0
ENTRY(at91_slow_clock_sz)
.word .-at91_slow_clock

View File

@ -92,7 +92,7 @@
#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_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_LOW_POWER_SDR 1
#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3