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