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