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