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