Oops
[rpi-open-firmware.git] / sdram.c
1 /*=============================================================================
2 Copyright (C) 2016 Kristina Brooks
3 All rights reserved.
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 FILE DESCRIPTION
16 VideoCoreIV SDRAM initialization code.
17
18 =============================================================================*/
19
20 #include "lib/common.h"
21 #include "hardware.h"
22
23
24 extern uint32_t g_CPUID;
25
26 #define MR_REQUEST_SUCCESS(x) ((SD_MR_TIMEOUT_SET & x) != SD_MR_TIMEOUT_SET)
27 #define MR_GET_RDATA(x) ((x & SD_MR_RDATA_SET) >> SD_MR_RDATA_LSB)
28
29 #define RAM_TEST_ADDR 0xC0000000
30 #define RAM_TEST_PATTERN 0xAAAAAAAA
31
32 #define SIP_DEBUG(x) x
33 #define SCLKU_DEBUG(x) //SIP_DEBUG(x)
34
35 ALWAYS_INLINE inline void sdram_clkman_update_begin() {
36 CM_SDCCTL |= CM_PASSWORD | CM_SDCCTL_UPDATE_SET;
37 SCLKU_DEBUG(printf("%s: waiting for ACCPT (%X) ...\n", __FUNCTION__, CM_SDCCTL));
38 for (;;) if (CM_SDCCTL & CM_SDCCTL_ACCPT_SET) break;
39 SCLKU_DEBUG(printf("%s: ACCPT received! (%X)\n", __FUNCTION__, CM_SDCCTL));
40 }
41
42 ALWAYS_INLINE inline void sdram_clkman_update_end() {
43 CM_SDCCTL = CM_PASSWORD | (CM_SDCCTL & CM_SDCCTL_UPDATE_CLR);
44 SCLKU_DEBUG(printf("%s: waiting for ACCPT clear (%X) ...\n", __FUNCTION__, CM_SDCCTL));
45 for (;;) if ((CM_SDCCTL & CM_SDCCTL_ACCPT_SET) == 0) break;
46 SCLKU_DEBUG(printf("%s: ACCPT cleared! (%X)\n", __FUNCTION__, CM_SDCCTL));
47 }
48
49 ALWAYS_INLINE void sdram_reset_phy_lines() {
50 SIP_DEBUG(printf("%s: resetting APHY/DPHY lines ...\n", __FUNCTION__));
51
52 /* politely tell sdc that we'll be messing with address lines */
53 APHY_CSR_PHY_BIST_CNTRL_SPR = 0x30;
54
55 DPHY_CSR_GLBL_DQ_DLL_RESET = 0x1;
56 APHY_CSR_GLBL_ADDR_DLL_RESET = 0x1;
57
58 /* stall ... */
59 SD_CS;
60 SD_CS;
61 SD_CS;
62 SD_CS;
63
64 DPHY_CSR_GLBL_DQ_DLL_RESET = 0x0;
65 APHY_CSR_GLBL_ADDR_DLL_RESET = 0x0;
66
67 SIP_DEBUG(printf("%s: waiting for DPHY master PLL to lock ...\n", __FUNCTION__));
68 for (;;) if ((DPHY_CSR_GLBL_MSTR_DLL_LOCK_STAT & 0xFFFF) == 0xFFFF) break;
69 SIP_DEBUG(printf("%s: DPHY master PLL locked!\n", __FUNCTION__));
70 }
71
72 void sdram_init_late() {
73 uint32_t ctrl = 0x4;
74
75 SD_CS = (SD_CS & ~(SD_CS_DEL_KEEP_SET|SD_CS_DPD_SET|SD_CS_RESTRT_SET)) | SD_CS_STBY_SET;
76
77 /* wait for SDRAM controller to go down */
78 SIP_DEBUG(printf("%s: waiting for SDRAM controller to go down (%X) ...\n", __FUNCTION__, SD_CS));
79 for (;;) if ((SD_CS & SD_CS_SDUP_SET) == 0) break;
80 SIP_DEBUG(printf("%s: SDRAM controller down!\n", __FUNCTION__));
81
82 /* disable SDRAM clock */
83 sdram_clkman_update_begin();
84 CM_SDCCTL = (CM_SDCCTL & ~(CM_SDCCTL_ENAB_SET|CM_SDCCTL_CTRL_SET)) | CM_PASSWORD;
85 sdram_clkman_update_end();
86
87 SIP_DEBUG(printf("%s: SDRAM clock disabled!\n", __FUNCTION__));
88
89 /* left */
90
91 APHY_CSR_DDR_PLL_PWRDWN = 0;
92 APHY_CSR_DDR_PLL_GLOBAL_RESET = 0;
93 APHY_CSR_DDR_PLL_POST_DIV_RESET = 0;
94
95 APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL0 = (1 << 16) | 0x53 /* magic */;
96 APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL1 = 0;
97 APHY_CSR_DDR_PLL_MDIV_VALUE = 0;
98 APHY_CSR_DDR_PLL_GLOBAL_RESET = 1;
99
100 SIP_DEBUG(printf("%s: waiting for APHY DDR PLL to lock ...\n", __FUNCTION__));
101 for (;;) if (APHY_CSR_DDR_PLL_LOCK_STATUS & (1 << 16)) break;
102 SIP_DEBUG(printf("%s: APHY DDR PLL locked!\n", __FUNCTION__));
103
104 APHY_CSR_DDR_PLL_POST_DIV_RESET = 1;
105
106 sdram_clkman_update_begin();
107
108 CM_SDCCTL = CM_PASSWORD | (ctrl << CM_SDCCTL_CTRL_LSB) | (CM_SDCCTL & CM_SDCCTL_CTRL_CLR);
109 sdram_clkman_update_end();
110
111 SIP_DEBUG(printf("%s: CM_SDCCTL = 0x%X\n", __FUNCTION__, CM_SDCCTL));
112
113 /* second stage magic values */
114 SD_SA = 0x0C293395;
115 SD_SB = 0x0F9;
116 SD_SC = 0x32200743;
117 SD_SD = 0x71810F66;
118 SD_SE = 0x10412136;
119 SD_PT1 = 0x137B828;
120 SD_PT2 = 0x0F96;
121 SD_MRT = 0x3;
122
123 sdram_reset_phy_lines();
124
125 /* wait for address line pll to come back */
126 SIP_DEBUG(printf("%s: waiting for APHY global PLL to lock ...\n", __FUNCTION__));
127 for (;;) if (APHY_CSR_GLBL_ADR_DLL_LOCK_STAT == 3) break;
128 SIP_DEBUG(printf("%s: APHY global PLL locked!\n", __FUNCTION__));
129
130 /* tell sdc we're done messing with address lines */
131 APHY_CSR_PHY_BIST_CNTRL_SPR = 0x0;
132
133 /* woo, turn on sdram! */
134 SD_CS = (0x200042 & ~(SD_CS_STOP_SET|SD_CS_STBY_SET)) | SD_CS_RESTRT_SET;
135 }
136
137 unsigned int sdram_read_mr(unsigned int addr) {
138 while ((SD_MR & SD_MR_DONE_SET) != SD_MR_DONE_SET) {}
139 SD_MR = addr & 0xFF;
140 unsigned int mrr;
141 while (((mrr = SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {}
142 return mrr;
143 }
144
145 unsigned int sdram_write_mr(unsigned int addr, unsigned int data, bool wait) {
146 while ((SD_MR & SD_MR_DONE_SET) != SD_MR_DONE_SET) {}
147
148 SD_MR = (addr & 0xFF) | ((data & 0xFF) << 8) | SD_MR_RW_SET;
149
150 if (wait) {
151 unsigned int mrr;
152 while (((mrr = SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {}
153
154 if (mrr & SD_MR_TIMEOUT_SET)
155 panic("MR write timed out (addr=%d data=0x%X)", addr, data);
156
157 return mrr;
158 }
159 else {
160 return 0;
161 }
162 }
163
164 void sdram_reset_phy() {
165 printf("%s: resetting SDRAM PHY ...\n", __FUNCTION__);
166
167 /* reset PHYC */
168 SD_PHYC = SD_PHYC_PHYRST_SET;
169 udelay(64);
170 SD_PHYC = 0;
171
172 printf("%s: resetting DPHY CTRL ...\n", __FUNCTION__);
173
174 DPHY_CSR_DQ_PHY_MISC_CTRL = 0x7;
175 DPHY_CSR_DQ_PAD_MISC_CTRL = 0x0;
176 DPHY_CSR_BOOT_READ_DQS_GATE_CTRL = 0x11;
177
178 sdram_reset_phy_lines();
179
180 APHY_CSR_PHY_BIST_CNTRL_SPR = 0x0;
181 }
182
183 static void sdram_set_clock_source(unsigned int source, unsigned int div_) {
184 CM_SDCDIV = CM_PASSWORD | (div_ << CM_SDCDIV_DIV_LSB);
185 CM_SDCCTL = CM_PASSWORD | (CM_SDCCTL & CM_SDCCTL_SRC_CLR) | source;
186 CM_SDCCTL |= CM_PASSWORD | CM_SDCCTL_ENAB_SET;
187
188 printf("%s: source set to %d, div to %d, waiting for BUSY set (%X) ... \n", __FUNCTION__, source, div_, CM_SDCCTL);
189
190 for (;;) if (CM_SDCCTL & CM_SDCCTL_BUSY_SET) break;
191
192 printf("%s: BUSY set! (%X)\n", __FUNCTION__, CM_SDCCTL);
193 }
194
195 static void sdram_init_clkman()
196 {
197 uint32_t ctrl = 0;
198
199 sdram_clkman_update_begin();
200 CM_SDCCTL = CM_PASSWORD | (ctrl << CM_SDCCTL_CTRL_LSB) | (CM_SDCCTL & CM_SDCCTL_CTRL_CLR);
201 sdram_clkman_update_end();
202 }
203
204 static const char* lpddr2_manufacturer_name(uint32_t mr) {
205 switch (mr) {
206 case 1: return "Samsung";
207 case 2: return "Qimonda";
208 case 3: return "Elpida";
209 case 4: return "Etron";
210 case 5: return "Nanya";
211 case 6: return "Hynix";
212 default: return "Unknown";
213 }
214 }
215
216 static const char* lpddr2_density(uint32_t mr) {
217 /*
218 * i'm so stupid, why did i not notice that LPDDR2
219 * spec listed those as bits, not bytes *sigh*
220 */
221 switch ((mr & 0x33) >> 3) {
222 case 1: return "128MB";
223 case 2: return "256MB";
224 case 3: return "512MB";
225 case 4: return "1GB";
226 case 5: return "2GB";
227 case 6: return "4GB";
228 default: return "Unknown";
229 }
230 }
231
232 static void sdram_calibrate() {
233 /* some hw revisions require different slews */
234 bool st = ((g_CPUID >> 4) & 0xFFF) == 0x14;
235 uint32_t dq_slew = (st ? 2 : 3);
236
237 /* i don't get it, the spec says do not use this register */
238 sdram_write_mr(0xFF, 0, true);
239 /* RL = 6 / WL = 3 */
240 sdram_write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, true);
241
242 APHY_CSR_ADDR_PAD_DRV_SLEW_CTRL = 0x333;
243 DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL = (dq_slew << 8) | (dq_slew << 4) | 3;
244
245 printf("%s: DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL = 0x%X\n", __FUNCTION__, DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL);
246
247 /* tell sdc we want to calibrate */
248 APHY_CSR_PHY_BIST_CNTRL_SPR = 0x20;
249
250 APHY_CSR_ADDR_PVT_COMP_CTRL = 0x1;
251 printf("%s: waiting for address PVT calibration ...\n", __FUNCTION__);
252 for (;;) if (APHY_CSR_ADDR_PVT_COMP_STATUS & 2) break;
253
254 DPHY_CSR_DQ_PVT_COMP_CTRL = 0x1;
255 printf("%s: waiting for data PVT calibration ...\n", __FUNCTION__);
256 for (;;) if (DPHY_CSR_DQ_PVT_COMP_STATUS & 2) break;
257
258 /* tell sdc we're done calibrating */
259 APHY_CSR_PHY_BIST_CNTRL_SPR = 0x0;
260
261 /* send calibration command */
262 uint32_t old_mrt = SD_MRT;
263 SD_MRT = 20;
264 printf("%s: waiting for SDRAM calibration command ...\n", __FUNCTION__);
265 SD_MR = LPDDR2_MR_CALIBRATION | (0xFF << 8) | SD_MR_RW_SET | SD_MR_HI_Z_SET;
266 while ((SD_MR & SD_MR_DONE_SET) != SD_MR_DONE_SET) {}
267 SD_MRT = old_mrt;
268
269 sdram_write_mr(LPDDR2_MR_IO_CONFIG, st ? 3 : 2, false);
270 }
271
272 static void sdram_selftest()
273 {
274 volatile uint32_t* p = (volatile uint32_t*)RAM_TEST_ADDR;
275
276 printf("Testing SDRAM ...\n");
277
278 for (int i = 0; i < 0x100000; i++) {
279 p[i] = RAM_TEST_PATTERN;
280 if (p[i] != RAM_TEST_PATTERN)
281 panic("sdram initialization failed (idx=%d exptected=0x%x got=0x%x)", i, RAM_TEST_PATTERN, p[i]);
282 }
283
284 printf("SDRAM test successful!\n");
285 }
286
287 void sdram_init() {
288 uint32_t vendor_id, bc;
289
290 printf("%s: (0) SD_CS = 0x%X\n", __FUNCTION__, SD_CS);
291
292 PM_SMPS = PM_PASSWORD | 0x1;
293 A2W_SMPS_LDO1 = A2W_PASSWORD | 0x40000;
294 A2W_SMPS_LDO0 = A2W_PASSWORD | 0x0;
295
296 A2W_XOSC_CTRL |= A2W_PASSWORD | A2W_XOSC_CTRL_DDREN_SET;
297
298 /*
299 * STEP 1:
300 * configure the low-frequency PLL and enable SDC and perform
301 * the calibration sequence.
302 */
303
304 sdram_set_clock_source(CM_SRC_OSC, 1);
305
306 sdram_init_clkman();
307
308 sdram_reset_phy();
309
310 /* magic values */
311 SD_SA = 0x6E3395;
312 SD_SB = 0x0F9;
313 SD_SC = 0x6000431;
314 SD_SD = 0x10000011;
315 SD_SE = 0x10106000;
316 SD_PT1 = 0x0AF002;
317 SD_PT2 = 0x8C;
318 SD_MRT = 0x3;
319 SD_CS = 0x200042;
320
321 /* wait for SDRAM controller */
322 printf("%s: waiting for SDUP (%X) ...\n", __FUNCTION__, SD_CS);
323 for (;;) if (SD_CS & SD_CS_SDUP_SET) break;
324 printf("%s: SDRAM controller has arrived! (%X)\n", __FUNCTION__, SD_CS);
325
326 /* RL = 6 / WL = 3 */
327 sdram_write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, false);
328 sdram_calibrate();
329
330 /* identify installed memory */
331 vendor_id = sdram_read_mr(LPDDR2_MR_MANUFACTURER_ID);
332 if (!MR_REQUEST_SUCCESS(vendor_id)) {
333 panic("vendor id memory register read timed out");
334 }
335 vendor_id = MR_GET_RDATA(vendor_id);
336
337 bc = sdram_read_mr(LPDDR2_MR_METRICS);
338 if (!MR_REQUEST_SUCCESS(bc)) {
339 panic("basic configuration memory register read timed out");
340 }
341 bc = MR_GET_RDATA(bc);
342
343 printf("SDRAM Type: %s %s LPDDR2 (BC=0x%X)\n",
344 lpddr2_manufacturer_name(vendor_id),
345 lpddr2_density(bc),
346 bc);
347
348 /*
349 * STEP 2:
350 * after calibration, enable high-freq SDRAM PLL. because we're
351 * running from cache, we can freely mess with SDRAM clock without
352 * any issues, removing the need to copy the SDRAM late init stuff
353 * to bootrom ram. if later code that's running from SDRAM wants to
354 * mess with SDRAM clock it would need to do that.
355 */
356
357 sdram_init_late();
358 sdram_selftest();
359 }
360
This page took 0.132475 seconds and 5 git commands to generate.