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