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