soc/software/bios/sdram: split memtest and allow external #define of memtest sizes
[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 static unsigned int seed_to_data_32(unsigned int seed, int random)
427 {
428 if (random)
429 return 1664525*seed + 1013904223;
430 else
431 return seed + 1;
432 }
433
434 static unsigned short seed_to_data_16(unsigned short seed, int random)
435 {
436 if (random)
437 return 25173*seed + 13849;
438 else
439 return seed + 1;
440 }
441
442 #define ONEZERO 0xAAAAAAAA
443 #define ZEROONE 0x55555555
444
445 #ifndef MEMTEST_BUS_SIZE
446 #define MEMTEST_BUS_SIZE (512)
447 #endif
448
449 static int memtest_bus(void)
450 {
451 volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
452 int i, errors;
453
454 errors = 0;
455
456 for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
457 array[i] = ONEZERO;
458 }
459 flush_cpu_dcache();
460 flush_l2_cache();
461 for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
462 if(array[i] != ONEZERO)
463 errors++;
464 }
465
466 for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
467 array[i] = ZEROONE;
468 }
469 flush_cpu_dcache();
470 flush_l2_cache();
471 for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
472 if(array[i] != ZEROONE)
473 errors++;
474 }
475
476 return errors;
477 }
478
479 #ifndef MEMTEST_DATA_SIZE
480 #define MEMTEST_DATA_SIZE (2*1024*1024)
481 #endif
482 #define MEMTEST_DATA_RANDOM 1
483
484 static int memtest_data(void)
485 {
486 volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
487 int i, errors;
488 unsigned int seed_32;
489
490 errors = 0;
491 seed_32 = 0;
492
493 for(i=0;i<MEMTEST_DATA_SIZE/4;i++) {
494 seed_32 = seed_to_data_32(seed_32, MEMTEST_DATA_RANDOM);
495 array[i] = seed_32;
496 }
497
498 seed_32 = 0;
499 flush_cpu_dcache();
500 flush_l2_cache();
501 for(i=0;i<MEMTEST_DATA_SIZE/4;i++) {
502 seed_32 = seed_to_data_32(seed_32, MEMTEST_DATA_RANDOM);
503 if(array[i] != seed_32)
504 errors++;
505 }
506
507 return errors;
508 }
509 #ifndef MEMTEST_ADDR_SIZE
510 #define MEMTEST_ADDR_SIZE (32*1024)
511 #endif
512 #define MEMTEST_ADDR_RANDOM 0
513
514 static int memtest_addr(void)
515 {
516 volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
517 int i, errors;
518 unsigned short seed_16;
519
520 errors = 0;
521 seed_16 = 0;
522
523 for(i=0;i<MEMTEST_ADDR_SIZE/4;i++) {
524 seed_16 = seed_to_data_16(seed_16, MEMTEST_ADDR_RANDOM);
525 array[(unsigned int) seed_16] = i;
526 }
527
528 seed_16 = 0;
529 flush_cpu_dcache();
530 flush_l2_cache();
531 for(i=0;i<MEMTEST_ADDR_SIZE/4;i++) {
532 seed_16 = seed_to_data_16(seed_16, MEMTEST_ADDR_RANDOM);
533 if(array[(unsigned int) seed_16] != i)
534 errors++;
535 }
536
537 return errors;
538 }
539
540 int memtest(void)
541 {
542 int bus_errors, data_errors, addr_errors;
543
544 bus_errors = memtest_bus();
545 if(bus_errors != 0)
546 printf("Memtest bus failed: %d/%d errors\n", bus_errors, 2*128);
547
548 data_errors = memtest_data();
549 if(bus_errors != 0)
550 printf("Memtest data failed: %d/%d errors\n", data_errors, MEMTEST_DATA_SIZE/4);
551
552 addr_errors = memtest_addr();
553 if(addr_errors != 0)
554 printf("Memtest addr failed: %d/%d errors\n", addr_errors, MEMTEST_ADDR_SIZE/4);
555
556 if(bus_errors + data_errors + addr_errors != 0)
557 return 0;
558 else {
559 printf("Memtest OK\n");
560 return 1;
561 }
562 }
563
564 int sdrinit(void)
565 {
566 printf("Initializing SDRAM...\n");
567
568 init_sequence();
569 #ifdef CSR_DDRPHY_BASE
570 if(!sdrlevel())
571 return 0;
572 #endif
573 sdram_dfii_control_write(DFII_CONTROL_SEL);
574 if(!memtest())
575 return 0;
576
577 return 1;
578 }
579
580 #endif