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