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