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