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