update Ultrascale DDRPHY
[litex.git] / litex / soc / software / bios / sdram.c
1 #include <generated/csr.h>
2
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 #ifdef CSR_SDRAM_BASE
7 #include <generated/sdram_phy.h>
8 #endif
9 #include <generated/mem.h>
10 #include <hw/flags.h>
11 #include <system.h>
12
13 #include "sdram.h"
14
15 // FIXME(hack): If we don't have main ram, just target the sram instead.
16 #ifndef MAIN_RAM_BASE
17 #define MAIN_RAM_BASE SRAM_BASE
18 #endif
19
20 static void cdelay(int i)
21 {
22 while(i > 0) {
23 #if defined (__lm32__)
24 __asm__ volatile("nop");
25 #elif defined (__or1k__)
26 __asm__ volatile("l.nop");
27 #elif defined (__picorv32__)
28 __asm__ volatile("nop");
29 #elif defined (__vexriscv__)
30 __asm__ volatile("nop");
31 #elif defined (__minerva__)
32 __asm__ volatile("nop");
33 #else
34 #error Unsupported architecture
35 #endif
36 i--;
37 }
38 }
39
40 #ifdef CSR_SDRAM_BASE
41
42 void sdrsw(void)
43 {
44 sdram_dfii_control_write(DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N);
45 printf("SDRAM now under software control\n");
46 }
47
48 void sdrhw(void)
49 {
50 sdram_dfii_control_write(DFII_CONTROL_SEL);
51 printf("SDRAM now under hardware control\n");
52 }
53
54 void sdrrow(char *_row)
55 {
56 char *c;
57 unsigned int row;
58
59 if(*_row == 0) {
60 sdram_dfii_pi0_address_write(0x0000);
61 sdram_dfii_pi0_baddress_write(0);
62 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
63 cdelay(15);
64 printf("Precharged\n");
65 } else {
66 row = strtoul(_row, &c, 0);
67 if(*c != 0) {
68 printf("incorrect row\n");
69 return;
70 }
71 sdram_dfii_pi0_address_write(row);
72 sdram_dfii_pi0_baddress_write(0);
73 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CS);
74 cdelay(15);
75 printf("Activated row %d\n", row);
76 }
77 }
78
79 void sdrrdbuf(int dq)
80 {
81 int i, p;
82 int first_byte, step;
83
84 if(dq < 0) {
85 first_byte = 0;
86 step = 1;
87 } else {
88 first_byte = DFII_PIX_DATA_SIZE/2 - 1 - dq;
89 step = DFII_PIX_DATA_SIZE/2;
90 }
91
92 for(p=0;p<DFII_NPHASES;p++)
93 for(i=first_byte;i<DFII_PIX_DATA_SIZE;i+=step)
94 printf("%02x", MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i));
95 printf("\n");
96 }
97
98 void sdrrd(char *startaddr, char *dq)
99 {
100 char *c;
101 unsigned int addr;
102 int _dq;
103
104 if(*startaddr == 0) {
105 printf("sdrrd <address>\n");
106 return;
107 }
108 addr = strtoul(startaddr, &c, 0);
109 if(*c != 0) {
110 printf("incorrect address\n");
111 return;
112 }
113 if(*dq == 0)
114 _dq = -1;
115 else {
116 _dq = strtoul(dq, &c, 0);
117 if(*c != 0) {
118 printf("incorrect DQ\n");
119 return;
120 }
121 }
122
123 sdram_dfii_pird_address_write(addr);
124 sdram_dfii_pird_baddress_write(0);
125 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
126 cdelay(15);
127 sdrrdbuf(_dq);
128 }
129
130 void sdrrderr(char *count)
131 {
132 int addr;
133 char *c;
134 int _count;
135 int i, j, p;
136 unsigned char prev_data[DFII_NPHASES*DFII_PIX_DATA_SIZE];
137 unsigned char errs[DFII_NPHASES*DFII_PIX_DATA_SIZE];
138
139 if(*count == 0) {
140 printf("sdrrderr <count>\n");
141 return;
142 }
143 _count = strtoul(count, &c, 0);
144 if(*c != 0) {
145 printf("incorrect count\n");
146 return;
147 }
148
149 for(i=0;i<DFII_NPHASES*DFII_PIX_DATA_SIZE;i++)
150 errs[i] = 0;
151 for(addr=0;addr<16;addr++) {
152 sdram_dfii_pird_address_write(addr*8);
153 sdram_dfii_pird_baddress_write(0);
154 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
155 cdelay(15);
156 for(p=0;p<DFII_NPHASES;p++)
157 for(i=0;i<DFII_PIX_DATA_SIZE;i++)
158 prev_data[p*DFII_PIX_DATA_SIZE+i] = MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i);
159
160 for(j=0;j<_count;j++) {
161 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
162 cdelay(15);
163 for(p=0;p<DFII_NPHASES;p++)
164 for(i=0;i<DFII_PIX_DATA_SIZE;i++) {
165 unsigned char new_data;
166
167 new_data = MMPTR(sdram_dfii_pix_rddata_addr[p]+4*i);
168 errs[p*DFII_PIX_DATA_SIZE+i] |= prev_data[p*DFII_PIX_DATA_SIZE+i] ^ new_data;
169 prev_data[p*DFII_PIX_DATA_SIZE+i] = new_data;
170 }
171 }
172 }
173
174 for(i=0;i<DFII_NPHASES*DFII_PIX_DATA_SIZE;i++)
175 printf("%02x", errs[i]);
176 printf("\n");
177 for(p=0;p<DFII_NPHASES;p++)
178 for(i=0;i<DFII_PIX_DATA_SIZE;i++)
179 printf("%2x", DFII_PIX_DATA_SIZE/2 - 1 - (i % (DFII_PIX_DATA_SIZE/2)));
180 printf("\n");
181 }
182
183 void sdrwr(char *startaddr)
184 {
185 char *c;
186 unsigned int addr;
187 int i;
188 int p;
189
190 if(*startaddr == 0) {
191 printf("sdrrd <address>\n");
192 return;
193 }
194 addr = strtoul(startaddr, &c, 0);
195 if(*c != 0) {
196 printf("incorrect address\n");
197 return;
198 }
199
200 for(p=0;p<DFII_NPHASES;p++)
201 for(i=0;i<DFII_PIX_DATA_SIZE;i++)
202 MMPTR(sdram_dfii_pix_wrdata_addr[p]+4*i) = 0x10*p + i;
203
204 sdram_dfii_piwr_address_write(addr);
205 sdram_dfii_piwr_baddress_write(0);
206 command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA);
207 }
208
209 #ifdef CSR_DDRPHY_BASE
210
211 #ifdef USDDRPHY
212 #define ERR_DDRPHY_DELAY 512
213 #else
214 #define ERR_DDRPHY_DELAY 32
215 #endif
216 #define ERR_DDRPHY_BITSLIP 8
217
218 #define NBMODULES DFII_PIX_DATA_SIZE/2
219
220 #ifdef CSR_DDRPHY_WLEVEL_EN_ADDR
221
222 void sdrwlon(void)
223 {
224 sdram_dfii_pi0_address_write(DDRX_MR1 | (1 << 7));
225 sdram_dfii_pi0_baddress_write(1);
226 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
227 ddrphy_wlevel_en_write(1);
228 }
229
230 void sdrwloff(void)
231 {
232 sdram_dfii_pi0_address_write(DDRX_MR1);
233 sdram_dfii_pi0_baddress_write(1);
234 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
235 ddrphy_wlevel_en_write(0);
236 }
237
238 int write_level(void)
239 {
240 int i, j, k;
241
242 int dq_address;
243 unsigned char dq;
244
245 int err_ddrphy_wdly;
246
247 unsigned char taps_scan[ERR_DDRPHY_DELAY];
248
249 int one_window_active;
250 int one_window_start;
251
252 int delays[NBMODULES];
253
254 int ok;
255
256 err_ddrphy_wdly = ERR_DDRPHY_DELAY - ddrphy_half_sys8x_taps_read() - 1;
257
258 printf("Write leveling:\n");
259
260 sdrwlon();
261 cdelay(100);
262 for(i=0;i<NBMODULES;i++) {
263 printf("m%d: |", i);
264 dq_address = sdram_dfii_pix_rddata_addr[0]+4*(NBMODULES-1-i);
265
266 /* reset delay */
267 ddrphy_dly_sel_write(1 << i);
268 ddrphy_wdly_dq_rst_write(1);
269 ddrphy_wdly_dqs_rst_write(1);
270 #ifdef USDDRPHY /* need to init manually on Ultrascale */
271 for(j=0; j<ddrphy_half_sys8x_taps_read(); j++)
272 ddrphy_wdly_dqs_inc_write(1);
273 #endif
274 /* scan taps */
275 for(j=0;j<err_ddrphy_wdly;j++) {
276 int zero_count = 0;
277 int one_count = 0;
278 int show = 1;
279 #ifdef USDDRPHY
280 show = (j%16 == 0);
281 #endif
282 for (k=0; k<128; k++) {
283 ddrphy_wlevel_strobe_write(1);
284 cdelay(10);
285 dq = MMPTR(dq_address);
286 if (dq != 0)
287 one_count++;
288 else
289 zero_count++;
290 }
291 if (one_count > zero_count)
292 taps_scan[j] = 1;
293 else
294 taps_scan[j] = 0;
295 if (show)
296 printf("%d", taps_scan[j]);
297 ddrphy_wdly_dq_inc_write(1);
298 ddrphy_wdly_dqs_inc_write(1);
299 cdelay(10);
300 }
301 printf("|");
302
303 /* select last 0/1 transition */
304 one_window_active = 0;
305 one_window_start = 0;
306 delays[i] = -1;
307 for(j=0;j<err_ddrphy_wdly;j++) {
308 if (one_window_active) {
309 if (taps_scan[j] == 0)
310 one_window_active = 0;
311 } else {
312 if (taps_scan[j]) {
313 one_window_active = 1;
314 one_window_start = j;
315 }
316 }
317 }
318 delays[i] = one_window_start;
319
320 /* configure delays */
321 ddrphy_wdly_dq_rst_write(1);
322 ddrphy_wdly_dqs_rst_write(1);
323 #ifdef USDDRPHY /* need to init manually on Ultrascale */
324 for(j=0; j<ddrphy_half_sys8x_taps_read(); j++)
325 ddrphy_wdly_dqs_inc_write(1);
326 #endif
327 for(j=0; j<delays[i]; j++) {
328 ddrphy_wdly_dq_inc_write(1);
329 ddrphy_wdly_dqs_inc_write(1);
330 }
331
332 printf(" delay: %02d\n", delays[i]);
333 }
334
335 sdrwloff();
336
337 ok = 1;
338 for(i=NBMODULES-1;i>=0;i--) {
339 if(delays[i] < 0)
340 ok = 0;
341 }
342
343 return ok;
344 }
345
346 #endif /* CSR_DDRPHY_WLEVEL_EN_ADDR */
347
348 static void read_bitslip_inc(char m)
349 {
350 ddrphy_dly_sel_write(1 << m);
351 ddrphy_rdly_dq_bitslip_write(1);
352 }
353
354 static int read_level_scan(int module, int bitslip)
355 {
356 unsigned int prv;
357 unsigned char prs[DFII_NPHASES*DFII_PIX_DATA_SIZE];
358 int p, i, j;
359 int score;
360
361 /* Generate pseudo-random sequence */
362 prv = 42;
363 for(i=0;i<DFII_NPHASES*DFII_PIX_DATA_SIZE;i++) {
364 prv = 1664525*prv + 1013904223;
365 prs[i] = prv;
366 }
367
368 /* Activate */
369 sdram_dfii_pi0_address_write(0);
370 sdram_dfii_pi0_baddress_write(0);
371 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CS);
372 cdelay(15);
373
374 /* Write test pattern */
375 for(p=0;p<DFII_NPHASES;p++)
376 for(i=0;i<DFII_PIX_DATA_SIZE;i++)
377 MMPTR(sdram_dfii_pix_wrdata_addr[p]+4*i) = prs[DFII_PIX_DATA_SIZE*p+i];
378 sdram_dfii_piwr_address_write(0);
379 sdram_dfii_piwr_baddress_write(0);
380 command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA);
381
382 /* Calibrate each DQ in turn */
383 sdram_dfii_pird_address_write(0);
384 sdram_dfii_pird_baddress_write(0);
385 score = 0;
386
387 printf("m%d, b%d: |", module, bitslip);
388 ddrphy_dly_sel_write(1 << module);
389 ddrphy_rdly_dq_rst_write(1);
390 for(j=0; j<ERR_DDRPHY_DELAY;j++) {
391 int working;
392 int show = 1;
393 #ifdef USDDRPHY
394 show = (j%16 == 0);
395 #endif
396 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
397 cdelay(15);
398 working = 1;
399 for(p=0;p<DFII_NPHASES;p++) {
400 if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
401 working = 0;
402 if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
403 working = 0;
404 }
405 if (show)
406 printf("%d", working);
407 score += working;
408 ddrphy_rdly_dq_inc_write(1);
409 }
410 printf("| ");
411
412 /* Precharge */
413 sdram_dfii_pi0_address_write(0);
414 sdram_dfii_pi0_baddress_write(0);
415 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
416 cdelay(15);
417
418 return score;
419 }
420
421 static void read_level(int module)
422 {
423 unsigned int prv;
424 unsigned char prs[DFII_NPHASES*DFII_PIX_DATA_SIZE];
425 int p, i, j;
426 int working;
427 int delay, delay_min, delay_max;
428
429 printf("delays: ");
430
431 /* Generate pseudo-random sequence */
432 prv = 42;
433 for(i=0;i<DFII_NPHASES*DFII_PIX_DATA_SIZE;i++) {
434 prv = 1664525*prv + 1013904223;
435 prs[i] = prv;
436 }
437
438 /* Activate */
439 sdram_dfii_pi0_address_write(0);
440 sdram_dfii_pi0_baddress_write(0);
441 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CS);
442 cdelay(15);
443
444 /* Write test pattern */
445 for(p=0;p<DFII_NPHASES;p++)
446 for(i=0;i<DFII_PIX_DATA_SIZE;i++)
447 MMPTR(sdram_dfii_pix_wrdata_addr[p]+4*i) = prs[DFII_PIX_DATA_SIZE*p+i];
448 sdram_dfii_piwr_address_write(0);
449 sdram_dfii_piwr_baddress_write(0);
450 command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA);
451
452 /* Calibrate each DQ in turn */
453 sdram_dfii_pird_address_write(0);
454 sdram_dfii_pird_baddress_write(0);
455
456 ddrphy_dly_sel_write(1 << module);
457 delay = 0;
458
459 /* Find smallest working delay */
460 ddrphy_rdly_dq_rst_write(1);
461 while(1) {
462 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
463 cdelay(15);
464 working = 1;
465 for(p=0;p<DFII_NPHASES;p++) {
466 if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
467 working = 0;
468 if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
469 working = 0;
470 }
471 if(working)
472 break;
473 delay++;
474 if(delay >= ERR_DDRPHY_DELAY)
475 break;
476 ddrphy_rdly_dq_inc_write(1);
477 }
478 delay_min = delay;
479
480 /* Get a bit further into the working zone */
481 #ifdef USDDRPHY
482 for(j=0;j<16;j++) {
483 delay += 1;
484 ddrphy_rdly_dq_inc_write(1);
485 }
486 #else
487 delay++;
488 ddrphy_rdly_dq_inc_write(1);
489 #endif
490
491 /* Find largest working delay */
492 while(1) {
493 command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
494 cdelay(15);
495 working = 1;
496 for(p=0;p<DFII_NPHASES;p++) {
497 if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+(NBMODULES-module-1)])
498 working = 0;
499 if(MMPTR(sdram_dfii_pix_rddata_addr[p]+4*(2*NBMODULES-module-1)) != prs[DFII_PIX_DATA_SIZE*p+2*NBMODULES-module-1])
500 working = 0;
501 }
502 if(!working)
503 break;
504 delay++;
505 if(delay >= ERR_DDRPHY_DELAY)
506 break;
507 ddrphy_rdly_dq_inc_write(1);
508 }
509 delay_max = delay;
510
511 printf("%02d+-%02d", (delay_min+delay_max)/2, (delay_max-delay_min)/2);
512
513 /* Set delay to the middle */
514 ddrphy_rdly_dq_rst_write(1);
515 for(j=0;j<(delay_min+delay_max)/2;j++)
516 ddrphy_rdly_dq_inc_write(1);
517
518 /* Precharge */
519 sdram_dfii_pi0_address_write(0);
520 sdram_dfii_pi0_baddress_write(0);
521 command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
522 cdelay(15);
523 }
524 #endif /* CSR_DDRPHY_BASE */
525
526 #endif /* CSR_SDRAM_BASE */
527
528 static unsigned int seed_to_data_32(unsigned int seed, int random)
529 {
530 if (random)
531 return 1664525*seed + 1013904223;
532 else
533 return seed + 1;
534 }
535
536 static unsigned short seed_to_data_16(unsigned short seed, int random)
537 {
538 if (random)
539 return 25173*seed + 13849;
540 else
541 return seed + 1;
542 }
543
544 #define ONEZERO 0xAAAAAAAA
545 #define ZEROONE 0x55555555
546
547 #ifndef MEMTEST_BUS_SIZE
548 #define MEMTEST_BUS_SIZE (512)
549 #endif
550
551 //#define MEMTEST_BUS_DEBUG
552
553 static int memtest_bus(void)
554 {
555 volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
556 int i, errors;
557 unsigned int rdata;
558
559 errors = 0;
560
561 for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
562 array[i] = ONEZERO;
563 }
564 flush_cpu_dcache();
565 #ifdef L2_SIZE
566 flush_l2_cache();
567 #endif
568 for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
569 rdata = array[i];
570 if(rdata != ONEZERO) {
571 errors++;
572 #ifdef MEMTEST_BUS_DEBUG
573 printf("[bus: 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, ONEZERO);
574 #endif
575 }
576 }
577
578 for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
579 array[i] = ZEROONE;
580 }
581 flush_cpu_dcache();
582 #ifdef L2_SIZE
583 flush_l2_cache();
584 #endif
585 for(i=0;i<MEMTEST_BUS_SIZE/4;i++) {
586 rdata = array[i];
587 if(rdata != ZEROONE) {
588 errors++;
589 #ifdef MEMTEST_BUS_DEBUG
590 printf("[bus 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, ZEROONE);
591 #endif
592 }
593 }
594
595 return errors;
596 }
597
598 #ifndef MEMTEST_DATA_SIZE
599 #define MEMTEST_DATA_SIZE (2*1024*1024)
600 #endif
601 #define MEMTEST_DATA_RANDOM 1
602
603 //#define MEMTEST_DATA_DEBUG
604
605 static int memtest_data(void)
606 {
607 volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
608 int i, errors;
609 unsigned int seed_32;
610 unsigned int rdata;
611
612 errors = 0;
613 seed_32 = 0;
614
615 for(i=0;i<MEMTEST_DATA_SIZE/4;i++) {
616 seed_32 = seed_to_data_32(seed_32, MEMTEST_DATA_RANDOM);
617 array[i] = seed_32;
618 }
619
620 seed_32 = 0;
621 flush_cpu_dcache();
622 #ifdef L2_SIZE
623 flush_l2_cache();
624 #endif
625 for(i=0;i<MEMTEST_DATA_SIZE/4;i++) {
626 seed_32 = seed_to_data_32(seed_32, MEMTEST_DATA_RANDOM);
627 rdata = array[i];
628 if(rdata != seed_32) {
629 errors++;
630 #ifdef MEMTEST_DATA_DEBUG
631 printf("[data 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, seed_32);
632 #endif
633 }
634 }
635
636 return errors;
637 }
638 #ifndef MEMTEST_ADDR_SIZE
639 #define MEMTEST_ADDR_SIZE (32*1024)
640 #endif
641 #define MEMTEST_ADDR_RANDOM 0
642
643 //#define MEMTEST_ADDR_DEBUG
644
645 static int memtest_addr(void)
646 {
647 volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
648 int i, errors;
649 unsigned short seed_16;
650 unsigned short rdata;
651
652 errors = 0;
653 seed_16 = 0;
654
655 for(i=0;i<MEMTEST_ADDR_SIZE/4;i++) {
656 seed_16 = seed_to_data_16(seed_16, MEMTEST_ADDR_RANDOM);
657 array[(unsigned int) seed_16] = i;
658 }
659
660 seed_16 = 0;
661 flush_cpu_dcache();
662 #ifdef L2_SIZE
663 flush_l2_cache();
664 #endif
665 for(i=0;i<MEMTEST_ADDR_SIZE/4;i++) {
666 seed_16 = seed_to_data_16(seed_16, MEMTEST_ADDR_RANDOM);
667 rdata = array[(unsigned int) seed_16];
668 if(rdata != i) {
669 errors++;
670 #ifdef MEMTEST_ADDR_DEBUG
671 printf("[addr 0x%0x]: 0x%08x vs 0x%08x\n", i, rdata, i);
672 #endif
673 }
674 }
675
676 return errors;
677 }
678
679 int memtest(void)
680 {
681 int bus_errors, data_errors, addr_errors;
682
683 bus_errors = memtest_bus();
684 if(bus_errors != 0)
685 printf("Memtest bus failed: %d/%d errors\n", bus_errors, 2*128);
686
687 data_errors = memtest_data();
688 if(data_errors != 0)
689 printf("Memtest data failed: %d/%d errors\n", data_errors, MEMTEST_DATA_SIZE/4);
690
691 addr_errors = memtest_addr();
692 if(addr_errors != 0)
693 printf("Memtest addr failed: %d/%d errors\n", addr_errors, MEMTEST_ADDR_SIZE/4);
694
695 if(bus_errors + data_errors + addr_errors != 0)
696 return 0;
697 else {
698 printf("Memtest OK\n");
699 return 1;
700 }
701 }
702
703 #ifdef CSR_SDRAM_BASE
704
705 #ifdef CSR_DDRPHY_BASE
706 int sdrlevel(void)
707 {
708 int i, j;
709 int bitslip;
710 int score;
711 int best_score;
712 int best_bitslip;
713
714 sdrsw();
715
716 for(i=0; i<NBMODULES; i++) {
717 ddrphy_dly_sel_write(1<<i);
718 ddrphy_rdly_dq_rst_write(1);
719 ddrphy_rdly_dq_bitslip_rst_write(1);
720 }
721
722 #ifdef CSR_DDRPHY_WLEVEL_EN_ADDR
723 if(!write_level())
724 return 0;
725 #endif
726
727 printf("Read leveling:\n");
728 for(i=0; i<NBMODULES; i++) {
729 /* scan possible read windows */
730 best_score = 0;
731 best_bitslip = 0;
732 for(bitslip=0; bitslip<ERR_DDRPHY_BITSLIP; bitslip++) {
733 /* compute score */
734 score = read_level_scan(i, bitslip);
735 read_level(i);
736 printf("\n");
737 if (score > best_score) {
738 best_bitslip = bitslip;
739 best_score = score;
740 }
741 /* exit */
742 if (bitslip == ERR_DDRPHY_BITSLIP-1)
743 break;
744 /* increment bitslip */
745 read_bitslip_inc(i);
746 }
747
748 /* select best read window */
749 printf("best: m%d, b%d ", i, best_bitslip);
750 ddrphy_rdly_dq_bitslip_rst_write(1);
751 for (j=0; j<best_bitslip; j++)
752 read_bitslip_inc(i);
753
754 /* re-do leveling on best read window*/
755 read_level(i);
756 printf("\n");
757 }
758
759 return 1;
760 }
761 #endif
762
763 int sdrinit(void)
764 {
765 printf("Initializing SDRAM...\n");
766
767 init_sequence();
768 #ifdef CSR_DDRPHY_BASE
769 #if CSR_DDRPHY_EN_VTC_ADDR
770 ddrphy_en_vtc_write(0);
771 #endif
772 sdrlevel();
773 #if CSR_DDRPHY_EN_VTC_ADDR
774 ddrphy_en_vtc_write(1);
775 #endif
776 #endif
777 sdrhw();
778 if(!memtest()) {
779 return 0;
780 }
781
782 return 1;
783 }
784
785 #endif