diff options
author | Peter Rosin <peda@axentia.se> | 2015-02-05 01:02:09 -0500 |
---|---|---|
committer | Nicolas Ferre <nicolas.ferre@atmel.com> | 2015-03-03 13:43:59 -0500 |
commit | 02f513a0970d97e4fc5f262f5a6c814014af524e (patch) | |
tree | 1608f7b1eaf9cd1e42df3f021031742bdbf68fcc | |
parent | ad4a38d2187720a3d1442d693c99675ccd955f32 (diff) |
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>
-rw-r--r-- | arch/arm/mach-at91/pm_slowclock.S | 43 | ||||
-rw-r--r-- | include/soc/at91/at91sam9_ddrsdr.h | 2 |
2 files changed, 39 insertions, 6 deletions
diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S index 50744e7d5577..a2cc49f96f61 100644 --- a/arch/arm/mach-at91/pm_slowclock.S +++ b/arch/arm/mach-at91/pm_slowclock.S | |||
@@ -109,6 +109,16 @@ ddr_sr_enable: | |||
109 | cmp memctrl, #AT91_MEMCTRL_DDRSDR | 109 | cmp memctrl, #AT91_MEMCTRL_DDRSDR |
110 | bne sdr_sr_enable | 110 | bne sdr_sr_enable |
111 | 111 | ||
112 | /* LPDDR1 --> force DDR2 mode during self-refresh */ | ||
113 | ldr tmp1, [sdramc, #AT91_DDRSDRC_MDR] | ||
114 | str tmp1, .saved_sam9_mdr | ||
115 | bic tmp1, tmp1, #~AT91_DDRSDRC_MD | ||
116 | cmp tmp1, #AT91_DDRSDRC_MD_LOW_POWER_DDR | ||
117 | ldreq tmp1, [sdramc, #AT91_DDRSDRC_MDR] | ||
118 | biceq tmp1, tmp1, #AT91_DDRSDRC_MD | ||
119 | orreq tmp1, tmp1, #AT91_DDRSDRC_MD_DDR2 | ||
120 | streq tmp1, [sdramc, #AT91_DDRSDRC_MDR] | ||
121 | |||
112 | /* prepare for DDRAM self-refresh mode */ | 122 | /* prepare for DDRAM self-refresh mode */ |
113 | ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR] | 123 | ldr tmp1, [sdramc, #AT91_DDRSDRC_LPR] |
114 | str tmp1, .saved_sam9_lpr | 124 | str tmp1, .saved_sam9_lpr |
@@ -117,14 +127,26 @@ ddr_sr_enable: | |||
117 | 127 | ||
118 | /* figure out if we use the second ram controller */ | 128 | /* figure out if we use the second ram controller */ |
119 | cmp ramc1, #0 | 129 | cmp ramc1, #0 |
120 | ldrne tmp2, [ramc1, #AT91_DDRSDRC_LPR] | 130 | beq ddr_no_2nd_ctrl |
121 | strne tmp2, .saved_sam9_lpr1 | 131 | |
122 | bicne tmp2, #AT91_DDRSDRC_LPCB | 132 | ldr tmp2, [ramc1, #AT91_DDRSDRC_MDR] |
123 | orrne tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH | 133 | str tmp2, .saved_sam9_mdr1 |
134 | bic tmp2, tmp2, #~AT91_DDRSDRC_MD | ||
135 | cmp tmp2, #AT91_DDRSDRC_MD_LOW_POWER_DDR | ||
136 | ldreq tmp2, [ramc1, #AT91_DDRSDRC_MDR] | ||
137 | biceq tmp2, tmp2, #AT91_DDRSDRC_MD | ||
138 | orreq tmp2, tmp2, #AT91_DDRSDRC_MD_DDR2 | ||
139 | streq tmp2, [ramc1, #AT91_DDRSDRC_MDR] | ||
140 | |||
141 | ldr tmp2, [ramc1, #AT91_DDRSDRC_LPR] | ||
142 | str tmp2, .saved_sam9_lpr1 | ||
143 | bic tmp2, #AT91_DDRSDRC_LPCB | ||
144 | orr tmp2, #AT91_DDRSDRC_LPCB_SELF_REFRESH | ||
124 | 145 | ||
125 | /* Enable DDRAM self-refresh mode */ | 146 | /* Enable DDRAM self-refresh mode */ |
147 | str tmp2, [ramc1, #AT91_DDRSDRC_LPR] | ||
148 | ddr_no_2nd_ctrl: | ||
126 | str tmp1, [sdramc, #AT91_DDRSDRC_LPR] | 149 | str tmp1, [sdramc, #AT91_DDRSDRC_LPR] |
127 | strne tmp2, [ramc1, #AT91_DDRSDRC_LPR] | ||
128 | 150 | ||
129 | b sdr_sr_done | 151 | b sdr_sr_done |
130 | 152 | ||
@@ -255,12 +277,17 @@ sdr_sr_done: | |||
255 | */ | 277 | */ |
256 | cmp memctrl, #AT91_MEMCTRL_DDRSDR | 278 | cmp memctrl, #AT91_MEMCTRL_DDRSDR |
257 | bne sdr_en_restore | 279 | bne sdr_en_restore |
280 | /* Restore MDR in case of LPDDR1 */ | ||
281 | ldr tmp1, .saved_sam9_mdr | ||
282 | str tmp1, [sdramc, #AT91_DDRSDRC_MDR] | ||
258 | /* Restore LPR on AT91 with DDRAM */ | 283 | /* Restore LPR on AT91 with DDRAM */ |
259 | ldr tmp1, .saved_sam9_lpr | 284 | ldr tmp1, .saved_sam9_lpr |
260 | str tmp1, [sdramc, #AT91_DDRSDRC_LPR] | 285 | str tmp1, [sdramc, #AT91_DDRSDRC_LPR] |
261 | 286 | ||
262 | /* if we use the second ram controller */ | 287 | /* if we use the second ram controller */ |
263 | cmp ramc1, #0 | 288 | cmp ramc1, #0 |
289 | ldrne tmp2, .saved_sam9_mdr1 | ||
290 | strne tmp2, [ramc1, #AT91_DDRSDRC_MDR] | ||
264 | ldrne tmp2, .saved_sam9_lpr1 | 291 | ldrne tmp2, .saved_sam9_lpr1 |
265 | strne tmp2, [ramc1, #AT91_DDRSDRC_LPR] | 292 | strne tmp2, [ramc1, #AT91_DDRSDRC_LPR] |
266 | 293 | ||
@@ -294,5 +321,11 @@ ram_restored: | |||
294 | .saved_sam9_lpr1: | 321 | .saved_sam9_lpr1: |
295 | .word 0 | 322 | .word 0 |
296 | 323 | ||
324 | .saved_sam9_mdr: | ||
325 | .word 0 | ||
326 | |||
327 | .saved_sam9_mdr1: | ||
328 | .word 0 | ||
329 | |||
297 | ENTRY(at91_slow_clock_sz) | 330 | ENTRY(at91_slow_clock_sz) |
298 | .word .-at91_slow_clock | 331 | .word .-at91_slow_clock |
diff --git a/include/soc/at91/at91sam9_ddrsdr.h b/include/soc/at91/at91sam9_ddrsdr.h index 0210797abf2e..dc10c52e0e91 100644 --- a/include/soc/at91/at91sam9_ddrsdr.h +++ b/include/soc/at91/at91sam9_ddrsdr.h | |||
@@ -92,7 +92,7 @@ | |||
92 | #define AT91_DDRSDRC_UPD_MR (3 << 20) /* Update load mode register and extended mode register */ | 92 | #define AT91_DDRSDRC_UPD_MR (3 << 20) /* Update load mode register and extended mode register */ |
93 | 93 | ||
94 | #define AT91_DDRSDRC_MDR 0x20 /* Memory Device Register */ | 94 | #define AT91_DDRSDRC_MDR 0x20 /* Memory Device Register */ |
95 | #define AT91_DDRSDRC_MD (3 << 0) /* Memory Device Type */ | 95 | #define AT91_DDRSDRC_MD (7 << 0) /* Memory Device Type */ |
96 | #define AT91_DDRSDRC_MD_SDR 0 | 96 | #define AT91_DDRSDRC_MD_SDR 0 |
97 | #define AT91_DDRSDRC_MD_LOW_POWER_SDR 1 | 97 | #define AT91_DDRSDRC_MD_LOW_POWER_SDR 1 |
98 | #define AT91_DDRSDRC_MD_LOW_POWER_DDR 3 | 98 | #define AT91_DDRSDRC_MD_LOW_POWER_DDR 3 |