aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Rosin <peda@axentia.se>2015-02-05 01:02:09 -0500
committerNicolas Ferre <nicolas.ferre@atmel.com>2015-03-03 13:43:59 -0500
commit02f513a0970d97e4fc5f262f5a6c814014af524e (patch)
tree1608f7b1eaf9cd1e42df3f021031742bdbf68fcc
parentad4a38d2187720a3d1442d693c99675ccd955f32 (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.S43
-rw-r--r--include/soc/at91/at91sam9_ddrsdr.h2
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]
148ddr_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
297ENTRY(at91_slow_clock_sz) 330ENTRY(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