ppc4xx: Fix DDR2 auto calibration on Kilauea 600MHz (200MHz PLB)
[oweals/u-boot.git] / cpu / ppc4xx / 4xx_ibm_ddr2_autocalib.c
1 /*
2  * cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
3  * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a
4  * DDR2 controller (non Denali Core). Those currently are:
5  *
6  * 405:         405EX
7  * 440/460:     440SP/440SPe/460EX/460GT/460SX
8  *
9  * (C) Copyright 2008 Applied Micro Circuits Corporation
10  * Adam Graham  <agraham@amcc.com>
11  *
12  * (C) Copyright 2007-2008
13  * Stefan Roese, DENX Software Engineering, sr@denx.de.
14  *
15  * COPYRIGHT   AMCC   CORPORATION 2004
16  *
17  * See file CREDITS for list of people who contributed to this
18  * project.
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License as
22  * published by the Free Software Foundation; either version 2 of
23  * the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
33  * MA 02111-1307 USA
34  *
35  */
36
37 /* define DEBUG for debugging output (obviously ;-)) */
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  * Only compile the DDR auto-calibration code for NOR boot and
49  * not for NAND boot (NAND SPL and NAND U-Boot - NUB)
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(CFG_DECREMENT_PATTERNS)
57 #define NUMMEMTESTS             24
58 #else
59 #define NUMMEMTESTS             8
60 #endif /* CFG_DECREMENT_PATTERNS */
61 #define NUMLOOPS                1       /* configure as you deem approporiate */
62 #define NUMMEMWORDS             16
63
64 /* Private Structure Definitions */
65
66 struct autocal_regs {
67         u32 rffd;
68         u32 rqfd;
69 };
70
71 struct ddrautocal {
72         u32 rffd;
73         u32 rffd_min;
74         u32 rffd_max;
75         u32 rffd_size;
76         u32 rqfd;
77         u32 rqfd_size;
78         u32 rdcc;
79         u32 flags;
80 };
81
82 struct sdram_timing_clks {
83         u32 wrdtr;
84         u32 clktr;
85         u32 rdcc;
86         u32 flags;
87 };
88
89 struct autocal_clks {
90         struct sdram_timing_clks clocks;
91         struct ddrautocal        autocal;
92 };
93
94 /*--------------------------------------------------------------------------+
95  * Prototypes
96  *--------------------------------------------------------------------------*/
97 #if defined(CONFIG_PPC4xx_DDR_METHOD_A)
98 static u32 DQS_calibration_methodA(struct ddrautocal *);
99 static u32 program_DQS_calibration_methodA(struct ddrautocal *);
100 #else
101 static u32 DQS_calibration_methodB(struct ddrautocal *);
102 static u32 program_DQS_calibration_methodB(struct ddrautocal *);
103 #endif
104 static int short_mem_test(u32 *);
105
106 /*
107  * To provide an interface for board specific config values in this common
108  * DDR setup code, we implement he "weak" default functions here. They return
109  * the default value back to the caller.
110  *
111  * Please see include/configs/yucca.h for an example fora board specific
112  * implementation.
113  */
114
115 #if !defined(CONFIG_SPD_EEPROM)
116 u32 __ddr_wrdtr(u32 default_val)
117 {
118         return default_val;
119 }
120 u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));
121
122 u32 __ddr_clktr(u32 default_val)
123 {
124         return default_val;
125 }
126 u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));
127
128 /*
129  * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
130  */
131 void __spd_ddr_init_hang(void)
132 {
133         hang();
134 }
135 void
136 spd_ddr_init_hang(void) __attribute__((weak, alias("__spd_ddr_init_hang")));
137 #endif /* defined(CONFIG_SPD_EEPROM) */
138
139 ulong __ddr_scan_option(ulong default_val)
140 {
141         return default_val;
142 }
143 ulong ddr_scan_option(ulong) __attribute__((weak, alias("__ddr_scan_option")));
144
145 static u32 *get_membase(int bxcr_num)
146 {
147         ulong bxcf;
148         u32 *membase;
149
150 #if defined(SDRAM_R0BAS)
151         /* BAS from Memory Queue rank reg. */
152         membase =
153             (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num)));
154         bxcf = 0;       /* just to satisfy the compiler */
155 #else
156         /* BAS from SDRAM_MBxCF mem rank reg. */
157         mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
158         membase = (u32 *)((bxcf & 0xfff80000) << 3);
159 #endif
160
161         return membase;
162 }
163
164 static inline void ecc_clear_status_reg(void)
165 {
166         mtsdram(SDRAM_ECCCR, 0xffffffff);
167 #if defined(SDRAM_R0BAS)
168         mtdcr(SDRAM_ERRSTATLL, 0xffffffff);
169 #endif
170 }
171
172 static int ecc_check_status_reg(void)
173 {
174         u32 ecc_status;
175
176         /*
177          * Compare suceeded, now check
178          * if got ecc error. If got an
179          * ecc error, then don't count
180          * this as a passing value
181          */
182         mfsdram(SDRAM_ECCCR, ecc_status);
183         if (ecc_status != 0x00000000) {
184                 /* clear on error */
185                 ecc_clear_status_reg();
186                 /* ecc check failure */
187                 return 0;
188         }
189         ecc_clear_status_reg();
190         sync();
191
192         return 1;
193 }
194
195 /* return 1 if passes, 0 if fail */
196 static int short_mem_test(u32 *base_address)
197 {
198         int i, j, l;
199         u32 ecc_mode = 0;
200
201         ulong test[NUMMEMTESTS][NUMMEMWORDS] = {
202         /* 0 */ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
203                  0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
204                  0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
205                  0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
206         /* 1 */ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
207                  0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
208                  0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
209                  0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
210         /* 2 */ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
211                  0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
212                  0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
213                  0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
214         /* 3 */ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
215                  0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
216                  0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
217                  0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
218         /* 4 */ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
219                  0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
220                  0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
221                  0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
222         /* 5 */ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
223                  0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
224                  0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
225                  0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
226         /* 6 */ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
227                  0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
228                  0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
229                  0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
230         /* 7 */ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
231                  0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
232                  0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
233                  0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55},
234
235 #if defined(CFG_DECREMENT_PATTERNS)
236         /* 8 */ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
237                  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
238                  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
239                  0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff},
240         /* 9 */ {0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
241                  0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
242                  0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
243                  0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe},
244         /* 10 */{0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
245                  0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
246                  0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
247                  0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd},
248         /* 11 */{0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
249                  0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
250                  0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
251                  0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc},
252         /* 12 */{0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
253                  0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
254                  0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
255                  0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb},
256         /* 13 */{0xfffafffa, 0xfffafffa, 0xfffffffa, 0xfffafffa,
257                  0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
258                  0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
259                  0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa},
260         /* 14 */{0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
261                  0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
262                  0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
263                  0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9},
264         /* 15 */{0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
265                  0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
266                  0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
267                  0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8},
268         /* 16 */{0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
269                  0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
270                  0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
271                  0xfff7ffff, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7},
272         /* 17 */{0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
273                  0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
274                  0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
275                  0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7},
276         /* 18 */{0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
277                  0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
278                  0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
279                  0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5},
280         /* 19 */{0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
281                  0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
282                  0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
283                  0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4},
284         /* 20 */{0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
285                  0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
286                  0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
287                  0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3},
288         /* 21 */{0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
289                  0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
290                  0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
291                  0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2},
292         /* 22 */{0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
293                  0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
294                  0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
295                  0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1},
296         /* 23 */{0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
297                  0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
298                  0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
299                  0xfff0fff0, 0xfff0fffe, 0xfff0fff0, 0xfff0fff0},
300 #endif /* CFG_DECREMENT_PATTERNS */
301                                                                  };
302
303         mfsdram(SDRAM_MCOPT1, ecc_mode);
304         if ((ecc_mode & SDRAM_MCOPT1_MCHK_CHK_REP) ==
305                                                 SDRAM_MCOPT1_MCHK_CHK_REP) {
306                 ecc_clear_status_reg();
307                 sync();
308                 ecc_mode = 1;
309         } else {
310                 ecc_mode = 0;
311         }
312
313         /*
314          * Run the short memory test.
315          */
316         for (i = 0; i < NUMMEMTESTS; i++) {
317                 for (j = 0; j < NUMMEMWORDS; j++) {
318                         base_address[j] = test[i][j];
319                         ppcDcbf((ulong)&(base_address[j]));
320                 }
321                 sync();
322                 for (l = 0; l < NUMLOOPS; l++) {
323                         for (j = 0; j < NUMMEMWORDS; j++) {
324                                 if (base_address[j] != test[i][j]) {
325                                         ppcDcbf((u32)&(base_address[j]));
326                                         return 0;
327                                 } else {
328                                         if (ecc_mode) {
329                                                 if (!ecc_check_status_reg())
330                                                         return 0;
331                                         }
332                                 }
333                                 ppcDcbf((u32)&(base_address[j]));
334                         } /* for (j = 0; j < NUMMEMWORDS; j++) */
335                         sync();
336                 } /* for (l=0; l<NUMLOOPS; l++) */
337         }
338
339         return 1;
340 }
341
342 #if defined(CONFIG_PPC4xx_DDR_METHOD_A)
343 /*-----------------------------------------------------------------------------+
344 | program_DQS_calibration_methodA.
345 +-----------------------------------------------------------------------------*/
346 static u32 program_DQS_calibration_methodA(struct ddrautocal *ddrcal)
347 {
348         u32 pass_result = 0;
349
350 #ifdef DEBUG
351         ulong temp;
352
353         mfsdram(SDRAM_RDCC, temp);
354         debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
355 #endif
356
357         pass_result = DQS_calibration_methodA(ddrcal);
358
359         return pass_result;
360 }
361
362 /*
363  * DQS_calibration_methodA()
364  *
365  * Autocalibration Method A
366  *
367  *  ARRAY [Entire DQS Range] DQS_Valid_Window ;    initialized to all zeros
368  *  ARRAY [Entire FDBK Range] FDBK_Valid_Window;   initialized to all zeros
369  *  MEMWRITE(addr, expected_data);
370  *  for (i = 0; i < Entire DQS Range; i++) {       RQDC.RQFD
371  *      for (j = 0; j < Entire FDBK Range; j++) {  RFDC.RFFD
372  *         MEMREAD(addr, actual_data);
373  *         if (actual_data == expected_data) {
374  *             DQS_Valid_Window[i] = 1;            RQDC.RQFD
375  *             FDBK_Valid_Window[i][j] = 1;        RFDC.RFFD
376  *         }
377  *      }
378  *  }
379  */
380 static u32 DQS_calibration_methodA(struct ddrautocal *cal)
381 {
382         ulong rfdc_reg;
383         ulong rffd;
384
385         ulong rqdc_reg;
386         ulong rqfd;
387
388         u32 *membase;
389         ulong bxcf;
390         int rqfd_average;
391         int bxcr_num;
392         int rffd_average;
393         int pass;
394         u32 passed = 0;
395
396         int in_window;
397         struct autocal_regs curr_win_min;
398         struct autocal_regs curr_win_max;
399         struct autocal_regs best_win_min;
400         struct autocal_regs best_win_max;
401         struct autocal_regs loop_win_min;
402         struct autocal_regs loop_win_max;
403
404 #ifdef DEBUG
405         ulong temp;
406 #endif
407         ulong rdcc;
408
409         char slash[] = "\\|/-\\|/-";
410         int loopi = 0;
411
412         /* start */
413         in_window = 0;
414
415         memset(&curr_win_min, 0, sizeof(curr_win_min));
416         memset(&curr_win_max, 0, sizeof(curr_win_max));
417         memset(&best_win_min, 0, sizeof(best_win_min));
418         memset(&best_win_max, 0, sizeof(best_win_max));
419         memset(&loop_win_min, 0, sizeof(loop_win_min));
420         memset(&loop_win_max, 0, sizeof(loop_win_max));
421
422         rdcc = 0;
423
424         /*
425          * Program RDCC register
426          * Read sample cycle auto-update enable
427          */
428         mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T1 | SDRAM_RDCC_RSAE_ENABLE);
429
430 #ifdef DEBUG
431         mfsdram(SDRAM_RDCC, temp);
432         debug("<%s>SDRAM_RDCC=0x%x\n", __func__, temp);
433         mfsdram(SDRAM_RTSR, temp);
434         debug("<%s>SDRAM_RTSR=0x%x\n", __func__, temp);
435         mfsdram(SDRAM_FCSR, temp);
436         debug("<%s>SDRAM_FCSR=0x%x\n", __func__, temp);
437 #endif
438
439         /*
440          * Program RQDC register
441          * Internal DQS delay mechanism enable
442          */
443         mtsdram(SDRAM_RQDC,
444                 SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x00));
445
446 #ifdef DEBUG
447         mfsdram(SDRAM_RQDC, temp);
448         debug("<%s>SDRAM_RQDC=0x%x\n", __func__, temp);
449 #endif
450
451         /*
452          * Program RFDC register
453          * Set Feedback Fractional Oversample
454          * Auto-detect read sample cycle enable
455          */
456         mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
457                 SDRAM_RFDC_RFOS_ENCODE(0) | SDRAM_RFDC_RFFD_ENCODE(0));
458
459 #ifdef DEBUG
460         mfsdram(SDRAM_RFDC, temp);
461         debug("<%s>SDRAM_RFDC=0x%x\n", __func__, temp);
462 #endif
463
464         putc(' ');
465         for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
466
467                 mfsdram(SDRAM_RQDC, rqdc_reg);
468                 rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
469                 mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
470
471                 putc('\b');
472                 putc(slash[loopi++ % 8]);
473
474                 curr_win_min.rffd = 0;
475                 curr_win_max.rffd = 0;
476                 in_window = 0;
477
478                 for (rffd = 0, pass = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
479                         mfsdram(SDRAM_RFDC, rfdc_reg);
480                         rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
481                         mtsdram(SDRAM_RFDC,
482                                     rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
483
484                         for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
485                                 mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
486
487                                 /* Banks enabled */
488                                 if (bxcf & SDRAM_BXCF_M_BE_MASK) {
489                                         /* Bank is enabled */
490                                         membase = get_membase(bxcr_num);
491                                         pass = short_mem_test(membase);
492                                 } /* if bank enabled */
493                         } /* for bxcr_num */
494
495                         /* If this value passed update RFFD windows */
496                         if (pass && !in_window) { /* at the start of window */
497                                 in_window = 1;
498                                 curr_win_min.rffd = curr_win_max.rffd = rffd;
499                                 curr_win_min.rqfd = curr_win_max.rqfd = rqfd;
500                                 mfsdram(SDRAM_RDCC, rdcc); /*record this value*/
501                         } else if (!pass && in_window) { /* at end of window */
502                                 in_window = 0;
503                         } else if (pass && in_window) { /* within the window */
504                                 curr_win_max.rffd = rffd;
505                                 curr_win_max.rqfd = rqfd;
506                         }
507                         /* else if (!pass && !in_window)
508                                 skip - no pass, not currently in a window */
509
510                         if (in_window) {
511                                 if ((curr_win_max.rffd - curr_win_min.rffd) >
512                                     (best_win_max.rffd - best_win_min.rffd)) {
513                                         best_win_min.rffd = curr_win_min.rffd;
514                                         best_win_max.rffd = curr_win_max.rffd;
515
516                                         best_win_min.rqfd = curr_win_min.rqfd;
517                                         best_win_max.rqfd = curr_win_max.rqfd;
518                                         cal->rdcc         = rdcc;
519                                 }
520                                 passed = 1;
521                         }
522                 } /* RFDC.RFFD */
523
524                 /*
525                  * save-off the best window results of the RFDC.RFFD
526                  * for this RQDC.RQFD setting
527                  */
528                 /*
529                  * if (just ended RFDC.RFDC loop pass window) >
530                  *      (prior RFDC.RFFD loop pass window)
531                  */
532                 if ((best_win_max.rffd - best_win_min.rffd) >
533                     (loop_win_max.rffd - loop_win_min.rffd)) {
534                         loop_win_min.rffd = best_win_min.rffd;
535                         loop_win_max.rffd = best_win_max.rffd;
536                         loop_win_min.rqfd = rqfd;
537                         loop_win_max.rqfd = rqfd;
538                         debug("RQFD.min 0x%08x, RQFD.max 0x%08x, "
539                               "RFFD.min 0x%08x, RFFD.max 0x%08x\n",
540                                         loop_win_min.rqfd, loop_win_max.rqfd,
541                                         loop_win_min.rffd, loop_win_max.rffd);
542                 }
543         } /* RQDC.RQFD */
544
545         putc('\b');
546
547         debug("\n");
548
549         if ((loop_win_min.rffd == 0) && (loop_win_max.rffd == 0) &&
550             (best_win_min.rffd == 0) && (best_win_max.rffd == 0) &&
551             (best_win_min.rqfd == 0) && (best_win_max.rqfd == 0)) {
552                 passed = 0;
553         }
554
555         /*
556          * Need to program RQDC before RFDC.
557          */
558         debug("<%s> RQFD Min: 0x%x\n", __func__, loop_win_min.rqfd);
559         debug("<%s> RQFD Max: 0x%x\n", __func__, loop_win_max.rqfd);
560         rqfd_average = loop_win_max.rqfd;
561
562         if (rqfd_average < 0)
563                 rqfd_average = 0;
564
565         if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
566                 rqfd_average = SDRAM_RQDC_RQFD_MAX;
567
568         debug("<%s> RFFD average: 0x%08x\n", __func__, rqfd_average);
569         mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
570                                 SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
571
572         debug("<%s> RFFD Min: 0x%08x\n", __func__, loop_win_min.rffd);
573         debug("<%s> RFFD Max: 0x%08x\n", __func__, loop_win_max.rffd);
574         rffd_average = ((loop_win_min.rffd + loop_win_max.rffd) / 2);
575
576         if (rffd_average < 0)
577                 rffd_average = 0;
578
579         if (rffd_average > SDRAM_RFDC_RFFD_MAX)
580                 rffd_average = SDRAM_RFDC_RFFD_MAX;
581
582         debug("<%s> RFFD average: 0x%08x\n", __func__, rffd_average);
583         mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
584
585         /* if something passed, then return the size of the largest window */
586         if (passed != 0) {
587                 passed          = loop_win_max.rffd - loop_win_min.rffd;
588                 cal->rqfd       = rqfd_average;
589                 cal->rffd       = rffd_average;
590                 cal->rffd_min   = loop_win_min.rffd;
591                 cal->rffd_max   = loop_win_max.rffd;
592         }
593
594         return (u32)passed;
595 }
596
597 #else   /* !defined(CONFIG_PPC4xx_DDR_METHOD_A) */
598
599 /*-----------------------------------------------------------------------------+
600 | program_DQS_calibration_methodB.
601 +-----------------------------------------------------------------------------*/
602 static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal)
603 {
604         u32 pass_result = 0;
605
606 #ifdef DEBUG
607         ulong temp;
608 #endif
609
610         /*
611          * Program RDCC register
612          * Read sample cycle auto-update enable
613          */
614         mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T2 | SDRAM_RDCC_RSAE_ENABLE);
615
616 #ifdef DEBUG
617         mfsdram(SDRAM_RDCC, temp);
618         debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
619 #endif
620
621         /*
622          * Program RQDC register
623          * Internal DQS delay mechanism enable
624          */
625         mtsdram(SDRAM_RQDC,
626 #if defined(CONFIG_DDR_RQDC_START_VAL)
627                         SDRAM_RQDC_RQDE_ENABLE |
628                             SDRAM_RQDC_RQFD_ENCODE(CONFIG_DDR_RQDC_START_VAL));
629 #else
630                         SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x38));
631 #endif
632
633 #ifdef DEBUG
634         mfsdram(SDRAM_RQDC, temp);
635         debug("<%s>SDRAM_RQDC=0x%08x\n", __func__, temp);
636 #endif
637
638         /*
639          * Program RFDC register
640          * Set Feedback Fractional Oversample
641          * Auto-detect read sample cycle enable
642          */
643         mtsdram(SDRAM_RFDC,     SDRAM_RFDC_ARSE_ENABLE |
644                                 SDRAM_RFDC_RFOS_ENCODE(0) |
645                                 SDRAM_RFDC_RFFD_ENCODE(0));
646
647 #ifdef DEBUG
648         mfsdram(SDRAM_RFDC, temp);
649         debug("<%s>SDRAM_RFDC=0x%08x\n", __func__, temp);
650 #endif
651
652         pass_result = DQS_calibration_methodB(ddrcal);
653
654         return pass_result;
655 }
656
657 /*
658  * DQS_calibration_methodB()
659  *
660  * Autocalibration Method B
661  *
662  * ARRAY [Entire DQS Range] DQS_Valid_Window ;       initialized to all zeros
663  * ARRAY [Entire Feedback Range] FDBK_Valid_Window;  initialized to all zeros
664  * MEMWRITE(addr, expected_data);
665  * Initialialize the DQS delay to 80 degrees (MCIF0_RRQDC[RQFD]=0x38).
666  *
667  *  for (j = 0; j < Entire Feedback Range; j++) {
668  *      MEMREAD(addr, actual_data);
669  *       if (actual_data == expected_data) {
670  *           FDBK_Valid_Window[j] = 1;
671  *       }
672  * }
673  *
674  * Set MCIF0_RFDC[RFFD] to the middle of the FDBK_Valid_Window.
675  *
676  * for (i = 0; i < Entire DQS Range; i++) {
677  *     MEMREAD(addr, actual_data);
678  *     if (actual_data == expected_data) {
679  *         DQS_Valid_Window[i] = 1;
680  *      }
681  * }
682  *
683  * Set MCIF0_RRQDC[RQFD] to the middle of the DQS_Valid_Window.
684  */
685 /*-----------------------------------------------------------------------------+
686 | DQS_calibration_methodB.
687 +-----------------------------------------------------------------------------*/
688 static u32 DQS_calibration_methodB(struct ddrautocal *cal)
689 {
690         ulong rfdc_reg;
691         ulong rffd;
692
693         ulong rqdc_reg;
694         ulong rqfd;
695
696         ulong rdcc;
697
698         u32 *membase;
699         ulong bxcf;
700         int rqfd_average;
701         int bxcr_num;
702         int rffd_average;
703         int pass;
704         uint passed = 0;
705
706         int in_window;
707         u32 curr_win_min, curr_win_max;
708         u32 best_win_min, best_win_max;
709         u32 size = 0;
710
711         /*------------------------------------------------------------------
712          | Test to determine the best read clock delay tuning bits.
713          |
714          | Before the DDR controller can be used, the read clock delay needs to
715          | be set.  This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].
716          | This value cannot be hardcoded into the program because it changes
717          | depending on the board's setup and environment.
718          | To do this, all delay values are tested to see if they
719          | work or not.  By doing this, you get groups of fails with groups of
720          | passing values.  The idea is to find the start and end of a passing
721          | window and take the center of it to use as the read clock delay.
722          |
723          | A failure has to be seen first so that when we hit a pass, we know
724          | that it is truely the start of the window.  If we get passing values
725          | to start off with, we don't know if we are at the start of the window
726          |
727          | The code assumes that a failure will always be found.
728          | If a failure is not found, there is no easy way to get the middle
729          | of the passing window.  I guess we can pretty much pick any value
730          | but some values will be better than others.  Since the lowest speed
731          | we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
732          | from experimentation it is safe to say you will always have a failure
733          +-----------------------------------------------------------------*/
734
735         debug("\n\n");
736
737         in_window = 0;
738         rdcc = 0;
739
740         curr_win_min = curr_win_max = 0;
741         best_win_min = best_win_max = 0;
742         for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
743                 mfsdram(SDRAM_RFDC, rfdc_reg);
744                 rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
745                 mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
746
747                 pass = 1;
748                 for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
749                         mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
750
751                         /* Banks enabled */
752                         if (bxcf & SDRAM_BXCF_M_BE_MASK) {
753                                 /* Bank is enabled */
754                                 membase = get_membase(bxcr_num);
755                                 pass &= short_mem_test(membase);
756                         } /* if bank enabled */
757                 } /* for bxcf_num */
758
759                 /* If this value passed */
760                 if (pass && !in_window) {       /* start of passing window */
761                         in_window = 1;
762                         curr_win_min = curr_win_max = rffd;
763                         mfsdram(SDRAM_RDCC, rdcc);      /* record this value */
764                 } else if (!pass && in_window) {        /* end passing window */
765                         in_window = 0;
766                 } else if (pass && in_window) { /* within the passing window */
767                         curr_win_max = rffd;
768                 }
769
770                 if (in_window) {
771                         if ((curr_win_max - curr_win_min) >
772                             (best_win_max - best_win_min)) {
773                                 best_win_min = curr_win_min;
774                                 best_win_max = curr_win_max;
775                                 cal->rdcc    = rdcc;
776                         }
777                         passed = 1;
778                 }
779         } /* for rffd */
780
781         if ((best_win_min == 0) && (best_win_max == 0))
782                 passed = 0;
783         else
784                 size = best_win_max - best_win_min;
785
786         debug("RFFD Min: 0x%x\n", best_win_min);
787         debug("RFFD Max: 0x%x\n", best_win_max);
788         rffd_average = ((best_win_min + best_win_max) / 2);
789
790         cal->rffd_min = best_win_min;
791         cal->rffd_max = best_win_max;
792
793         if (rffd_average < 0)
794                 rffd_average = 0;
795
796         if (rffd_average > SDRAM_RFDC_RFFD_MAX)
797                 rffd_average = SDRAM_RFDC_RFFD_MAX;
798
799         mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
800
801         rffd = rffd_average;
802         in_window = 0;
803
804         curr_win_min = curr_win_max = 0;
805         best_win_min = best_win_max = 0;
806         for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
807                 mfsdram(SDRAM_RQDC, rqdc_reg);
808                 rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
809                 mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
810
811                 pass = 1;
812                 for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
813
814                         mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
815
816                         /* Banks enabled */
817                         if (bxcf & SDRAM_BXCF_M_BE_MASK) {
818                                 /* Bank is enabled */
819                                 membase = get_membase(bxcr_num);
820                                 pass &= short_mem_test(membase);
821                         } /* if bank enabled */
822                 } /* for bxcf_num */
823
824                 /* If this value passed */
825                 if (pass && !in_window) {
826                         in_window = 1;
827                         curr_win_min = curr_win_max = rqfd;
828                 } else if (!pass && in_window) {
829                         in_window = 0;
830                 } else if (pass && in_window) {
831                         curr_win_max = rqfd;
832                 }
833
834                 if (in_window) {
835                         if ((curr_win_max - curr_win_min) >
836                             (best_win_max - best_win_min)) {
837                                 best_win_min = curr_win_min;
838                                 best_win_max = curr_win_max;
839                         }
840                         passed = 1;
841                 }
842         } /* for rqfd */
843
844         if ((best_win_min == 0) && (best_win_max == 0))
845                 passed = 0;
846
847         debug("RQFD Min: 0x%x\n", best_win_min);
848         debug("RQFD Max: 0x%x\n", best_win_max);
849         rqfd_average = ((best_win_min + best_win_max) / 2);
850
851         if (rqfd_average < 0)
852                 rqfd_average = 0;
853
854         if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
855                 rqfd_average = SDRAM_RQDC_RQFD_MAX;
856
857         mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
858                                         SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
859
860         mfsdram(SDRAM_RQDC, rqdc_reg);
861         mfsdram(SDRAM_RFDC, rfdc_reg);
862
863         /*
864          * Need to program RQDC before RFDC. The value is read above.
865          * That is the reason why auto cal not work.
866          * See, comments below.
867          */
868         mtsdram(SDRAM_RQDC, rqdc_reg);
869         mtsdram(SDRAM_RFDC, rfdc_reg);
870
871         debug("RQDC: 0x%08X\n", rqdc_reg);
872         debug("RFDC: 0x%08X\n", rfdc_reg);
873
874         /* if something passed, then return the size of the largest window */
875         if (passed != 0) {
876                 passed          = size;
877                 cal->rqfd       = rqfd_average;
878                 cal->rffd       = rffd_average;
879         }
880
881         return (uint)passed;
882 }
883 #endif /* defined(CONFIG_PPC4xx_DDR_METHOD_A) */
884
885 /*
886  * Default table for DDR auto-calibration of all
887  * possible WRDTR and CLKTR values.
888  * Table format is:
889  *       {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]}
890  *
891  * Table is terminated with {-1, -1} value pair.
892  *
893  * Board vendors can specify their own board specific subset of
894  * known working {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} value
895  * pairs via a board defined ddr_scan_option() function.
896  */
897 struct sdram_timing full_scan_options[] = {
898         {0, 0}, {0, 1}, {0, 2}, {0, 3},
899         {1, 0}, {1, 1}, {1, 2}, {1, 3},
900         {2, 0}, {2, 1}, {2, 2}, {2, 3},
901         {3, 0}, {3, 1}, {3, 2}, {3, 3},
902         {4, 0}, {4, 1}, {4, 2}, {4, 3},
903         {5, 0}, {5, 1}, {5, 2}, {5, 3},
904         {6, 0}, {6, 1}, {6, 2}, {6, 3},
905         {-1, -1}
906 };
907
908 /*---------------------------------------------------------------------------+
909 | DQS_calibration.
910 +----------------------------------------------------------------------------*/
911 u32 DQS_autocalibration(void)
912 {
913         u32 wdtr;
914         u32 clkp;
915         u32 result = 0;
916         u32 best_result = 0;
917         u32 best_rdcc;
918         struct ddrautocal ddrcal;
919         struct autocal_clks tcal;
920         ulong rfdc_reg;
921         ulong rqdc_reg;
922         u32 val;
923         int verbose_lvl = 0;
924         char *str;
925         char slash[] = "\\|/-\\|/-";
926         int loopi = 0;
927         struct sdram_timing *scan_list;
928
929 #if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
930         int i;
931         char tmp[64];   /* long enough for environment variables */
932 #endif
933
934         memset(&tcal, 0, sizeof(tcal));
935
936         ddr_scan_option((ulong)full_scan_options);
937
938         scan_list =
939               (struct sdram_timing *)ddr_scan_option((ulong)full_scan_options);
940
941         mfsdram(SDRAM_MCOPT1, val);
942         if ((val & SDRAM_MCOPT1_MCHK_CHK_REP) == SDRAM_MCOPT1_MCHK_CHK_REP)
943                 str = "ECC Auto calibration -";
944         else
945                 str = "Auto calibration -";
946
947         puts(str);
948
949 #if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
950         i = getenv_r("autocalib", tmp, sizeof(tmp));
951         if (i < 0)
952                 strcpy(tmp, CONFIG_AUTOCALIB);
953
954         if (strcmp(tmp, "final") == 0) {
955                 /* display the final autocalibration results only */
956                 verbose_lvl = 1;
957         } else if (strcmp(tmp, "loop") == 0) {
958                 /* display summary autocalibration info per iteration */
959                 verbose_lvl = 2;
960         } else if (strcmp(tmp, "display") == 0) {
961                 /* display full debug autocalibration window info. */
962                 verbose_lvl = 3;
963         }
964 #endif /* (DEBUG_PPC4xx_DDR_AUTOCALIBRATION) */
965
966         best_rdcc = (SDRAM_RDCC_RDSS_T4 >> 30);
967
968         while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) {
969                 wdtr = scan_list->wrdtr;
970                 clkp = scan_list->clktr;
971
972                 mfsdram(SDRAM_WRDTR, val);
973                 val &= ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK);
974                 mtsdram(SDRAM_WRDTR, (val |
975                         ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (wdtr << 25))));
976
977                 mtsdram(SDRAM_CLKTR, clkp << 30);
978
979                 putc('\b');
980                 putc(slash[loopi++ % 8]);
981
982 #ifdef DEBUG
983                 debug("\n");
984                 debug("*** --------------\n");
985                 mfsdram(SDRAM_WRDTR, val);
986                 debug("*** SDRAM_WRDTR set to 0x%08x\n", val);
987                 mfsdram(SDRAM_CLKTR, val);
988                 debug("*** SDRAM_CLKTR set to 0x%08x\n", val);
989 #endif
990
991                 debug("\n");
992                 if (verbose_lvl > 2) {
993                         printf("*** SDRAM_WRDTR (wdtr) set to %d\n", wdtr);
994                         printf("*** SDRAM_CLKTR (clkp) set to %d\n", clkp);
995                 }
996
997                 memset(&ddrcal, 0, sizeof(ddrcal));
998
999                 /*
1000                  * DQS calibration.
1001                  */
1002                 /*
1003                  * program_DQS_calibration_method[A|B]() returns 0 if no
1004                  * passing RFDC.[RFFD] window is found or returns the size
1005                  * of the best passing window; in the case of a found passing
1006                  * window, the ddrcal will contain the values of the best
1007                  * window RQDC.[RQFD] and RFDC.[RFFD].
1008                  */
1009
1010                 /*
1011                  * Call PPC4xx SDRAM DDR autocalibration methodA or methodB.
1012                  * Default is methodB.
1013                  * Defined the autocalibration method in the board specific
1014                  * header file.
1015                  * Please see include/configs/kilauea.h for an example for
1016                  * a board specific implementation.
1017                  */
1018 #if defined(CONFIG_PPC4xx_DDR_METHOD_A)
1019                 result = program_DQS_calibration_methodA(&ddrcal);
1020 #else
1021                 result = program_DQS_calibration_methodB(&ddrcal);
1022 #endif
1023
1024                 sync();
1025
1026                 /*
1027                  * Clear potential errors resulting from auto-calibration.
1028                  * If not done, then we could get an interrupt later on when
1029                  * exceptions are enabled.
1030                  */
1031                 set_mcsr(get_mcsr());
1032
1033                 val = ddrcal.rdcc;      /* RDCC from the best passing window */
1034
1035                 udelay(100);
1036
1037                 if (verbose_lvl > 1) {
1038                         char *tstr;
1039                         switch ((val >> 30)) {
1040                         case 0:
1041                                 if (result != 0)
1042                                         tstr = "T1";
1043                                 else
1044                                         tstr = "N/A";
1045                                 break;
1046                         case 1:
1047                                 tstr = "T2";
1048                                 break;
1049                         case 2:
1050                                 tstr = "T3";
1051                                 break;
1052                         case 3:
1053                                 tstr = "T4";
1054                                 break;
1055                         default:
1056                                 tstr = "unknown";
1057                                 break;
1058                         }
1059                         printf("** WRDTR(%d) CLKTR(%d), Wind (%d), best (%d), "
1060                                "max-min(0x%04x)(0x%04x), RDCC: %s\n",
1061                                 wdtr, clkp, result, best_result,
1062                                 ddrcal.rffd_min, ddrcal.rffd_max, tstr);
1063                 }
1064
1065                 /*
1066                  * The DQS calibration "result" is either "0"
1067                  * if no passing window was found, or is the
1068                  * size of the RFFD passing window.
1069                  */
1070                 if (result != 0) {
1071                         tcal.autocal.flags = 1;
1072                         debug("*** (%d)(%d) result passed window size: 0x%08x, "
1073                               "rqfd = 0x%08x, rffd = 0x%08x, rdcc = 0x%08x\n",
1074                                 wdtr, clkp, result, ddrcal.rqfd,
1075                                 ddrcal.rffd, ddrcal.rdcc);
1076                         /*
1077                          * Save the SDRAM_WRDTR and SDRAM_CLKTR
1078                          * settings for the largest returned
1079                          * RFFD passing window size.
1080                          */
1081                         if (result > best_result) {
1082                                 /*
1083                                  * want the lowest Read Sample Cycle Select
1084                                  */
1085                                 val = (val & SDRAM_RDCC_RDSS_MASK) >> 30;
1086                                 debug("*** (%d) (%d) current_rdcc, best_rdcc\n",
1087                                                         val, best_rdcc);
1088                                 if (val <= best_rdcc) {
1089                                         best_rdcc = val;
1090                                         tcal.clocks.wrdtr = wdtr;
1091                                         tcal.clocks.clktr = clkp;
1092                                         tcal.clocks.rdcc = (val << 30);
1093                                         tcal.autocal.rqfd = ddrcal.rqfd;
1094                                         tcal.autocal.rffd = ddrcal.rffd;
1095                                         best_result = result;
1096
1097                                         if (verbose_lvl > 2) {
1098                                                 printf("** (%d)(%d)  "
1099                                                        "best result: 0x%04x\n",
1100                                                         wdtr, clkp,
1101                                                         best_result);
1102                                                 printf("** (%d)(%d)  "
1103                                                        "best WRDTR: 0x%04x\n",
1104                                                         wdtr, clkp,
1105                                                         tcal.clocks.wrdtr);
1106                                                 printf("** (%d)(%d)  "
1107                                                        "best CLKTR: 0x%04x\n",
1108                                                         wdtr, clkp,
1109                                                         tcal.clocks.clktr);
1110                                                 printf("** (%d)(%d)  "
1111                                                        "best RQDC: 0x%04x\n",
1112                                                         wdtr, clkp,
1113                                                         tcal.autocal.rqfd);
1114                                                 printf("** (%d)(%d)  "
1115                                                        "best RFDC: 0x%04x\n",
1116                                                         wdtr, clkp,
1117                                                         tcal.autocal.rffd);
1118                                                 printf("** (%d)(%d)  "
1119                                                        "best RDCC: 0x%08x\n",
1120                                                         wdtr, clkp,
1121                                                         (u32)tcal.clocks.rdcc);
1122                                                 mfsdram(SDRAM_RTSR, val);
1123                                                 printf("** (%d)(%d)  best "
1124                                                        "loop RTSR: 0x%08x\n",
1125                                                         wdtr, clkp, val);
1126                                                 mfsdram(SDRAM_FCSR, val);
1127                                                 printf("** (%d)(%d)  best "
1128                                                        "loop FCSR: 0x%08x\n",
1129                                                         wdtr, clkp, val);
1130                                         }
1131                                 } /* if (val <= best_rdcc) */
1132                         } /* if (result >= best_result) */
1133                 } /* if (result != 0) */
1134                 scan_list++;
1135         } /* while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) */
1136
1137         if (tcal.autocal.flags == 1) {
1138                 if (verbose_lvl > 0) {
1139                         printf("*** --------------\n");
1140                         printf("*** best_result window size: %d\n",
1141                                                         best_result);
1142                         printf("*** best_result WRDTR: 0x%04x\n",
1143                                                         tcal.clocks.wrdtr);
1144                         printf("*** best_result CLKTR: 0x%04x\n",
1145                                                         tcal.clocks.clktr);
1146                         printf("*** best_result RQFD: 0x%04x\n",
1147                                                         tcal.autocal.rqfd);
1148                         printf("*** best_result RFFD: 0x%04x\n",
1149                                                         tcal.autocal.rffd);
1150                         printf("*** best_result RDCC: 0x%04x\n",
1151                                                         tcal.clocks.rdcc);
1152                         printf("*** --------------\n");
1153                         printf("\n");
1154                 }
1155
1156                 /*
1157                  * if got best passing result window, then lock in the
1158                  * best CLKTR, WRDTR, RQFD, and RFFD values
1159                  */
1160                 mfsdram(SDRAM_WRDTR, val);
1161                 mtsdram(SDRAM_WRDTR, (val &
1162                     ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) |
1163                     ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC |
1164                                         (tcal.clocks.wrdtr << 25)));
1165
1166                 mtsdram(SDRAM_CLKTR, tcal.clocks.clktr << 30);
1167
1168                 mfsdram(SDRAM_RQDC, rqdc_reg);
1169                 rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
1170                 mtsdram(SDRAM_RQDC, rqdc_reg |
1171                                 SDRAM_RQDC_RQFD_ENCODE(tcal.autocal.rqfd));
1172
1173                 mfsdram(SDRAM_RQDC, rqdc_reg);
1174                 debug("*** best_result: read value SDRAM_RQDC 0x%08x\n",
1175                                 rqdc_reg);
1176
1177                 mfsdram(SDRAM_RFDC, rfdc_reg);
1178                 rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
1179                 mtsdram(SDRAM_RFDC, rfdc_reg |
1180                                 SDRAM_RFDC_RFFD_ENCODE(tcal.autocal.rffd));
1181
1182                 mfsdram(SDRAM_RFDC, rfdc_reg);
1183                 debug("*** best_result: read value SDRAM_RFDC 0x%08x\n",
1184                                 rfdc_reg);
1185                 mfsdram(SDRAM_RDCC, val);
1186                 debug("***  SDRAM_RDCC 0x%08x\n", val);
1187         } else {
1188                 /*
1189                  * no valid windows were found
1190                  */
1191                 printf("DQS memory calibration window can not be determined, "
1192                        "terminating u-boot.\n");
1193                 ppc4xx_ibm_ddr2_register_dump();
1194                 spd_ddr_init_hang();
1195         }
1196
1197         blank_string(strlen(str));
1198
1199         return 0;
1200 }
1201 #else /* defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
1202 u32 DQS_autocalibration(void)
1203 {
1204         return 0;
1205 }
1206 #endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
1207 #endif /* defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */