1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38#undef DEBUG
39
40#include <common.h>
41#include <ppc4xx.h>
42#include <asm/io.h>
43#include <asm/processor.h>
44
45#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
46
47
48
49
50
51#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
52
53#define MAXBXCF 4
54#define SDRAM_RXBAS_SHIFT_1M 20
55
56#if defined(CONFIG_SYS_DECREMENT_PATTERNS)
57#define NUMMEMTESTS 24
58#else
59#define NUMMEMTESTS 8
60#endif
61#define NUMLOOPS 1
62#define NUMMEMWORDS 16
63
64#define SDRAM_RDCC_RDSS_VAL(n) SDRAM_RDCC_RDSS_DECODE(ddr_rdss_opt(n))
65
66
67
68struct autocal_regs {
69 u32 rffd;
70 u32 rqfd;
71};
72
73struct ddrautocal {
74 u32 rffd;
75 u32 rffd_min;
76 u32 rffd_max;
77 u32 rffd_size;
78 u32 rqfd;
79 u32 rqfd_size;
80 u32 rdcc;
81 u32 flags;
82};
83
84struct sdram_timing {
85 u32 wrdtr;
86 u32 clktr;
87};
88
89struct sdram_timing_clks {
90 u32 wrdtr;
91 u32 clktr;
92 u32 rdcc;
93 u32 flags;
94};
95
96struct autocal_clks {
97 struct sdram_timing_clks clocks;
98 struct ddrautocal autocal;
99};
100
101
102
103
104#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
105static u32 DQS_calibration_methodA(struct ddrautocal *);
106static u32 program_DQS_calibration_methodA(struct ddrautocal *);
107#else
108static u32 DQS_calibration_methodB(struct ddrautocal *);
109static u32 program_DQS_calibration_methodB(struct ddrautocal *);
110#endif
111static int short_mem_test(u32 *);
112
113
114
115
116
117
118
119
120
121
122#if !defined(CONFIG_SPD_EEPROM)
123u32 __ddr_wrdtr(u32 default_val)
124{
125 return default_val;
126}
127u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));
128
129u32 __ddr_clktr(u32 default_val)
130{
131 return default_val;
132}
133u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));
134
135
136
137
138void __spd_ddr_init_hang(void)
139{
140 hang();
141}
142void
143spd_ddr_init_hang(void) __attribute__((weak, alias("__spd_ddr_init_hang")));
144#endif
145
146ulong __ddr_scan_option(ulong default_val)
147{
148 return default_val;
149}
150ulong ddr_scan_option(ulong) __attribute__((weak, alias("__ddr_scan_option")));
151
152u32 __ddr_rdss_opt(u32 default_val)
153{
154 return default_val;
155}
156u32 ddr_rdss_opt(ulong) __attribute__((weak, alias("__ddr_rdss_opt")));
157
158
159static u32 *get_membase(int bxcr_num)
160{
161 ulong bxcf;
162 u32 *membase;
163
164#if defined(SDRAM_R0BAS)
165
166 membase =
167 (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num)));
168 bxcf = 0;
169#else
170
171 mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
172 membase = (u32 *)((bxcf & 0xfff80000) << 3);
173#endif
174
175 return membase;
176}
177
178static inline void ecc_clear_status_reg(void)
179{
180 mtsdram(SDRAM_ECCCR, 0xffffffff);
181#if defined(SDRAM_R0BAS)
182 mtdcr(SDRAM_ERRSTATLL, 0xffffffff);
183#endif
184}
185
186
187
188
189static inline void relock_memory_DLL(void)
190{
191 u32 reg;
192
193 mtsdram(SDRAM_MCOPT2, SDRAM_MCOPT2_IPTR_EXECUTE);
194
195 do {
196 mfsdram(SDRAM_MCSTAT, reg);
197 } while (!(reg & SDRAM_MCSTAT_MIC_COMP));
198
199 mfsdram(SDRAM_MCOPT2, reg);
200 mtsdram(SDRAM_MCOPT2, reg | SDRAM_MCOPT2_DCEN_ENABLE);
201}
202
203static int ecc_check_status_reg(void)
204{
205 u32 ecc_status;
206
207
208
209
210
211
212
213 mfsdram(SDRAM_ECCCR, ecc_status);
214 if (ecc_status != 0x00000000) {
215
216 ecc_clear_status_reg();
217
218 return 0;
219 }
220 ecc_clear_status_reg();
221 sync();
222
223 return 1;
224}
225
226
227static int short_mem_test(u32 *base_address)
228{
229 int i, j, l;
230 u32 ecc_mode = 0;
231
232 ulong test[NUMMEMTESTS][NUMMEMWORDS] = {
233 {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
234 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
235 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
236 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
237 {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
238 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
239 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
240 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
241 {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
242 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
243 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
244 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
245 {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
246 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
247 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
248 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
249 {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
250 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
251 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
252 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
253 {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
254 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
255 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
256 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
257 {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
258 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
259 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
260 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
261 {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
262 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
263 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
264 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55},
265
266#if defined(CONFIG_SYS_DECREMENT_PATTERNS)
267 {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
268 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
269 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
270 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff},
271 {0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
272 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
273 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
274 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe},
275 {0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
276 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
277 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
278 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd},
279 {0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
280 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
281 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
282 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc},
283 {0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
284 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
285 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
286 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb},
287 {0xfffafffa, 0xfffafffa, 0xfffffffa, 0xfffafffa,
288 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
289 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
290 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa},
291 {0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
292 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
293 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
294 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9},
295 {0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
296 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
297 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
298 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8},
299 {0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
300 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
301 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
302 0xfff7ffff, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7},
303 {0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
304 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
305 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
306 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7},
307 {0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
308 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
309 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
310 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5},
311 {0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
312 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
313 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
314 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4},
315 {0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
316 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
317 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
318 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3},
319 {0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
320 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
321 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
322 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2},
323 {0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
324 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
325 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
326 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1},
327 {0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
328 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
329 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
330 0xfff0fff0, 0xfff0fffe, 0xfff0fff0, 0xfff0fff0},
331#endif
332 };
333
334 mfsdram(SDRAM_MCOPT1, ecc_mode);
335 if ((ecc_mode & SDRAM_MCOPT1_MCHK_CHK_REP) ==
336 SDRAM_MCOPT1_MCHK_CHK_REP) {
337 ecc_clear_status_reg();
338 sync();
339 ecc_mode = 1;
340 } else {
341 ecc_mode = 0;
342 }
343
344
345
346
347 for (i = 0; i < NUMMEMTESTS; i++) {
348 for (j = 0; j < NUMMEMWORDS; j++) {
349 base_address[j] = test[i][j];
350 ppcDcbf((ulong)&(base_address[j]));
351 }
352 sync();
353 iobarrier_rw();
354 for (l = 0; l < NUMLOOPS; l++) {
355 for (j = 0; j < NUMMEMWORDS; j++) {
356 if (base_address[j] != test[i][j]) {
357 ppcDcbf((u32)&(base_address[j]));
358 return 0;
359 } else {
360 if (ecc_mode) {
361 if (!ecc_check_status_reg())
362 return 0;
363 }
364 }
365 ppcDcbf((u32)&(base_address[j]));
366 }
367 sync();
368 iobarrier_rw();
369 }
370 }
371
372 return 1;
373}
374
375#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
376
377
378
379static u32 program_DQS_calibration_methodA(struct ddrautocal *ddrcal)
380{
381 u32 pass_result = 0;
382
383#ifdef DEBUG
384 ulong temp;
385
386 mfsdram(SDRAM_RDCC, temp);
387 debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
388#endif
389
390 pass_result = DQS_calibration_methodA(ddrcal);
391
392 return pass_result;
393}
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413static u32 DQS_calibration_methodA(struct ddrautocal *cal)
414{
415 ulong rfdc_reg;
416 ulong rffd;
417
418 ulong rqdc_reg;
419 ulong rqfd;
420
421 u32 *membase;
422 ulong bxcf;
423 int rqfd_average;
424 int bxcr_num;
425 int rffd_average;
426 int pass;
427 u32 passed = 0;
428
429 int in_window;
430 struct autocal_regs curr_win_min;
431 struct autocal_regs curr_win_max;
432 struct autocal_regs best_win_min;
433 struct autocal_regs best_win_max;
434 struct autocal_regs loop_win_min;
435 struct autocal_regs loop_win_max;
436
437#ifdef DEBUG
438 ulong temp;
439#endif
440 ulong rdcc;
441
442 char slash[] = "\\|/-\\|/-";
443 int loopi = 0;
444
445
446 in_window = 0;
447
448 memset(&curr_win_min, 0, sizeof(curr_win_min));
449 memset(&curr_win_max, 0, sizeof(curr_win_max));
450 memset(&best_win_min, 0, sizeof(best_win_min));
451 memset(&best_win_max, 0, sizeof(best_win_max));
452 memset(&loop_win_min, 0, sizeof(loop_win_min));
453 memset(&loop_win_max, 0, sizeof(loop_win_max));
454
455 rdcc = 0;
456
457
458
459
460
461 mtsdram(SDRAM_RDCC,
462 ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE);
463
464#ifdef DEBUG
465 mfsdram(SDRAM_RDCC, temp);
466 debug("<%s>SDRAM_RDCC=0x%x\n", __func__, temp);
467 mfsdram(SDRAM_RTSR, temp);
468 debug("<%s>SDRAM_RTSR=0x%x\n", __func__, temp);
469 mfsdram(SDRAM_FCSR, temp);
470 debug("<%s>SDRAM_FCSR=0x%x\n", __func__, temp);
471#endif
472
473
474
475
476
477 mtsdram(SDRAM_RQDC,
478 SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x00));
479
480#ifdef DEBUG
481 mfsdram(SDRAM_RQDC, temp);
482 debug("<%s>SDRAM_RQDC=0x%x\n", __func__, temp);
483#endif
484
485
486
487
488
489
490 mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
491 SDRAM_RFDC_RFOS_ENCODE(0) | SDRAM_RFDC_RFFD_ENCODE(0));
492
493#ifdef DEBUG
494 mfsdram(SDRAM_RFDC, temp);
495 debug("<%s>SDRAM_RFDC=0x%x\n", __func__, temp);
496#endif
497
498 putc(' ');
499 for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
500
501 mfsdram(SDRAM_RQDC, rqdc_reg);
502 rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
503 mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
504
505 putc('\b');
506 putc(slash[loopi++ % 8]);
507
508 curr_win_min.rffd = 0;
509 curr_win_max.rffd = 0;
510 in_window = 0;
511
512 for (rffd = 0, pass = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
513 mfsdram(SDRAM_RFDC, rfdc_reg);
514 rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
515 mtsdram(SDRAM_RFDC,
516 rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
517
518 for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
519 mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
520
521
522 if (bxcf & SDRAM_BXCF_M_BE_MASK) {
523
524 membase = get_membase(bxcr_num);
525 pass = short_mem_test(membase);
526 }
527 }
528
529
530 if (pass && !in_window) {
531 in_window = 1;
532 curr_win_min.rffd = curr_win_max.rffd = rffd;
533 curr_win_min.rqfd = curr_win_max.rqfd = rqfd;
534 mfsdram(SDRAM_RDCC, rdcc);
535 } else if (!pass && in_window) {
536 in_window = 0;
537 } else if (pass && in_window) {
538 curr_win_max.rffd = rffd;
539 curr_win_max.rqfd = rqfd;
540 }
541
542
543
544 if (in_window) {
545 if ((curr_win_max.rffd - curr_win_min.rffd) >
546 (best_win_max.rffd - best_win_min.rffd)) {
547 best_win_min.rffd = curr_win_min.rffd;
548 best_win_max.rffd = curr_win_max.rffd;
549
550 best_win_min.rqfd = curr_win_min.rqfd;
551 best_win_max.rqfd = curr_win_max.rqfd;
552 cal->rdcc = rdcc;
553 }
554 passed = 1;
555 }
556 }
557
558
559
560
561
562
563
564
565
566 if ((best_win_max.rffd - best_win_min.rffd) >
567 (loop_win_max.rffd - loop_win_min.rffd)) {
568 loop_win_min.rffd = best_win_min.rffd;
569 loop_win_max.rffd = best_win_max.rffd;
570 loop_win_min.rqfd = rqfd;
571 loop_win_max.rqfd = rqfd;
572 debug("RQFD.min 0x%08x, RQFD.max 0x%08x, "
573 "RFFD.min 0x%08x, RFFD.max 0x%08x\n",
574 loop_win_min.rqfd, loop_win_max.rqfd,
575 loop_win_min.rffd, loop_win_max.rffd);
576 }
577 }
578
579 putc('\b');
580
581 debug("\n");
582
583 if ((loop_win_min.rffd == 0) && (loop_win_max.rffd == 0) &&
584 (best_win_min.rffd == 0) && (best_win_max.rffd == 0) &&
585 (best_win_min.rqfd == 0) && (best_win_max.rqfd == 0)) {
586 passed = 0;
587 }
588
589
590
591
592 debug("<%s> RQFD Min: 0x%x\n", __func__, loop_win_min.rqfd);
593 debug("<%s> RQFD Max: 0x%x\n", __func__, loop_win_max.rqfd);
594 rqfd_average = loop_win_max.rqfd;
595
596 if (rqfd_average < 0)
597 rqfd_average = 0;
598
599 if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
600 rqfd_average = SDRAM_RQDC_RQFD_MAX;
601
602 debug("<%s> RFFD average: 0x%08x\n", __func__, rqfd_average);
603 mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
604 SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
605
606 debug("<%s> RFFD Min: 0x%08x\n", __func__, loop_win_min.rffd);
607 debug("<%s> RFFD Max: 0x%08x\n", __func__, loop_win_max.rffd);
608 rffd_average = ((loop_win_min.rffd + loop_win_max.rffd) / 2);
609
610 if (rffd_average < 0)
611 rffd_average = 0;
612
613 if (rffd_average > SDRAM_RFDC_RFFD_MAX)
614 rffd_average = SDRAM_RFDC_RFFD_MAX;
615
616 debug("<%s> RFFD average: 0x%08x\n", __func__, rffd_average);
617 mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
618
619
620 if (passed != 0) {
621 passed = loop_win_max.rffd - loop_win_min.rffd;
622 cal->rqfd = rqfd_average;
623 cal->rffd = rffd_average;
624 cal->rffd_min = loop_win_min.rffd;
625 cal->rffd_max = loop_win_max.rffd;
626 }
627
628 return (u32)passed;
629}
630
631#else
632
633
634
635
636static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal)
637{
638 u32 pass_result = 0;
639
640#ifdef DEBUG
641 ulong temp;
642#endif
643
644
645
646
647
648 mtsdram(SDRAM_RDCC,
649 ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE);
650
651#ifdef DEBUG
652 mfsdram(SDRAM_RDCC, temp);
653 debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
654#endif
655
656
657
658
659
660 mtsdram(SDRAM_RQDC,
661#if defined(CONFIG_DDR_RQDC_START_VAL)
662 SDRAM_RQDC_RQDE_ENABLE |
663 SDRAM_RQDC_RQFD_ENCODE(CONFIG_DDR_RQDC_START_VAL));
664#else
665 SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x38));
666#endif
667
668#ifdef DEBUG
669 mfsdram(SDRAM_RQDC, temp);
670 debug("<%s>SDRAM_RQDC=0x%08x\n", __func__, temp);
671#endif
672
673
674
675
676
677
678 mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
679 SDRAM_RFDC_RFOS_ENCODE(0) |
680 SDRAM_RFDC_RFFD_ENCODE(0));
681
682#ifdef DEBUG
683 mfsdram(SDRAM_RFDC, temp);
684 debug("<%s>SDRAM_RFDC=0x%08x\n", __func__, temp);
685#endif
686
687 pass_result = DQS_calibration_methodB(ddrcal);
688
689 return pass_result;
690}
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723static u32 DQS_calibration_methodB(struct ddrautocal *cal)
724{
725 ulong rfdc_reg;
726 ulong rffd;
727
728 ulong rqdc_reg;
729 ulong rqfd;
730
731 ulong rdcc;
732
733 u32 *membase;
734 ulong bxcf;
735 int rqfd_average;
736 int bxcr_num;
737 int rffd_average;
738 int pass;
739 uint passed = 0;
740
741 int in_window;
742 u32 curr_win_min, curr_win_max;
743 u32 best_win_min, best_win_max;
744 u32 size = 0;
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770 debug("\n\n");
771
772 in_window = 0;
773 rdcc = 0;
774
775 curr_win_min = curr_win_max = 0;
776 best_win_min = best_win_max = 0;
777 for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
778 mfsdram(SDRAM_RFDC, rfdc_reg);
779 rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
780 mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
781
782 pass = 1;
783 for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
784 mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
785
786
787 if (bxcf & SDRAM_BXCF_M_BE_MASK) {
788
789 membase = get_membase(bxcr_num);
790 pass &= short_mem_test(membase);
791 }
792 }
793
794
795 if (pass && !in_window) {
796 in_window = 1;
797 curr_win_min = curr_win_max = rffd;
798 mfsdram(SDRAM_RDCC, rdcc);
799 } else if (!pass && in_window) {
800 in_window = 0;
801 } else if (pass && in_window) {
802 curr_win_max = rffd;
803 }
804
805 if (in_window) {
806 if ((curr_win_max - curr_win_min) >
807 (best_win_max - best_win_min)) {
808 best_win_min = curr_win_min;
809 best_win_max = curr_win_max;
810 cal->rdcc = rdcc;
811 }
812 passed = 1;
813 }
814 }
815
816 if ((best_win_min == 0) && (best_win_max == 0))
817 passed = 0;
818 else
819 size = best_win_max - best_win_min;
820
821 debug("RFFD Min: 0x%x\n", best_win_min);
822 debug("RFFD Max: 0x%x\n", best_win_max);
823 rffd_average = ((best_win_min + best_win_max) / 2);
824
825 cal->rffd_min = best_win_min;
826 cal->rffd_max = best_win_max;
827
828 if (rffd_average < 0)
829 rffd_average = 0;
830
831 if (rffd_average > SDRAM_RFDC_RFFD_MAX)
832 rffd_average = SDRAM_RFDC_RFFD_MAX;
833
834 mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
835
836 rffd = rffd_average;
837 in_window = 0;
838
839 curr_win_min = curr_win_max = 0;
840 best_win_min = best_win_max = 0;
841 for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
842 mfsdram(SDRAM_RQDC, rqdc_reg);
843 rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
844 mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
845
846 pass = 1;
847 for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
848
849 mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
850
851
852 if (bxcf & SDRAM_BXCF_M_BE_MASK) {
853
854 membase = get_membase(bxcr_num);
855 pass &= short_mem_test(membase);
856 }
857 }
858
859
860 if (pass && !in_window) {
861 in_window = 1;
862 curr_win_min = curr_win_max = rqfd;
863 } else if (!pass && in_window) {
864 in_window = 0;
865 } else if (pass && in_window) {
866 curr_win_max = rqfd;
867 }
868
869 if (in_window) {
870 if ((curr_win_max - curr_win_min) >
871 (best_win_max - best_win_min)) {
872 best_win_min = curr_win_min;
873 best_win_max = curr_win_max;
874 }
875 passed = 1;
876 }
877 }
878
879 if ((best_win_min == 0) && (best_win_max == 0))
880 passed = 0;
881
882 debug("RQFD Min: 0x%x\n", best_win_min);
883 debug("RQFD Max: 0x%x\n", best_win_max);
884 rqfd_average = ((best_win_min + best_win_max) / 2);
885
886 if (rqfd_average < 0)
887 rqfd_average = 0;
888
889 if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
890 rqfd_average = SDRAM_RQDC_RQFD_MAX;
891
892 mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
893 SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
894
895 mfsdram(SDRAM_RQDC, rqdc_reg);
896 mfsdram(SDRAM_RFDC, rfdc_reg);
897
898
899
900
901
902
903 mtsdram(SDRAM_RQDC, rqdc_reg);
904 mtsdram(SDRAM_RFDC, rfdc_reg);
905
906 debug("RQDC: 0x%08X\n", rqdc_reg);
907 debug("RFDC: 0x%08X\n", rfdc_reg);
908
909
910 if (passed != 0) {
911 passed = size;
912 cal->rqfd = rqfd_average;
913 cal->rffd = rffd_average;
914 }
915
916 return (uint)passed;
917}
918#endif
919
920
921
922
923
924
925
926
927
928
929
930
931
932struct sdram_timing full_scan_options[] = {
933 {0, 0}, {0, 1}, {0, 2}, {0, 3},
934 {1, 0}, {1, 1}, {1, 2}, {1, 3},
935 {2, 0}, {2, 1}, {2, 2}, {2, 3},
936 {3, 0}, {3, 1}, {3, 2}, {3, 3},
937 {4, 0}, {4, 1}, {4, 2}, {4, 3},
938 {5, 0}, {5, 1}, {5, 2}, {5, 3},
939 {6, 0}, {6, 1}, {6, 2}, {6, 3},
940 {-1, -1}
941};
942
943
944
945
946u32 DQS_autocalibration(void)
947{
948 u32 wdtr;
949 u32 clkp;
950 u32 result = 0;
951 u32 best_result = 0;
952 u32 best_rdcc;
953 struct ddrautocal ddrcal;
954 struct autocal_clks tcal;
955 ulong rfdc_reg;
956 ulong rqdc_reg;
957 u32 val;
958 int verbose_lvl = 0;
959 char *str;
960 char slash[] = "\\|/-\\|/-";
961 int loopi = 0;
962 struct sdram_timing *scan_list;
963
964#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
965 int i;
966 char tmp[64];
967#endif
968
969 memset(&tcal, 0, sizeof(tcal));
970
971 ddr_scan_option((ulong)full_scan_options);
972
973 scan_list =
974 (struct sdram_timing *)ddr_scan_option((ulong)full_scan_options);
975
976 mfsdram(SDRAM_MCOPT1, val);
977 if ((val & SDRAM_MCOPT1_MCHK_CHK_REP) == SDRAM_MCOPT1_MCHK_CHK_REP)
978 str = "ECC Auto calibration -";
979 else
980 str = "Auto calibration -";
981
982 puts(str);
983
984#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
985 i = getenv_r("autocalib", tmp, sizeof(tmp));
986 if (i < 0)
987 strcpy(tmp, CONFIG_AUTOCALIB);
988
989 if (strcmp(tmp, "final") == 0) {
990
991 verbose_lvl = 1;
992 } else if (strcmp(tmp, "loop") == 0) {
993
994 verbose_lvl = 2;
995 } else if (strcmp(tmp, "display") == 0) {
996
997 verbose_lvl = 3;
998 }
999#endif
1000
1001 best_rdcc = (SDRAM_RDCC_RDSS_T4 >> 30);
1002
1003 while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) {
1004 wdtr = scan_list->wrdtr;
1005 clkp = scan_list->clktr;
1006
1007 mfsdram(SDRAM_WRDTR, val);
1008 val &= ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK);
1009 mtsdram(SDRAM_WRDTR, (val |
1010 ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (wdtr << 25))));
1011
1012 mtsdram(SDRAM_CLKTR, clkp << 30);
1013
1014 relock_memory_DLL();
1015
1016 putc('\b');
1017 putc(slash[loopi++ % 8]);
1018
1019#ifdef DEBUG
1020 debug("\n");
1021 debug("*** --------------\n");
1022 mfsdram(SDRAM_WRDTR, val);
1023 debug("*** SDRAM_WRDTR set to 0x%08x\n", val);
1024 mfsdram(SDRAM_CLKTR, val);
1025 debug("*** SDRAM_CLKTR set to 0x%08x\n", val);
1026#endif
1027
1028 debug("\n");
1029 if (verbose_lvl > 2) {
1030 printf("*** SDRAM_WRDTR (wdtr) set to %d\n", wdtr);
1031 printf("*** SDRAM_CLKTR (clkp) set to %d\n", clkp);
1032 }
1033
1034 memset(&ddrcal, 0, sizeof(ddrcal));
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
1056 result = program_DQS_calibration_methodA(&ddrcal);
1057#else
1058 result = program_DQS_calibration_methodB(&ddrcal);
1059#endif
1060
1061 sync();
1062
1063
1064
1065
1066
1067
1068 set_mcsr(get_mcsr());
1069
1070 val = ddrcal.rdcc;
1071
1072 udelay(100);
1073
1074 if (verbose_lvl > 1) {
1075 char *tstr;
1076 switch ((val >> 30)) {
1077 case 0:
1078 if (result != 0)
1079 tstr = "T1";
1080 else
1081 tstr = "N/A";
1082 break;
1083 case 1:
1084 tstr = "T2";
1085 break;
1086 case 2:
1087 tstr = "T3";
1088 break;
1089 case 3:
1090 tstr = "T4";
1091 break;
1092 default:
1093 tstr = "unknown";
1094 break;
1095 }
1096 printf("** WRDTR(%d) CLKTR(%d), Wind (%d), best (%d), "
1097 "max-min(0x%04x)(0x%04x), RDCC: %s\n",
1098 wdtr, clkp, result, best_result,
1099 ddrcal.rffd_min, ddrcal.rffd_max, tstr);
1100 }
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110 val = SDRAM_RDCC_RDSS_DECODE(val);
1111 debug("*** (%d) (%d) current_rdcc, best_rdcc\n",
1112 val, best_rdcc);
1113
1114 if ((result != 0) &&
1115 (val >= SDRAM_RDCC_RDSS_VAL(SDRAM_RDCC_RDSS_T2))) {
1116 if (((result == best_result) && (val < best_rdcc)) ||
1117 ((result > best_result) && (val <= best_rdcc))) {
1118 tcal.autocal.flags = 1;
1119 debug("*** (%d)(%d) result passed window "
1120 "size: 0x%08x, rqfd = 0x%08x, "
1121 "rffd = 0x%08x, rdcc = 0x%08x\n",
1122 wdtr, clkp, result, ddrcal.rqfd,
1123 ddrcal.rffd, ddrcal.rdcc);
1124
1125
1126
1127
1128
1129
1130 best_rdcc = val;
1131 tcal.clocks.wrdtr = wdtr;
1132 tcal.clocks.clktr = clkp;
1133 tcal.clocks.rdcc = SDRAM_RDCC_RDSS_ENCODE(val);
1134 tcal.autocal.rqfd = ddrcal.rqfd;
1135 tcal.autocal.rffd = ddrcal.rffd;
1136 best_result = result;
1137
1138 if (verbose_lvl > 2) {
1139 printf("** (%d)(%d) "
1140 "best result: 0x%04x\n",
1141 wdtr, clkp,
1142 best_result);
1143 printf("** (%d)(%d) "
1144 "best WRDTR: 0x%04x\n",
1145 wdtr, clkp,
1146 tcal.clocks.wrdtr);
1147 printf("** (%d)(%d) "
1148 "best CLKTR: 0x%04x\n",
1149 wdtr, clkp,
1150 tcal.clocks.clktr);
1151 printf("** (%d)(%d) "
1152 "best RQDC: 0x%04x\n",
1153 wdtr, clkp,
1154 tcal.autocal.rqfd);
1155 printf("** (%d)(%d) "
1156 "best RFDC: 0x%04x\n",
1157 wdtr, clkp,
1158 tcal.autocal.rffd);
1159 printf("** (%d)(%d) "
1160 "best RDCC: 0x%08x\n",
1161 wdtr, clkp,
1162 (u32)tcal.clocks.rdcc);
1163 mfsdram(SDRAM_RTSR, val);
1164 printf("** (%d)(%d) best "
1165 "loop RTSR: 0x%08x\n",
1166 wdtr, clkp, val);
1167 mfsdram(SDRAM_FCSR, val);
1168 printf("** (%d)(%d) best "
1169 "loop FCSR: 0x%08x\n",
1170 wdtr, clkp, val);
1171 }
1172 }
1173 }
1174 scan_list++;
1175 }
1176
1177 if (tcal.autocal.flags == 1) {
1178 if (verbose_lvl > 0) {
1179 printf("*** --------------\n");
1180 printf("*** best_result window size: %d\n",
1181 best_result);
1182 printf("*** best_result WRDTR: 0x%04x\n",
1183 tcal.clocks.wrdtr);
1184 printf("*** best_result CLKTR: 0x%04x\n",
1185 tcal.clocks.clktr);
1186 printf("*** best_result RQFD: 0x%04x\n",
1187 tcal.autocal.rqfd);
1188 printf("*** best_result RFFD: 0x%04x\n",
1189 tcal.autocal.rffd);
1190 printf("*** best_result RDCC: 0x%04x\n",
1191 tcal.clocks.rdcc);
1192 printf("*** --------------\n");
1193 printf("\n");
1194 }
1195
1196
1197
1198
1199
1200 mfsdram(SDRAM_WRDTR, val);
1201 mtsdram(SDRAM_WRDTR, (val &
1202 ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) |
1203 ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC |
1204 (tcal.clocks.wrdtr << 25)));
1205
1206 mtsdram(SDRAM_CLKTR, tcal.clocks.clktr << 30);
1207
1208 relock_memory_DLL();
1209
1210 mfsdram(SDRAM_RQDC, rqdc_reg);
1211 rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
1212 mtsdram(SDRAM_RQDC, rqdc_reg |
1213 SDRAM_RQDC_RQFD_ENCODE(tcal.autocal.rqfd));
1214
1215 mfsdram(SDRAM_RQDC, rqdc_reg);
1216 debug("*** best_result: read value SDRAM_RQDC 0x%08x\n",
1217 rqdc_reg);
1218
1219 mfsdram(SDRAM_RFDC, rfdc_reg);
1220 rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
1221 mtsdram(SDRAM_RFDC, rfdc_reg |
1222 SDRAM_RFDC_RFFD_ENCODE(tcal.autocal.rffd));
1223
1224 mfsdram(SDRAM_RFDC, rfdc_reg);
1225 debug("*** best_result: read value SDRAM_RFDC 0x%08x\n",
1226 rfdc_reg);
1227 mfsdram(SDRAM_RDCC, val);
1228 debug("*** SDRAM_RDCC 0x%08x\n", val);
1229 } else {
1230
1231
1232
1233 printf("DQS memory calibration window can not be determined, "
1234 "terminating u-boot.\n");
1235 ppc4xx_ibm_ddr2_register_dump();
1236 spd_ddr_init_hang();
1237 }
1238
1239 blank_string(strlen(str));
1240
1241 return 0;
1242}
1243#else
1244u32 DQS_autocalibration(void)
1245{
1246 return 0;
1247}
1248#endif
1249#endif
1250