uboot/drivers/ddr/marvell/axp/ddr3_dqs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) Marvell International Ltd. and its affiliates
   4 */
   5
   6#include <common.h>
   7#include <i2c.h>
   8#include <spl.h>
   9#include <asm/io.h>
  10#include <asm/arch/cpu.h>
  11#include <asm/arch/soc.h>
  12
  13#include "ddr3_hw_training.h"
  14
  15/*
  16 * Debug
  17 */
  18#define DEBUG_DQS_C(s, d, l) \
  19        DEBUG_DQS_S(s); DEBUG_DQS_D(d, l); DEBUG_DQS_S("\n")
  20#define DEBUG_DQS_FULL_C(s, d, l) \
  21        DEBUG_DQS_FULL_S(s); DEBUG_DQS_FULL_D(d, l); DEBUG_DQS_FULL_S("\n")
  22#define DEBUG_DQS_RESULTS_C(s, d, l) \
  23        DEBUG_DQS_RESULTS_S(s); DEBUG_DQS_RESULTS_D(d, l); DEBUG_DQS_RESULTS_S("\n")
  24#define DEBUG_PER_DQ_C(s, d, l) \
  25        puts(s); printf("%x", d); puts("\n")
  26
  27#define DEBUG_DQS_RESULTS_S(s) \
  28        debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
  29#define DEBUG_DQS_RESULTS_D(d, l) \
  30        debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
  31
  32#define DEBUG_PER_DQ_S(s) \
  33        debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%s", s)
  34#define DEBUG_PER_DQ_D(d, l) \
  35        debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%x", d)
  36#define DEBUG_PER_DQ_DD(d, l) \
  37        debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%d", d)
  38
  39#ifdef MV_DEBUG_DQS
  40#define DEBUG_DQS_S(s)                  puts(s)
  41#define DEBUG_DQS_D(d, l)               printf("%x", d)
  42#else
  43#define DEBUG_DQS_S(s)
  44#define DEBUG_DQS_D(d, l)
  45#endif
  46
  47#ifdef MV_DEBUG_DQS_FULL
  48#define DEBUG_DQS_FULL_S(s)             puts(s)
  49#define DEBUG_DQS_FULL_D(d, l)          printf("%x", d)
  50#else
  51#define DEBUG_DQS_FULL_S(s)
  52#define DEBUG_DQS_FULL_D(d, l)
  53#endif
  54
  55/* State machine for centralization - find low & high limit */
  56enum {
  57        PUP_ADLL_LIMITS_STATE_FAIL,
  58        PUP_ADLL_LIMITS_STATE_PASS,
  59        PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS,
  60};
  61
  62/* Hold centralization low results */
  63static int centralization_low_limit[MAX_PUP_NUM] = { 0 };
  64/* Hold centralization high results */
  65static int centralization_high_limit[MAX_PUP_NUM] = { 0 };
  66
  67int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx);
  68int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
  69                          int *size_valid);
  70static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
  71                            int is_tx);
  72int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
  73                              int is_tx, u32 special_pattern_pup);
  74int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
  75                                   int is_tx, u32 special_pattern_pup);
  76int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
  77                                    int is_tx);
  78
  79#ifdef MV88F78X60
  80extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
  81extern u32 killer_pattern_64b[DQ_NUM][LEN_SPECIAL_PATTERN];
  82extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
  83#else
  84extern u32 killer_pattern[DQ_NUM][LEN_16BIT_KILLER_PATTERN];
  85extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
  86#if defined(MV88F672X)
  87extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
  88#endif
  89#endif
  90extern u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN];
  91
  92static u32 *ddr3_dqs_choose_pattern(MV_DRAM_INFO *dram_info, u32 victim_dq)
  93{
  94        u32 *pattern_ptr;
  95
  96        /* Choose pattern */
  97        switch (dram_info->ddr_width) {
  98#if defined(MV88F672X)
  99        case 16:
 100                pattern_ptr = (u32 *)&killer_pattern[victim_dq];
 101                break;
 102#endif
 103        case 32:
 104                pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
 105                break;
 106#if defined(MV88F78X60)
 107        case 64:
 108                pattern_ptr = (u32 *)&killer_pattern_64b[victim_dq];
 109                break;
 110#endif
 111        default:
 112#if defined(MV88F78X60)
 113                pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
 114#else
 115                pattern_ptr = (u32 *)&killer_pattern[victim_dq];
 116#endif
 117                break;
 118        }
 119
 120        return pattern_ptr;
 121}
 122
 123/*
 124 * Name:     ddr3_dqs_centralization_rx
 125 * Desc:     Execute the DQS centralization RX phase.
 126 * Args:     dram_info
 127 * Notes:
 128 * Returns:  MV_OK if success, other error code if fail.
 129 */
 130int ddr3_dqs_centralization_rx(MV_DRAM_INFO *dram_info)
 131{
 132        u32 cs, ecc, reg;
 133        int status;
 134
 135        DEBUG_DQS_S("DDR3 - DQS Centralization RX - Starting procedure\n");
 136
 137        /* Enable SW override */
 138        reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
 139                (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
 140
 141        /* [0] = 1 - Enable SW override  */
 142        /* 0x15B8 - Training SW 2 Register */
 143        reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
 144        DEBUG_DQS_S("DDR3 - DQS Centralization RX - SW Override Enabled\n");
 145
 146        reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
 147        reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
 148
 149        /* Loop for each CS */
 150        for (cs = 0; cs < MAX_CS; cs++) {
 151                if (dram_info->cs_ena & (1 << cs)) {
 152                        DEBUG_DQS_FULL_C("DDR3 - DQS Centralization RX - CS - ",
 153                                         (u32) cs, 1);
 154
 155                        for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
 156
 157                                /* ECC Support - Switch ECC Mux on ecc=1 */
 158                                reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
 159                                        ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
 160                                reg |= (dram_info->ecc_ena *
 161                                        ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
 162                                reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
 163
 164                                if (ecc)
 165                                        DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Enabled\n");
 166                                else
 167                                        DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Disabled\n");
 168
 169                                DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Find all limits\n");
 170
 171                                status = ddr3_find_adll_limits(dram_info, cs,
 172                                                               ecc, 0);
 173                                if (MV_OK != status)
 174                                        return status;
 175
 176                                DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Start calculating center\n");
 177
 178                                status = ddr3_center_calc(dram_info, cs, ecc,
 179                                                          0);
 180                                if (MV_OK != status)
 181                                        return status;
 182                        }
 183                }
 184        }
 185
 186        /* ECC Support - Disable ECC MUX */
 187        reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
 188                ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
 189        reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
 190
 191        /* Disable SW override - Must be in a different stage */
 192        /* [0]=0 - Enable SW override  */
 193        reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
 194        reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
 195        /* 0x15B8 - Training SW 2 Register */
 196        reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
 197
 198        reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
 199                (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
 200        reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
 201
 202        return MV_OK;
 203}
 204
 205/*
 206 * Name:     ddr3_dqs_centralization_tx
 207 * Desc:     Execute the DQS centralization TX phase.
 208 * Args:     dram_info
 209 * Notes:
 210 * Returns:  MV_OK if success, other error code if fail.
 211 */
 212int ddr3_dqs_centralization_tx(MV_DRAM_INFO *dram_info)
 213{
 214        u32 cs, ecc, reg;
 215        int status;
 216
 217        DEBUG_DQS_S("DDR3 - DQS Centralization TX - Starting procedure\n");
 218
 219        /* Enable SW override */
 220        reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
 221                (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
 222
 223        /* [0] = 1 - Enable SW override  */
 224        /* 0x15B8 - Training SW 2 Register */
 225        reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
 226        DEBUG_DQS_S("DDR3 - DQS Centralization TX - SW Override Enabled\n");
 227
 228        reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
 229        reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
 230
 231        /* Loop for each CS */
 232        for (cs = 0; cs < MAX_CS; cs++) {
 233                if (dram_info->cs_ena & (1 << cs)) {
 234                        DEBUG_DQS_FULL_C("DDR3 - DQS Centralization TX - CS - ",
 235                                         (u32) cs, 1);
 236                        for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
 237                                /* ECC Support - Switch ECC Mux on ecc=1 */
 238                                reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
 239                                        ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
 240                                reg |= (dram_info->ecc_ena *
 241                                        ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
 242                                reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
 243
 244                                if (ecc)
 245                                        DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Enabled\n");
 246                                else
 247                                        DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Disabled\n");
 248
 249                                DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Find all limits\n");
 250
 251                                status = ddr3_find_adll_limits(dram_info, cs,
 252                                                               ecc, 1);
 253                                if (MV_OK != status)
 254                                        return status;
 255
 256                                DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Start calculating center\n");
 257
 258                                status = ddr3_center_calc(dram_info, cs, ecc,
 259                                                          1);
 260                                if (MV_OK != status)
 261                                        return status;
 262                        }
 263                }
 264        }
 265
 266        /* ECC Support - Disable ECC MUX */
 267        reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
 268                ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
 269        reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
 270
 271        /* Disable SW override - Must be in a different stage */
 272        /* [0]=0 - Enable SW override  */
 273        reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
 274        reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
 275        /* 0x15B8 - Training SW 2 Register */
 276        reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
 277
 278        reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
 279                (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
 280        reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
 281
 282        return MV_OK;
 283}
 284
 285/*
 286 * Name:     ddr3_find_adll_limits
 287 * Desc:     Execute the Find ADLL limits phase.
 288 * Args:     dram_info
 289 *           cs
 290 *           ecc_ena
 291 *           is_tx             Indicate whether Rx or Tx
 292 * Notes:
 293 * Returns:  MV_OK if success, other error code if fail.
 294 */
 295int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx)
 296{
 297        u32 victim_dq, pup, tmp;
 298        u32 adll_addr;
 299        u32 max_pup;            /* maximal pup index */
 300        u32 pup_mask = 0;
 301        u32 unlock_pup;         /* bit array of un locked pups */
 302        u32 new_unlock_pup;     /* bit array of compare failed pups */
 303        u32 curr_adll;
 304        u32 adll_start_val;     /* adll start loop value - for rx or tx limit */
 305        u32 high_limit; /* holds found High Limit */
 306        u32 low_limit;          /* holds found Low Limit */
 307        int win_valid;
 308        int update_win;
 309        u32 sdram_offset;
 310        u32 uj, cs_count, cs_tmp, ii;
 311        u32 *pattern_ptr;
 312        u32 dq;
 313        u32 adll_end_val;       /* adll end of loop val - for rx or tx limit */
 314        u8 analog_pbs[DQ_NUM][MAX_PUP_NUM][DQ_NUM][2];
 315        u8 analog_pbs_sum[MAX_PUP_NUM][DQ_NUM][2];
 316        int pup_adll_limit_state[MAX_PUP_NUM];  /* hold state of each pup */
 317
 318        adll_addr = ((is_tx == 1) ? PUP_DQS_WR : PUP_DQS_RD);
 319        adll_end_val = ((is_tx == 1) ? ADLL_MIN : ADLL_MAX);
 320        adll_start_val = ((is_tx == 1) ? ADLL_MAX : ADLL_MIN);
 321        max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
 322
 323        DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - Starting Find ADLL Limits\n");
 324
 325        /* init the array */
 326        for (pup = 0; pup < max_pup; pup++) {
 327                centralization_low_limit[pup] = ADLL_MIN;
 328                centralization_high_limit[pup] = ADLL_MAX;
 329        }
 330
 331        /* Killer Pattern */
 332        cs_count = 0;
 333        for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
 334                if (dram_info->cs_ena & (1 << cs_tmp))
 335                        cs_count++;
 336        }
 337        sdram_offset = cs_count * (SDRAM_CS_SIZE + 1);
 338        sdram_offset += ((is_tx == 1) ?
 339                         SDRAM_DQS_TX_OFFS : SDRAM_DQS_RX_OFFS);
 340
 341        /* Prepare pup masks */
 342        for (pup = 0; pup < max_pup; pup++)
 343                pup_mask |= (1 << pup);
 344
 345        for (pup = 0; pup < max_pup; pup++) {
 346                for (dq = 0; dq < DQ_NUM; dq++) {
 347                        analog_pbs_sum[pup][dq][0] = adll_start_val;
 348                        analog_pbs_sum[pup][dq][1] = adll_end_val;
 349                }
 350        }
 351
 352        /* Loop - use different pattern for each victim_dq */
 353        for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
 354                DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Victim DQ - ",
 355                                 (u32)victim_dq, 1);
 356                /*
 357                 * The pups 3 bit arrays represent state machine. with
 358                 * 3 stages for each pup.
 359                 * 1. fail and didn't get pass in earlier compares.
 360                 * 2. pass compare
 361                 * 3. fail after pass - end state.
 362                 * The window limits are the adll values where the adll
 363                 * was in the pass stage.
 364                 */
 365
 366                /* Set all states to Fail (1st state) */
 367                for (pup = 0; pup < max_pup; pup++)
 368                        pup_adll_limit_state[pup] = PUP_ADLL_LIMITS_STATE_FAIL;
 369
 370                /* Set current valid pups */
 371                unlock_pup = pup_mask;
 372
 373                /* Set ADLL to start value */
 374                curr_adll = adll_start_val;
 375
 376#if defined(MV88F78X60)
 377                for (pup = 0; pup < max_pup; pup++) {
 378                        for (dq = 0; dq < DQ_NUM; dq++) {
 379                                analog_pbs[victim_dq][pup][dq][0] =
 380                                        adll_start_val;
 381                                analog_pbs[victim_dq][pup][dq][1] =
 382                                        adll_end_val;
 383                                per_bit_data[pup][dq] = 0;
 384                        }
 385                }
 386#endif
 387
 388                for (uj = 0; uj < ADLL_MAX; uj++) {
 389                        DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Setting ADLL to ",
 390                                         curr_adll, 2);
 391                        for (pup = 0; pup < max_pup; pup++) {
 392                                if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
 393                                        tmp = ((is_tx == 1) ? curr_adll +
 394                                               dram_info->wl_val[cs]
 395                                               [pup * (1 - ecc) + ecc * ECC_PUP]
 396                                               [D] : curr_adll);
 397                                        ddr3_write_pup_reg(adll_addr, cs, pup +
 398                                                (ecc * ECC_PUP), 0, tmp);
 399                                }
 400                        }
 401
 402                        /* Choose pattern */
 403                        pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
 404                                                              victim_dq);
 405
 406                        /* '1' - means pup failed, '0' - means pup pass */
 407                        new_unlock_pup = 0;
 408
 409                        /* Read and compare results for Victim_DQ# */
 410                        for (ii = 0; ii < 3; ii++) {
 411                                u32 tmp = 0;
 412                                if (MV_OK != ddr3_sdram_dqs_compare(dram_info,
 413                                                           unlock_pup, &tmp,
 414                                                           pattern_ptr,
 415                                                           LEN_KILLER_PATTERN,
 416                                                           sdram_offset +
 417                                                           LEN_KILLER_PATTERN *
 418                                                           4 * victim_dq,
 419                                                           is_tx, 0, NULL,
 420                                                           0))
 421                                        return MV_DDR3_TRAINING_ERR_DRAM_COMPARE;
 422
 423                                new_unlock_pup |= tmp;
 424                        }
 425
 426                        pup = 0;
 427                        DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - UnlockPup: ",
 428                                         unlock_pup, 2);
 429                        DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - NewUnlockPup: ",
 430                                         new_unlock_pup, 2);
 431
 432                        /* Update pup state */
 433                        for (pup = 0; pup < max_pup; pup++) {
 434                                if (IS_PUP_ACTIVE(unlock_pup, pup) == 0) {
 435                                        DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Skipping pup ",
 436                                                         pup, 1);
 437                                        continue;
 438                                }
 439
 440                                /*
 441                                 * Still didn't find the window limit of the pup
 442                                 */
 443                                if (IS_PUP_ACTIVE(new_unlock_pup, pup) == 1) {
 444                                        /* Current compare result == fail */
 445                                        if (pup_adll_limit_state[pup] ==
 446                                            PUP_ADLL_LIMITS_STATE_PASS) {
 447                                                /*
 448                                                 * If now it failed but passed
 449                                                 * earlier
 450                                                 */
 451                                                DEBUG_DQS_S("DDR3 - DQS Find Limits - PASS to FAIL: CS - ");
 452                                                DEBUG_DQS_D(cs, 1);
 453                                                DEBUG_DQS_S(", DQ - ");
 454                                                DEBUG_DQS_D(victim_dq, 1);
 455                                                DEBUG_DQS_S(", Pup - ");
 456                                                DEBUG_DQS_D(pup, 1);
 457                                                DEBUG_DQS_S(", ADLL - ");
 458                                                DEBUG_DQS_D(curr_adll, 2);
 459                                                DEBUG_DQS_S("\n");
 460
 461#if defined(MV88F78X60)
 462                                                for (dq = 0; dq < DQ_NUM; dq++) {
 463                                                        if ((analog_pbs[victim_dq][pup][dq][0] != adll_start_val)
 464                                                            && (analog_pbs[victim_dq][pup]
 465                                                                [dq][1] == adll_end_val))
 466                                                                analog_pbs
 467                                                                        [victim_dq]
 468                                                                        [pup][dq]
 469                                                                        [1] =
 470                                                                        curr_adll;
 471                                                }
 472#endif
 473                                                win_valid = 1;
 474                                                update_win = 0;
 475
 476                                                /* Keep min / max limit value */
 477                                                if (is_tx == 0) {
 478                                                        /* RX - found upper limit */
 479                                                        if (centralization_high_limit[pup] >
 480                                                            (curr_adll - 1)) {
 481                                                                high_limit =
 482                                                                        curr_adll - 1;
 483                                                                low_limit =
 484                                                                        centralization_low_limit[pup];
 485                                                                update_win = 1;
 486                                                        }
 487                                                } else {
 488                                                        /* TX - found lower limit */
 489                                                        if (centralization_low_limit[pup] < (curr_adll + 1)) {
 490                                                                high_limit =
 491                                                                        centralization_high_limit
 492                                                                        [pup];
 493                                                                low_limit =
 494                                                                        curr_adll + 1;
 495                                                                update_win =
 496                                                                        1;
 497                                                        }
 498                                                }
 499
 500                                                if (update_win == 1) {
 501                                                        /*
 502                                                         * Before updating
 503                                                         * window limits we need
 504                                                         * to check that the
 505                                                         * limits are valid
 506                                                         */
 507                                                        if (MV_OK !=
 508                                                            ddr3_check_window_limits
 509                                                            (pup, high_limit,
 510                                                             low_limit, is_tx,
 511                                                             &win_valid))
 512                                                                return MV_DDR3_TRAINING_ERR_WIN_LIMITS;
 513
 514                                                        if (win_valid == 1) {
 515                                                                /*
 516                                                                 * Window limits
 517                                                                 * should be
 518                                                                 * updated
 519                                                                 */
 520                                                                centralization_low_limit
 521                                                                        [pup] =
 522                                                                        low_limit;
 523                                                                centralization_high_limit
 524                                                                        [pup] =
 525                                                                        high_limit;
 526                                                        }
 527                                                }
 528
 529                                                if (win_valid == 1) {
 530                                                        /* Found end of window - lock the pup */
 531                                                        pup_adll_limit_state[pup] =
 532                                                                PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS;
 533                                                        unlock_pup &= ~(1 << pup);
 534                                                } else {
 535                                                        /* Probably false pass - reset status */
 536                                                        pup_adll_limit_state[pup] =
 537                                                                PUP_ADLL_LIMITS_STATE_FAIL;
 538
 539#if defined(MV88F78X60)
 540                                                        /* Clear logging array of win size (per Dq) */
 541                                                        for (dq = 0;
 542                                                             dq < DQ_NUM;
 543                                                             dq++) {
 544                                                                analog_pbs
 545                                                                        [victim_dq]
 546                                                                        [pup][dq]
 547                                                                        [0] =
 548                                                                        adll_start_val;
 549                                                                analog_pbs
 550                                                                        [victim_dq]
 551                                                                        [pup][dq]
 552                                                                        [1] =
 553                                                                        adll_end_val;
 554                                                                per_bit_data
 555                                                                        [pup][dq]
 556                                                                        = 0;
 557                                                        }
 558#endif
 559                                                }
 560                                        }
 561                                } else {
 562                                        /* Current compare result == pass */
 563                                        if (pup_adll_limit_state[pup] ==
 564                                            PUP_ADLL_LIMITS_STATE_FAIL) {
 565                                                /* If now it passed but failed earlier */
 566                                                DEBUG_DQS_S("DDR3 - DQS Find Limits - FAIL to PASS: CS - ");
 567                                                DEBUG_DQS_D(cs, 1);
 568                                                DEBUG_DQS_S(", DQ - ");
 569                                                DEBUG_DQS_D(victim_dq, 1);
 570                                                DEBUG_DQS_S(", Pup - ");
 571                                                DEBUG_DQS_D(pup, 1);
 572                                                DEBUG_DQS_S(", ADLL - ");
 573                                                DEBUG_DQS_D(curr_adll, 2);
 574                                                DEBUG_DQS_S("\n");
 575
 576#if defined(MV88F78X60)
 577                                                for (dq = 0; dq < DQ_NUM;
 578                                                     dq++) {
 579                                                        if (analog_pbs[victim_dq][pup][dq][0] == adll_start_val)
 580                                                                analog_pbs
 581                                                                    [victim_dq]
 582                                                                    [pup][dq]
 583                                                                    [0] =
 584                                                                    curr_adll;
 585                                                }
 586#endif
 587                                                /* Found start of window */
 588                                                pup_adll_limit_state[pup] =
 589                                                    PUP_ADLL_LIMITS_STATE_PASS;
 590
 591                                                /* Keep min / max limit value */
 592                                                if (is_tx == 0) {
 593                                                        /* RX - found low limit */
 594                                                        if (centralization_low_limit[pup] <= curr_adll)
 595                                                                centralization_low_limit
 596                                                                    [pup] =
 597                                                                    curr_adll;
 598                                                } else {
 599                                                        /* TX - found high limit */
 600                                                        if (centralization_high_limit[pup] >= curr_adll)
 601                                                                centralization_high_limit
 602                                                                    [pup] =
 603                                                                    curr_adll;
 604                                                }
 605                                        }
 606                                }
 607                        }
 608
 609                        if (unlock_pup == 0) {
 610                                /* Found limit to all pups */
 611                                DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - found PUP limit\n");
 612                                break;
 613                        }
 614
 615                        /*
 616                         * Increment / decrement (Move to right / left
 617                         * one phase - ADLL) dqs RX / TX delay (for all un
 618                         * lock pups
 619                         */
 620                        if (is_tx == 0)
 621                                curr_adll++;
 622                        else
 623                                curr_adll--;
 624                }
 625
 626                if (unlock_pup != 0) {
 627                        /*
 628                         * Found pups that didn't reach to the end of the
 629                         * state machine
 630                         */
 631                        DEBUG_DQS_C("DDR3 - DQS Find Limits - Pups that didn't reached end of the state machine: ",
 632                                    unlock_pup, 1);
 633
 634                        for (pup = 0; pup < max_pup; pup++) {
 635                                if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
 636                                        if (pup_adll_limit_state[pup] ==
 637                                            PUP_ADLL_LIMITS_STATE_FAIL) {
 638                                                /* ERROR - found fail for all window size */
 639                                                DEBUG_DQS_S("DDR3 - DQS Find Limits - Got FAIL for the complete range on pup - ");
 640                                                DEBUG_DQS_D(pup, 1);
 641                                                DEBUG_DQS_C(" victim DQ ",
 642                                                            victim_dq, 1);
 643
 644                                                /* For debug - set min limit to illegal limit */
 645                                                centralization_low_limit[pup]
 646                                                        = ADLL_ERROR;
 647                                                /*
 648                                                 * In case the pup is in mode
 649                                                 * PASS - the limit is the min
 650                                                 * / max adll, no need to
 651                                                 * update because of the results
 652                                                 * array default value
 653                                                 */
 654                                                return MV_DDR3_TRAINING_ERR_PUP_RANGE;
 655                                        }
 656                                }
 657                        }
 658                }
 659        }
 660
 661        DEBUG_DQS_S("DDR3 - DQS Find Limits - DQ values per victim results:\n");
 662        for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
 663                for (pup = 0; pup < max_pup; pup++) {
 664                        DEBUG_DQS_S("Victim DQ-");
 665                        DEBUG_DQS_D(victim_dq, 1);
 666                        DEBUG_DQS_S(", PUP-");
 667                        DEBUG_DQS_D(pup, 1);
 668                        for (dq = 0; dq < DQ_NUM; dq++) {
 669                                DEBUG_DQS_S(", DQ-");
 670                                DEBUG_DQS_D(dq, 1);
 671                                DEBUG_DQS_S(",S-");
 672                                DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
 673                                            [0], 2);
 674                                DEBUG_DQS_S(",E-");
 675                                DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
 676                                            [1], 2);
 677
 678                                if (is_tx == 0) {
 679                                        if (analog_pbs[victim_dq][pup][dq][0]
 680                                            > analog_pbs_sum[pup][dq][0])
 681                                                analog_pbs_sum[pup][dq][0] =
 682                                                    analog_pbs[victim_dq][pup]
 683                                                    [dq][0];
 684                                        if (analog_pbs[victim_dq][pup][dq][1]
 685                                            < analog_pbs_sum[pup][dq][1])
 686                                                analog_pbs_sum[pup][dq][1] =
 687                                                    analog_pbs[victim_dq][pup]
 688                                                    [dq][1];
 689                                } else {
 690                                        if (analog_pbs[victim_dq][pup][dq][0]
 691                                            < analog_pbs_sum[pup][dq][0])
 692                                                analog_pbs_sum[pup][dq][0] =
 693                                                    analog_pbs[victim_dq][pup]
 694                                                    [dq][0];
 695                                        if (analog_pbs[victim_dq][pup][dq][1]
 696                                            > analog_pbs_sum[pup][dq][1])
 697                                                analog_pbs_sum[pup][dq][1] =
 698                                                    analog_pbs[victim_dq][pup]
 699                                                    [dq][1];
 700                                }
 701                        }
 702                        DEBUG_DQS_S("\n");
 703                }
 704        }
 705
 706        if (ddr3_get_log_level() >= MV_LOG_LEVEL_3) {
 707                u32 dq;
 708
 709                DEBUG_PER_DQ_S("\n########## LOG LEVEL 3(Windows margins per-DQ) ##########\n");
 710                if (is_tx) {
 711                        DEBUG_PER_DQ_C("DDR3 - TX  CS: ", cs, 1);
 712                } else {
 713                        DEBUG_PER_DQ_C("DDR3 - RX  CS: ", cs, 1);
 714                }
 715
 716                if (ecc == 0) {
 717                        DEBUG_PER_DQ_S("\n DATA RESULTS:\n");
 718                } else {
 719                        DEBUG_PER_DQ_S("\n ECC RESULTS:\n");
 720                }
 721
 722                /* Since all dq has the same value we take 0 as representive */
 723                dq = 0;
 724                for (pup = 0; pup < max_pup; pup++) {
 725                        if (ecc == 0) {
 726                                DEBUG_PER_DQ_S("\nBYTE:");
 727                                DEBUG_PER_DQ_D(pup, 1);
 728                                DEBUG_PER_DQ_S("\n");
 729                        } else {
 730                                DEBUG_PER_DQ_S("\nECC BYTE:\n");
 731                        }
 732                        DEBUG_PER_DQ_S("  DQ's        LOW       HIGH       WIN-SIZE\n");
 733                        DEBUG_PER_DQ_S("============================================\n");
 734                        for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
 735                                if (ecc == 0) {
 736                                        DEBUG_PER_DQ_S("DQ[");
 737                                        DEBUG_PER_DQ_DD((victim_dq +
 738                                                         DQ_NUM * pup), 2);
 739                                        DEBUG_PER_DQ_S("]");
 740                                } else {
 741                                        DEBUG_PER_DQ_S("CB[");
 742                                        DEBUG_PER_DQ_DD(victim_dq, 2);
 743                                        DEBUG_PER_DQ_S("]");
 744                                }
 745                                if (is_tx) {
 746                                        DEBUG_PER_DQ_S("      0x");
 747                                        DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1], 2);   /* low value */
 748                                        DEBUG_PER_DQ_S("        0x");
 749                                        DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2);   /* high value */
 750                                        DEBUG_PER_DQ_S("        0x");
 751                                        DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0] - analog_pbs[victim_dq][pup][dq][1], 2);       /* win-size */
 752                                } else {
 753                                        DEBUG_PER_DQ_S("     0x");
 754                                        DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2);   /* low value */
 755                                        DEBUG_PER_DQ_S("       0x");
 756                                        DEBUG_PER_DQ_D((analog_pbs[victim_dq][pup][dq][1] - 1), 2);     /* high value */
 757                                        DEBUG_PER_DQ_S("       0x");
 758                                        DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1] - analog_pbs[victim_dq][pup][dq][0], 2);       /* win-size */
 759                                }
 760                                DEBUG_PER_DQ_S("\n");
 761                        }
 762                }
 763                DEBUG_PER_DQ_S("\n");
 764        }
 765
 766        if (is_tx) {
 767                DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
 768        } else {
 769                DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
 770        }
 771
 772        for (pup = 0; pup < max_pup; pup++) {
 773                DEBUG_DQS_S("PUP-");
 774                DEBUG_DQS_D(pup, 1);
 775                for (dq = 0; dq < DQ_NUM; dq++) {
 776                        DEBUG_DQS_S(", DQ-");
 777                        DEBUG_DQS_D(dq, 1);
 778                        DEBUG_DQS_S(",S-");
 779                        DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
 780                        DEBUG_DQS_S(",E-");
 781                        DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
 782                }
 783                DEBUG_DQS_S("\n");
 784        }
 785
 786        if (is_tx) {
 787                DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
 788        } else {
 789                DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
 790        }
 791
 792        for (pup = 0; pup < max_pup; pup++) {
 793                if (max_pup == 1) {
 794                        /* For ECC PUP */
 795                        DEBUG_DQS_S("DDR3 - DQS8");
 796                } else {
 797                        DEBUG_DQS_S("DDR3 - DQS");
 798                        DEBUG_DQS_D(pup, 1);
 799                }
 800
 801                for (dq = 0; dq < DQ_NUM; dq++) {
 802                        DEBUG_DQS_S(", DQ-");
 803                        DEBUG_DQS_D(dq, 1);
 804                        DEBUG_DQS_S("::S-");
 805                        DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
 806                        DEBUG_DQS_S(",E-");
 807                        DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
 808                }
 809                DEBUG_DQS_S("\n");
 810        }
 811
 812        DEBUG_DQS_S("DDR3 - DQS Find Limits - Ended\n");
 813
 814        return MV_OK;
 815}
 816
 817/*
 818 * Name:     ddr3_check_window_limits
 819 * Desc:     Check window High & Low limits.
 820 * Args:     pup                pup index
 821 *           high_limit           window high limit
 822 *           low_limit            window low limit
 823 *           is_tx                Indicate whether Rx or Tx
 824 *           size_valid          Indicate whether window size is valid
 825 * Notes:
 826 * Returns:  MV_OK if success, other error code if fail.
 827 */
 828int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
 829                             int *size_valid)
 830{
 831        DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Starting\n");
 832
 833        if (low_limit > high_limit) {
 834                DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
 835                DEBUG_DQS_D(pup, 1);
 836                DEBUG_DQS_S(" Low Limit grater than High Limit\n");
 837                *size_valid = 0;
 838                return MV_OK;
 839        }
 840
 841        /*
 842         * Check that window size is valid, if not it was probably false pass
 843         * before
 844         */
 845        if ((high_limit - low_limit) < MIN_WIN_SIZE) {
 846                /*
 847                 * Since window size is too small probably there was false
 848                 * pass
 849                 */
 850                *size_valid = 0;
 851
 852                DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
 853                DEBUG_DQS_D(pup, 1);
 854                DEBUG_DQS_S(" Window size is smaller than MIN_WIN_SIZE\n");
 855
 856        } else if ((high_limit - low_limit) > ADLL_MAX) {
 857                *size_valid = 0;
 858
 859                DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
 860                DEBUG_DQS_D(pup, 1);
 861                DEBUG_DQS_S
 862                    (" Window size is bigger than max ADLL taps (31)  Exiting.\n");
 863
 864                return MV_FAIL;
 865
 866        } else {
 867                *size_valid = 1;
 868
 869                DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Pup ");
 870                DEBUG_DQS_FULL_D(pup, 1);
 871                DEBUG_DQS_FULL_C(" window size is ", (high_limit - low_limit),
 872                                 2);
 873        }
 874
 875        return MV_OK;
 876}
 877
 878/*
 879 * Name:     ddr3_center_calc
 880 * Desc:     Execute the calculate the center of windows phase.
 881 * Args:     pDram Info
 882 *           is_tx             Indicate whether Rx or Tx
 883 * Notes:
 884 * Returns:  MV_OK if success, other error code if fail.
 885 */
 886static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
 887                            int is_tx)
 888{
 889        /* bit array of pups that need specail search */
 890        u32 special_pattern_i_pup = 0;
 891        u32 special_pattern_ii_pup = 0;
 892        u32 pup;
 893        u32 max_pup;
 894
 895        max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
 896
 897        for (pup = 0; pup < max_pup; pup++) {
 898                if (is_tx == 0) {
 899                        /* Check special pattern I */
 900                        /*
 901                         * Special pattern Low limit search - relevant only
 902                         * for Rx, win size < threshold and low limit = 0
 903                         */
 904                        if (((centralization_high_limit[pup] -
 905                              centralization_low_limit[pup]) < VALID_WIN_THRS)
 906                            && (centralization_low_limit[pup] == MIN_DELAY))
 907                                special_pattern_i_pup |= (1 << pup);
 908
 909                        /* Check special pattern II */
 910                        /*
 911                         * Special pattern High limit search - relevant only
 912                         * for Rx, win size < threshold and high limit = 31
 913                         */
 914                        if (((centralization_high_limit[pup] -
 915                              centralization_low_limit[pup]) < VALID_WIN_THRS)
 916                            && (centralization_high_limit[pup] == MAX_DELAY))
 917                                special_pattern_ii_pup |= (1 << pup);
 918                }
 919        }
 920
 921        /* Run special pattern Low limit search - for relevant pup */
 922        if (special_pattern_i_pup != 0) {
 923                DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern I for Low limit search\n");
 924                if (MV_OK !=
 925                    ddr3_special_pattern_i_search(dram_info, cs, ecc, is_tx,
 926                                              special_pattern_i_pup))
 927                        return MV_DDR3_TRAINING_ERR_DQS_LOW_LIMIT_SEARCH;
 928        }
 929
 930        /* Run special pattern High limit search - for relevant pup */
 931        if (special_pattern_ii_pup != 0) {
 932                DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern II for High limit search\n");
 933                if (MV_OK !=
 934                    ddr3_special_pattern_ii_search(dram_info, cs, ecc, is_tx,
 935                                                   special_pattern_ii_pup))
 936                        return MV_DDR3_TRAINING_ERR_DQS_HIGH_LIMIT_SEARCH;
 937        }
 938
 939        /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
 940        return ddr3_set_dqs_centralization_results(dram_info, cs, ecc, is_tx);
 941}
 942
 943/*
 944 * Name:     ddr3_special_pattern_i_search
 945 * Desc:     Execute special pattern low limit search.
 946 * Args:
 947 *           special_pattern_pup  The pups that need the special search
 948 * Notes:
 949 * Returns:  MV_OK if success, other error code if fail.
 950 */
 951int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
 952                                  int is_tx, u32 special_pattern_pup)
 953{
 954        u32 victim_dq;          /* loop index - victim DQ */
 955        u32 adll_idx;
 956        u32 pup;
 957        u32 unlock_pup;         /* bit array of the unlock pups  */
 958        u32 first_fail; /* bit array - of pups that  get first fail */
 959        u32 new_lockup_pup;     /* bit array of compare failed pups */
 960        u32 pass_pup;           /* bit array of compare pass pup */
 961        u32 sdram_offset;
 962        u32 max_pup;
 963        u32 comp_val;
 964        u32 special_res[MAX_PUP_NUM];   /* hold tmp results */
 965
 966        DEBUG_DQS_S("DDR3 - DQS - Special Pattern I Search - Starting\n");
 967
 968        max_pup = ecc + (1 - ecc) * dram_info->num_of_std_pups;
 969
 970        /* Init the temporary results to max ADLL value */
 971        for (pup = 0; pup < max_pup; pup++)
 972                special_res[pup] = ADLL_MAX;
 973
 974        /* Run special pattern for all DQ - use the same pattern */
 975        for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
 976                unlock_pup = special_pattern_pup;
 977                first_fail = 0;
 978
 979                sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS +
 980                        LEN_KILLER_PATTERN * 4 * victim_dq;
 981
 982                for (pup = 0; pup < max_pup; pup++) {
 983                        /* Set adll value per PUP. adll = high limit per pup */
 984                        if (IS_PUP_ACTIVE(unlock_pup, pup)) {
 985                                /* only for pups that need special search */
 986                                ddr3_write_pup_reg(PUP_DQS_RD, cs,
 987                                                   pup + (ecc * ECC_PUP), 0,
 988                                                   centralization_high_limit
 989                                                   [pup]);
 990                        }
 991                }
 992
 993                adll_idx = 0;
 994                do {
 995                        /*
 996                         * Perform read and compare simultaneously for all
 997                         * un-locked MC use the special pattern mask
 998                         */
 999                        new_lockup_pup = 0;
1000
1001                        if (MV_OK !=
1002                            ddr3_sdram_dqs_compare(dram_info, unlock_pup,
1003                                                   &new_lockup_pup,
1004                                                   special_pattern
1005                                                   [victim_dq],
1006                                                   LEN_SPECIAL_PATTERN,
1007                                                   sdram_offset, 0,
1008                                                   0, NULL, 1))
1009                                return MV_FAIL;
1010
1011                        DEBUG_DQS_S("DDR3 - DQS - Special I - ADLL value is: ");
1012                        DEBUG_DQS_D(adll_idx, 2);
1013                        DEBUG_DQS_S(", UnlockPup: ");
1014                        DEBUG_DQS_D(unlock_pup, 2);
1015                        DEBUG_DQS_S(", NewLockPup: ");
1016                        DEBUG_DQS_D(new_lockup_pup, 2);
1017                        DEBUG_DQS_S("\n");
1018
1019                        if (unlock_pup != new_lockup_pup)
1020                                DEBUG_DQS_S("DDR3 - DQS - Special I - Some Pup passed!\n");
1021
1022                        /* Search for pups with passed compare & already fail */
1023                        pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
1024                        first_fail |= new_lockup_pup;
1025                        unlock_pup &= ~pass_pup;
1026
1027                        /* Get pass pups */
1028                        if (pass_pup != 0) {
1029                                for (pup = 0; pup < max_pup; pup++) {
1030                                        if (IS_PUP_ACTIVE(pass_pup, pup) ==
1031                                            1) {
1032                                                /* If pup passed and has first fail = 1 */
1033                                                /* keep min value of ADLL max value - current adll */
1034                                                /* (centralization_high_limit[pup] + adll_idx) = current adll !!! */
1035                                                comp_val =
1036                                                    (ADLL_MAX -
1037                                                     (centralization_high_limit
1038                                                      [pup] + adll_idx));
1039
1040                                                DEBUG_DQS_C
1041                                                    ("DDR3 - DQS - Special I - Pup - ",
1042                                                     pup, 1);
1043                                                DEBUG_DQS_C
1044                                                    (" comp_val = ",
1045                                                     comp_val, 2);
1046
1047                                                if (comp_val <
1048                                                    special_res[pup]) {
1049                                                        special_res[pup] =
1050                                                            comp_val;
1051                                                        centralization_low_limit
1052                                                            [pup] =
1053                                                            (-1) *
1054                                                            comp_val;
1055
1056                                                        DEBUG_DQS_C
1057                                                            ("DDR3 - DQS - Special I - Pup - ",
1058                                                             pup, 1);
1059                                                        DEBUG_DQS_C
1060                                                            (" Changed Low limit to ",
1061                                                             centralization_low_limit
1062                                                             [pup], 2);
1063                                                }
1064                                        }
1065                                }
1066                        }
1067
1068                        /*
1069                         * Did all PUP found missing window?
1070                         * Check for each pup if adll (different for each pup)
1071                         * reach maximum if reach max value - lock the pup
1072                         * if not - increment (Move to right one phase - ADLL)
1073                         * dqs RX delay
1074                         */
1075                        adll_idx++;
1076                        for (pup = 0; pup < max_pup; pup++) {
1077                                if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
1078                                        /* Check only unlocked pups */
1079                                        if ((centralization_high_limit[pup] +
1080                                             adll_idx) >= ADLL_MAX) {
1081                                                /* reach maximum - lock the pup */
1082                                                DEBUG_DQS_C("DDR3 - DQS - Special I - reach maximum - lock pup ",
1083                                                            pup, 1);
1084                                                unlock_pup &= ~(1 << pup);
1085                                        } else {
1086                                                /* Didn't reach maximum - increment ADLL */
1087                                                ddr3_write_pup_reg(PUP_DQS_RD,
1088                                                                   cs,
1089                                                                   pup +
1090                                                                   (ecc *
1091                                                                    ECC_PUP), 0,
1092                                                                   (centralization_high_limit
1093                                                                    [pup] +
1094                                                                    adll_idx));
1095                                        }
1096                                }
1097                        }
1098                } while (unlock_pup != 0);
1099        }
1100
1101        return MV_OK;
1102}
1103
1104/*
1105 * Name:     ddr3_special_pattern_ii_search
1106 * Desc:     Execute special pattern high limit search.
1107 * Args:
1108 *           special_pattern_pup  The pups that need the special search
1109 * Notes:
1110 * Returns:  MV_OK if success, other error code if fail.
1111 */
1112int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
1113                                   int is_tx, u32 special_pattern_pup)
1114{
1115        u32 victim_dq;          /* loop index - victim DQ */
1116        u32 adll_idx;
1117        u32 pup;
1118        u32 unlock_pup;         /* bit array of the unlock pups  */
1119        u32 first_fail; /* bit array - of pups that  get first fail */
1120        u32 new_lockup_pup;     /* bit array of compare failed pups */
1121        u32 pass_pup;           /* bit array of compare pass pup */
1122        u32 sdram_offset;
1123        u32 max_pup;
1124        u32 comp_val;
1125        u32 special_res[MAX_PUP_NUM];   /* hold tmp results */
1126
1127        DEBUG_DQS_S("DDR3 - DQS - Special Pattern II Search - Starting\n");
1128
1129        max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
1130
1131        /* init the tmporary results to max ADLL value */
1132        for (pup = 0; pup < max_pup; pup++)
1133                special_res[pup] = ADLL_MAX;
1134
1135        sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS;
1136
1137        /* run special pattern for all DQ - use the same pattern */
1138        for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1139                unlock_pup = special_pattern_pup;
1140                first_fail = 0;
1141
1142                for (pup = 0; pup < max_pup; pup++) {
1143                        /* Set adll value per PUP. adll = 0 */
1144                        if (IS_PUP_ACTIVE(unlock_pup, pup)) {
1145                                /* Only for pups that need special search */
1146                                ddr3_write_pup_reg(PUP_DQS_RD, cs,
1147                                                   pup + (ecc * ECC_PUP), 0,
1148                                                   ADLL_MIN);
1149                        }
1150                }
1151
1152                adll_idx = 0;
1153                do {
1154                        /*
1155                         * Perform read and compare simultaneously for all
1156                         * un-locked MC use the special pattern mask
1157                         */
1158                        new_lockup_pup = 0;
1159
1160                        if (MV_OK != ddr3_sdram_dqs_compare(
1161                                    dram_info, unlock_pup, &new_lockup_pup,
1162                                    special_pattern[victim_dq],
1163                                    LEN_SPECIAL_PATTERN,
1164                                    sdram_offset, 0, 0, NULL, 0))
1165                                return MV_FAIL;
1166
1167                        DEBUG_DQS_S("DDR3 - DQS - Special II - ADLL value is ");
1168                        DEBUG_DQS_D(adll_idx, 2);
1169                        DEBUG_DQS_S("unlock_pup ");
1170                        DEBUG_DQS_D(unlock_pup, 1);
1171                        DEBUG_DQS_S("new_lockup_pup ");
1172                        DEBUG_DQS_D(new_lockup_pup, 1);
1173                        DEBUG_DQS_S("\n");
1174
1175                        if (unlock_pup != new_lockup_pup) {
1176                                DEBUG_DQS_S("DDR3 - DQS - Special II - Some Pup passed!\n");
1177                        }
1178
1179                        /* Search for pups with passed compare & already fail */
1180                        pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
1181                        first_fail |= new_lockup_pup;
1182                        unlock_pup &= ~pass_pup;
1183
1184                        /* Get pass pups */
1185                        if (pass_pup != 0) {
1186                                for (pup = 0; pup < max_pup; pup++) {
1187                                        if (IS_PUP_ACTIVE(pass_pup, pup) ==
1188                                            1) {
1189                                                /* If pup passed and has first fail = 1 */
1190                                                /* keep min value of ADLL max value - current adll */
1191                                                /* (adll_idx) = current adll !!! */
1192                                                comp_val = adll_idx;
1193
1194                                                DEBUG_DQS_C("DDR3 - DQS - Special II - Pup - ",
1195                                                            pup, 1);
1196                                                DEBUG_DQS_C(" comp_val = ",
1197                                                            comp_val, 1);
1198
1199                                                if (comp_val <
1200                                                    special_res[pup]) {
1201                                                        special_res[pup] =
1202                                                            comp_val;
1203                                                        centralization_high_limit
1204                                                            [pup] =
1205                                                            ADLL_MAX +
1206                                                            comp_val;
1207
1208                                                        DEBUG_DQS_C
1209                                                            ("DDR3 - DQS - Special II - Pup - ",
1210                                                             pup, 1);
1211                                                        DEBUG_DQS_C
1212                                                            (" Changed High limit to ",
1213                                                             centralization_high_limit
1214                                                             [pup], 2);
1215                                                }
1216                                        }
1217                                }
1218                        }
1219
1220                        /*
1221                         * Did all PUP found missing window?
1222                         * Check for each pup if adll (different for each pup)
1223                         * reach maximum if reach max value - lock the pup
1224                         * if not - increment (Move to right one phase - ADLL)
1225                         * dqs RX delay
1226                         */
1227                        adll_idx++;
1228                        for (pup = 0; pup < max_pup; pup++) {
1229                                if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
1230                                        /* Check only unlocked pups */
1231                                        if ((adll_idx) >= ADLL_MAX) {
1232                                                /* Reach maximum - lock the pup */
1233                                                DEBUG_DQS_C("DDR3 - DQS - Special II - reach maximum - lock pup ",
1234                                                            pup, 1);
1235                                                unlock_pup &= ~(1 << pup);
1236                                        } else {
1237                                                /* Didn't reach maximum - increment ADLL */
1238                                                ddr3_write_pup_reg(PUP_DQS_RD,
1239                                                                   cs,
1240                                                                   pup +
1241                                                                   (ecc *
1242                                                                    ECC_PUP), 0,
1243                                                                   (adll_idx));
1244                                        }
1245                                }
1246                        }
1247                } while (unlock_pup != 0);
1248        }
1249
1250        return MV_OK;
1251}
1252
1253/*
1254 * Name:     ddr3_set_dqs_centralization_results
1255 * Desc:     Set to HW the DQS centralization phase results.
1256 * Args:
1257 *           is_tx             Indicates whether to set Tx or RX results
1258 * Notes:
1259 * Returns:  MV_OK if success, other error code if fail.
1260 */
1261int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs,
1262                                        u32 ecc, int is_tx)
1263{
1264        u32 pup, pup_num;
1265        int addl_val;
1266        u32 max_pup;
1267
1268        max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
1269
1270        DEBUG_DQS_RESULTS_S("\n############ LOG LEVEL 2(Windows margins) ############\n");
1271
1272        if (is_tx) {
1273                DEBUG_DQS_RESULTS_C("DDR3 - DQS TX - Set Dqs Centralization Results - CS: ",
1274                                    cs, 1);
1275        } else {
1276                DEBUG_DQS_RESULTS_C("DDR3 - DQS RX - Set Dqs Centralization Results - CS: ",
1277                                    cs, 1);
1278        }
1279
1280        /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
1281        DEBUG_DQS_RESULTS_S("\nDQS    LOW     HIGH     WIN-SIZE      Set\n");
1282        DEBUG_DQS_RESULTS_S("==============================================\n");
1283        for (pup = 0; pup < max_pup; pup++) {
1284                addl_val = (centralization_high_limit[pup] +
1285                            centralization_low_limit[pup]) / 2;
1286
1287                pup_num = pup * (1 - ecc) + ecc * ECC_PUP;
1288
1289                DEBUG_DQS_RESULTS_D(pup_num, 1);
1290                DEBUG_DQS_RESULTS_S("     0x");
1291                DEBUG_DQS_RESULTS_D(centralization_low_limit[pup], 2);
1292                DEBUG_DQS_RESULTS_S("      0x");
1293                DEBUG_DQS_RESULTS_D(centralization_high_limit[pup], 2);
1294                DEBUG_DQS_RESULTS_S("      0x");
1295                DEBUG_DQS_RESULTS_D(centralization_high_limit[pup] -
1296                                    centralization_low_limit[pup], 2);
1297                DEBUG_DQS_RESULTS_S("       0x");
1298                DEBUG_DQS_RESULTS_D(addl_val, 2);
1299                DEBUG_DQS_RESULTS_S("\n");
1300
1301                if (addl_val < ADLL_MIN) {
1302                        addl_val = ADLL_MIN;
1303                        DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MIN (since it was lower than 0)\n");
1304                }
1305
1306                if (addl_val > ADLL_MAX) {
1307                        addl_val = ADLL_MAX;
1308                        DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MAX (since it was higher than 31)\n");
1309                }
1310
1311                if (is_tx) {
1312                        ddr3_write_pup_reg(PUP_DQS_WR, cs, pup_num, 0,
1313                                           addl_val +
1314                                           dram_info->wl_val[cs][pup_num][D]);
1315                } else {
1316                        ddr3_write_pup_reg(PUP_DQS_RD, cs, pup_num, 0,
1317                                           addl_val);
1318                }
1319        }
1320
1321        return MV_OK;
1322}
1323
1324/*
1325 * Set training patterns
1326 */
1327int ddr3_load_dqs_patterns(MV_DRAM_INFO *dram_info)
1328{
1329        u32 cs, cs_count, cs_tmp, victim_dq;
1330        u32 sdram_addr;
1331        u32 *pattern_ptr;
1332
1333        /* Loop for each CS */
1334        for (cs = 0; cs < MAX_CS; cs++) {
1335                if (dram_info->cs_ena & (1 << cs)) {
1336                        cs_count = 0;
1337                        for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
1338                                if (dram_info->cs_ena & (1 << cs_tmp))
1339                                        cs_count++;
1340                        }
1341
1342                        /* Init killer pattern */
1343                        sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
1344                                      SDRAM_DQS_RX_OFFS);
1345                        for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1346                                pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
1347                                                                      victim_dq);
1348                                if (MV_OK != ddr3_sdram_dqs_compare(
1349                                            dram_info, (u32)NULL, NULL,
1350                                            pattern_ptr, LEN_KILLER_PATTERN,
1351                                            sdram_addr + LEN_KILLER_PATTERN *
1352                                            4 * victim_dq, 1, 0, NULL,
1353                                            0))
1354                                        return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
1355                        }
1356
1357                        /* Init special-killer pattern */
1358                        sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
1359                                      SDRAM_DQS_RX_SPECIAL_OFFS);
1360                        for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1361                                if (MV_OK != ddr3_sdram_dqs_compare(
1362                                            dram_info, (u32)NULL, NULL,
1363                                            special_pattern[victim_dq],
1364                                            LEN_KILLER_PATTERN, sdram_addr +
1365                                            LEN_KILLER_PATTERN * 4 * victim_dq,
1366                                            1, 0, NULL, 0))
1367                                        return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
1368                        }
1369                }
1370        }
1371
1372        return MV_OK;
1373}
1374