boards/targets/sim: get SDRAM working in simulation with sdram/model
[litex.git] / litex / soc / software / bios / sdram.c
1 #include <generated/csr.h>
2 #ifdef CSR_SDRAM_BASE
3
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 #include <generated/sdram_phy.h>
8 #include <generated/mem.h>
9 #include <hw/flags.h>
10 #include <system.h>
11
12 #include "sdram.h"
13
14 static void cdelay(int i)
15 {
16 while(i > 0) {
17 #if defined (__lm32__)
18 __asm__ volatile("nop");
19 #elif defined (__or1k__)
20 __asm__ volatile("l.nop");
21 #else
22 #error Unsupported architecture
23 #endif
24 i--;
25 }
26 }
27
28 void sdrsw(void)
29 {
30 sdram_dfii_control_write(DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
31 printf("SDRAM now under software control\n");
32 }
33
34 void sdrhw(void)
35 {
36 sdram_dfii_control_write(DFII_CONTROL_SEL);
37 printf("SDRAM now under hardware control\n");
38 }
39
40 void sdrrow(char *_row)
41 {
42 char *c;
43 unsigned int row;
44
45 if(*_row == 0) {
46 sdram_dfii_pi0_address_write(0x0000);
47 sdram_dfii_pi0_baddress_write(0);
48 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
49 cdelay(15);
50 printf("Precharged\n");
51 } else {
52 row = strtoul(_row, &c, 0);
53 if(*c != 0) {
54 printf("incorrect row\n");
55 return;
56 }
57 sdram_dfii_pi0_address_write(row);
58 sdram_dfii_pi0_baddress_write(0);
59 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CS);
60 cdelay(15);
61 printf("Activated row %d\n", row);
62 }
63 }
64
65 void sdrrdbuf(int dq)
66 {
67 int i, p;
68 int first_byte, step;
69
70 if(dq < 0) {
71 first_byte = 0;
72 step = 1;
73 } else {
74 first_byte = DFII_PIX_DATA_SIZE/2 - 1 - dq;
75 step = DFII_PIX_DATA_SIZE/2;
76 }
77
78 for(p=0;p<DFII_NPHASES;p++)
79 for(i=first_byte;i<DFII_PIX_DATA_SIZE;i+=step)
80 printf("%02x", MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i));
81 printf("\n");
82 }
83
84 void sdrrd(char *startaddr, char *dq)
85 {
86 char *c;
87 unsigned int addr;
88 int _dq;
89
90 if(*startaddr == 0) {
91 printf("sdrrd <address>\n");
92 return;
93 }
94 addr = strtoul(startaddr, &c, 0);
95 if(*c != 0) {
96 printf("incorrect address\n");
97 return;
98 }
99 if(*dq == 0)
100 _dq = -1;
101 else {
102 _dq = strtoul(dq, &c, 0);
103 if(*c != 0) {
104 printf("incorrect DQ\n");
105 return;
106 }
107 }
108
109 sdram_dfii_pird_address_write(addr);
110 sdram_dfii_pird_baddress_write(0);
111 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
112 cdelay(15);
113 sdrrdbuf(_dq);
114 }
115
116 void sdrrderr(char *count)
117 {
118 int addr;
119 char *c;
120 int _count;
121 int i, j, p;
122 unsigned char prev_data[DFII_NPHASES*DFII_PIX_DATA_SIZE];
123 unsigned char errs[DFII_NPHASES*DFII_PIX_DATA_SIZE];
124
125 if(*count == 0) {
126 printf("sdrrderr <count>\n");
127 return;
128 }
129 _count = strtoul(count, &c, 0);
130 if(*c != 0) {
131 printf("incorrect count\n");
132 return;
133 }
134
135 for(i=0;i<DFII_NPHASES*DFII_PIX_DATA_SIZE;i++)
136 errs[i] = 0;
137 for(addr=0;addr<16;addr++) {
138 sdram_dfii_pird_address_write(addr*8);
139 sdram_dfii_pird_baddress_write(0);
140 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
141 cdelay(15);
142 for(p=0;p<DFII_NPHASES;p++)
143 for(i=0;i<DFII_PIX_DATA_SIZE;i++)
144 prev_data[p*DFII_PIX_DATA_SIZE+i] = MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i);
145
146 for(j=0;j<_count;j++) {
147 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
148 cdelay(15);
149 for(p=0;p<DFII_NPHASES;p++)
150 for(i=0;i<DFII_PIX_DATA_SIZE;i++) {
151 unsigned char new_data;
152
153 new_data = MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i);
154 errs[p*DFII_PIX_DATA_SIZE+i] |= prev_data[p*DFII_PIX_DATA_SIZE+i] ^ new_data;
155 prev_data[p*DFII_PIX_DATA_SIZE+i] = new_data;
156 }
157 }
158 }
159
160 for(i=0;i<DFII_NPHASES*DFII_PIX_DATA_SIZE;i++)
161 printf("%02x", errs[i]);
162 printf("\n");
163 for(p=0;p<DFII_NPHASES;p++)
164 for(i=0;i<DFII_PIX_DATA_SIZE;i++)
165 printf("%2x", DFII_PIX_DATA_SIZE/2 - 1 - (i % (DFII_PIX_DATA_SIZE/2)));
166 printf("\n");
167 }
168
169 void sdrwr(char *startaddr)
170 {
171 char *c;
172 unsigned int addr;
173 int i;
174 int p;
175
176 if(*startaddr == 0) {
177 printf("sdrrd <address>\n");
178 return;
179 }
180 addr = strtoul(startaddr, &c, 0);
181 if(*c != 0) {
182 printf("incorrect address\n");
183 return;
184 }
185
186 for(p=0;p<DFII_NPHASES;p++)
187 for(i=0;i<DFII_PIX_DATA_SIZE;i++)
188 MMPTR(sdram_dfii_pix_wrdata_addr[p]+4*i) = 0x10*p + i;
189
190 sdram_dfii_piwr_address_write(addr);
191 sdram_dfii_piwr_baddress_write(0);
192 command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA);
193 }
194
195 #ifdef CSR_DDRPHY_BASE
196
197 void sdrwlon(void)
198 {
199 sdram_dfii_pi0_address_write(DDR3_MR1 | (1 << 7));
200 sdram_dfii_pi0_baddress_write(1);
201 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
202 ddrphy_wlevel_en_write(1);
203 }
204
205 void sdrwloff(void)
206 {
207 sdram_dfii_pi0_address_write(DDR3_MR1);
208 sdram_dfii_pi0_baddress_write(1);
209 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
210 ddrphy_wlevel_en_write(0);
211 }
212
213 #define ERR_DDRPHY_DELAY 32
214
215 static int write_level(int *delay, int *high_skew)
216 {
217 int i;
218 int dq_address;
219 unsigned char dq;
220 int ok;
221
222 printf("Write leveling: ");
223
224 sdrwlon();
225 cdelay(100);
226 for(i=0;i<DFII_PIX_DATA_SIZE/2;i++) {
227 dq_address = sdram_dfii_pix_rddata_addr[0]+4*(DFII_PIX_DATA_SIZE/2-1-i);
228 ddrphy_dly_sel_write(1 << i);
229 ddrphy_wdly_dq_rst_write(1);
230 ddrphy_wdly_dqs_rst_write(1);
231
232 delay[i] = 0;
233
234 ddrphy_wlevel_strobe_write(1);
235 cdelay(10);
236 dq = MMPTR(dq_address);
237 if(dq != 0) {
238 /*
239 * Assume this DQ group has between 1 and 2 bit times of skew.
240 * Bring DQS into the CK=0 zone before continuing leveling.
241 */
242 high_skew[i] = 1;
243 while(dq != 0) {
244 delay[i]++;
245 if(delay[i] >= ERR_DDRPHY_DELAY)
246 break;
247 ddrphy_wdly_dq_inc_write(1);
248 ddrphy_wdly_dqs_inc_write(1);
249 ddrphy_wlevel_strobe_write(1);
250 cdelay(10);
251 dq = MMPTR(dq_address);
252 }
253 } else
254 high_skew[i] = 0;
255
256 while(dq == 0) {
257 delay[i]++;
258 if(delay[i] >= ERR_DDRPHY_DELAY)
259 break;
260 ddrphy_wdly_dq_inc_write(1);
261 ddrphy_wdly_dqs_inc_write(1);
262
263 ddrphy_wlevel_strobe_write(1);
264 cdelay(10);
265 dq = MMPTR(dq_address);
266 }
267 }
268 sdrwloff();
269
270 ok = 1;
271 for(i=DFII_PIX_DATA_SIZE/2-1;i>=0;i--) {
272 printf("%2d%c ", delay[i], high_skew[i] ? '*' : ' ');
273 if(delay[i] >= ERR_DDRPHY_DELAY)
274 ok = 0;
275 }
276
277 if(ok)
278 printf("completed\n");
279 else
280 printf("failed\n");
281
282 return ok;
283 }
284
285 static void read_bitslip(int *delay, int *high_skew)
286 {
287 int bitslip_thr;
288 int i;
289
290 bitslip_thr = 0x7fffffff;
291 for(i=0;i<DFII_PIX_DATA_SIZE/2;i++)
292 if(high_skew[i] && (delay[i] < bitslip_thr))
293 bitslip_thr = delay[i];
294 if(bitslip_thr == 0x7fffffff)
295 return;
296 bitslip_thr = bitslip_thr/2;
297
298 printf("Read bitslip: ");
299 for(i=DFII_PIX_DATA_SIZE/2-1;i>=0;i--)
300 if(delay[i] > bitslip_thr) {
301 ddrphy_dly_sel_write(1 << i);
302 /* 7-series SERDES in DDR mode needs 3 pulses for 1 bitslip */
303 ddrphy_rdly_dq_bitslip_write(1);
304 ddrphy_rdly_dq_bitslip_write(1);
305 ddrphy_rdly_dq_bitslip_write(1);
306 printf("%d ", i);
307 }
308 printf("\n");
309 }
310
311 static void read_delays(void)
312 {
313 unsigned int prv;
314 unsigned char prs[DFII_NPHASES*DFII_PIX_DATA_SIZE];
315 int p, i, j;
316 int working;
317 int delay, delay_min, delay_max;
318
319 printf("Read delays: ");
320
321 /* Generate pseudo-random sequence */
322 prv = 42;
323 for(i=0;i<DFII_NPHASES*DFII_PIX_DATA_SIZE;i++) {
324 prv = 1664525*prv + 1013904223;
325 prs[i] = prv;
326 }
327
328 /* Activate */
329 sdram_dfii_pi0_address_write(0);
330 sdram_dfii_pi0_baddress_write(0);
331 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CS);
332 cdelay(15);
333
334 /* Write test pattern */
335 for(p=0;p<DFII_NPHASES;p++)
336 for(i=0;i<DFII_PIX_DATA_SIZE;i++)
337 MMPTR(sdram_dfii_pix_wrdata_addr[p]+4*i) = prs[DFII_PIX_DATA_SIZE*p+i];
338 sdram_dfii_piwr_address_write(0);
339 sdram_dfii_piwr_baddress_write(0);
340 command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA);
341
342 /* Calibrate each DQ in turn */
343 sdram_dfii_pird_address_write(0);
344 sdram_dfii_pird_baddress_write(0);
345 for(i=0;i<DFII_PIX_DATA_SIZE/2;i++) {
346 ddrphy_dly_sel_write(1 << (DFII_PIX_DATA_SIZE/2-i-1));
347 delay = 0;
348
349 /* Find smallest working delay */
350 ddrphy_rdly_dq_rst_write(1);
351 while(1) {
352 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
353 cdelay(15);
354 working = 1;
355 for(p=0;p<DFII_NPHASES;p++) {
356 if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i) != prs[DFII_PIX_DATA_SIZE*p+i])
357 working = 0;
358 if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(i+DFII_PIX_DATA_SIZE/2)) != prs[DFII_PIX_DATA_SIZE*p+i+DFII_PIX_DATA_SIZE/2])
359 working = 0;
360 }
361 if(working)
362 break;
363 delay++;
364 if(delay >= ERR_DDRPHY_DELAY)
365 break;
366 ddrphy_rdly_dq_inc_write(1);
367 }
368 delay_min = delay;
369
370 /* Get a bit further into the working zone */
371 delay++;
372 ddrphy_rdly_dq_inc_write(1);
373
374 /* Find largest working delay */
375 while(1) {
376 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
377 cdelay(15);
378 working = 1;
379 for(p=0;p<DFII_NPHASES;p++) {
380 if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i) != prs[DFII_PIX_DATA_SIZE*p+i])
381 working = 0;
382 if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(i+DFII_PIX_DATA_SIZE/2)) != prs[DFII_PIX_DATA_SIZE*p+i+DFII_PIX_DATA_SIZE/2])
383 working = 0;
384 }
385 if(!working)
386 break;
387 delay++;
388 if(delay >= ERR_DDRPHY_DELAY)
389 break;
390 ddrphy_rdly_dq_inc_write(1);
391 }
392 delay_max = delay;
393
394 printf("%d:%02d-%02d ", DFII_PIX_DATA_SIZE/2-i-1, delay_min, delay_max);
395
396 /* Set delay to the middle */
397 ddrphy_rdly_dq_rst_write(1);
398 for(j=0;j<(delay_min+delay_max)/2;j++)
399 ddrphy_rdly_dq_inc_write(1);
400 }
401
402 /* Precharge */
403 sdram_dfii_pi0_address_write(0);
404 sdram_dfii_pi0_baddress_write(0);
405 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
406 cdelay(15);
407
408 printf("completed\n");
409 }
410
411 int sdrlevel(void)
412 {
413 int delay[DFII_PIX_DATA_SIZE/2];
414 int high_skew[DFII_PIX_DATA_SIZE/2];
415
416 if(!write_level(delay, high_skew))
417 return 0;
418 read_bitslip(delay, high_skew);
419 read_delays();
420
421 return 1;
422 }
423
424 #endif /* CSR_DDRPHY_BASE */
425
426 #define TEST_DATA_SIZE (32*1024) // FIXME add #define
427 #define TEST_DATA_RANDOM 1
428
429 #define TEST_ADDR_SIZE (32*1024)
430 #define TEST_ADDR_RANDOM 0
431
432 #define ONEZERO 0xAAAAAAAA
433 #define ZEROONE 0x55555555
434
435 static unsigned int seed_to_data_32(unsigned int seed, int random)
436 {
437 if (random)
438 return 1664525*seed + 1013904223;
439 else
440 return seed + 1;
441 }
442
443 static unsigned short seed_to_data_16(unsigned short seed, int random)
444 {
445 if (random)
446 return 25173*seed + 13849;
447 else
448 return seed + 1;
449 }
450
451 int memtest_silent(void)
452 {
453 volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
454 int i;
455 unsigned int seed_32;
456 unsigned short seed_16;
457 unsigned int error_cnt;
458
459 error_cnt = 0;
460
461 /* test data bus */
462 for(i=0;i<128;i++) {
463 array[i] = ONEZERO;
464 }
465 flush_cpu_dcache();
466 flush_l2_cache();
467 for(i=0;i<128;i++) {
468 if(array[i] != ONEZERO)
469 error_cnt++;
470 }
471
472 for(i=0;i<128;i++) {
473 array[i] = ZEROONE;
474 }
475 flush_cpu_dcache();
476 flush_l2_cache();
477 for(i=0;i<128;i++) {
478 if(array[i] != ZEROONE)
479 error_cnt++;
480 }
481
482 /* test counter or random data */
483 seed_32 = 0;
484 for(i=0;i<TEST_DATA_SIZE/4;i++) {
485 seed_32 = seed_to_data_32(seed_32, TEST_DATA_RANDOM);
486 array[i] = seed_32;
487 }
488
489 seed_32 = 0;
490 flush_cpu_dcache();
491 flush_l2_cache();
492 for(i=0;i<TEST_DATA_SIZE/4;i++) {
493 seed_32 = seed_to_data_32(seed_32, TEST_DATA_RANDOM);
494 if(array[i] != seed_32)
495 error_cnt++;
496 }
497
498 /* test random addressing */
499 seed_16 = 0;
500 for(i=0;i<TEST_ADDR_SIZE/4;i++) {
501 seed_16 = seed_to_data_16(seed_16, TEST_ADDR_RANDOM);
502 array[(unsigned int) seed_16] = i;
503 }
504
505 seed_16 = 0;
506 flush_cpu_dcache();
507 flush_l2_cache();
508 for(i=0;i<TEST_ADDR_SIZE/4;i++) {
509 seed_16 = seed_to_data_16(seed_16, TEST_ADDR_RANDOM);
510 if(array[(unsigned int) seed_16] != i)
511 error_cnt++;
512 }
513
514 return error_cnt;
515 }
516
517 int memtest(void)
518 {
519 unsigned int e;
520
521 e = memtest_silent();
522 if(e != 0) {
523 printf("Memtest failed: %d/%d words incorrect\n", e, 2*128 + TEST_DATA_SIZE/4 + TEST_ADDR_SIZE/4);
524 return 0;
525 } else {
526 printf("Memtest OK\n");
527 return 1;
528 }
529 }
530
531 int sdrinit(void)
532 {
533 printf("Initializing SDRAM...\n");
534
535 init_sequence();
536 #ifdef CSR_DDRPHY_BASE
537 if(!sdrlevel())
538 return 0;
539 #endif
540 sdram_dfii_control_write(DFII_CONTROL_SEL);
541 if(!memtest())
542 return 0;
543
544 return 1;
545 }
546
547 #endif