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