uboot/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) Marvell International Ltd. and its affiliates
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0
   5 */
   6
   7#include <common.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_init.h"
  14
  15#define PATTERN_1       0x55555555
  16#define PATTERN_2       0xaaaaaaaa
  17
  18#define VALIDATE_TRAINING_LIMIT(e1, e2)                 \
  19        ((((e2) - (e1) + 1) > 33) && ((e1) < 67))
  20
  21u32 phy_reg_bk[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
  22
  23u32 training_res[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS *
  24                 HWS_SEARCH_DIR_LIMIT];
  25
  26u16 mask_results_dq_reg_map[] = {
  27        RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG,
  28        RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG,
  29        RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG,
  30        RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG,
  31        RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG,
  32        RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG,
  33        RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG,
  34        RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG,
  35        RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG,
  36        RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG,
  37        RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG,
  38        RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_BIT_7_REG,
  39        RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG,
  40        RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG,
  41        RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG,
  42        RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG,
  43        RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
  44        RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
  45        RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
  46        RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
  47};
  48
  49u16 mask_results_pup_reg_map[] = {
  50        RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG,
  51        RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_3_REG,
  52        RESULT_CONTROL_BYTE_PUP_4_REG
  53};
  54
  55u16 mask_results_dq_reg_map_pup3_ecc[] = {
  56        RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG,
  57        RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG,
  58        RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG,
  59        RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG,
  60        RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG,
  61        RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG,
  62        RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG,
  63        RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG,
  64        RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG,
  65        RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG,
  66        RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG,
  67        RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_BIT_7_REG,
  68        RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
  69        RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
  70        RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
  71        RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
  72        RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
  73        RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
  74        RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
  75        RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
  76};
  77
  78u16 mask_results_pup_reg_map_pup3_ecc[] = {
  79        RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG,
  80        RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_4_REG,
  81        RESULT_CONTROL_BYTE_PUP_4_REG
  82};
  83
  84struct pattern_info pattern_table_16[] = {
  85        /*
  86         * num tx phases, tx burst, delay between, rx pattern,
  87         * start_address, pattern_len
  88         */
  89        {1, 1, 2, 1, 0x0080, 2},        /* PATTERN_PBS1 */
  90        {1, 1, 2, 1, 0x00c0, 2},        /* PATTERN_PBS2 */
  91        {1, 1, 2, 1, 0x0100, 2},        /* PATTERN_RL */
  92        {0xf, 0x7, 2, 0x7, 0x0140, 16}, /* PATTERN_STATIC_PBS */
  93        {0xf, 0x7, 2, 0x7, 0x0190, 16}, /* PATTERN_KILLER_DQ0 */
  94        {0xf, 0x7, 2, 0x7, 0x01d0, 16}, /* PATTERN_KILLER_DQ1 */
  95        {0xf, 0x7, 2, 0x7, 0x0210, 16}, /* PATTERN_KILLER_DQ2 */
  96        {0xf, 0x7, 2, 0x7, 0x0250, 16}, /* PATTERN_KILLER_DQ3 */
  97        {0xf, 0x7, 2, 0x7, 0x0290, 16}, /* PATTERN_KILLER_DQ4 */
  98        {0xf, 0x7, 2, 0x7, 0x02d0, 16}, /* PATTERN_KILLER_DQ5 */
  99        {0xf, 0x7, 2, 0x7, 0x0310, 16}, /* PATTERN_KILLER_DQ6 */
 100        {0xf, 0x7, 2, 0x7, 0x0350, 16}, /* PATTERN_KILLER_DQ7 */
 101        {1, 1, 2, 1, 0x0380, 2},        /* PATTERN_PBS3 */
 102        {1, 1, 2, 1, 0x0000, 2},        /* PATTERN_RL2 */
 103        {1, 1, 2, 1, 0x0040, 2},        /* PATTERN_TEST */
 104        {0xf, 0x7, 2, 0x7, 0x03c0, 16}, /* PATTERN_FULL_SSO_1T */
 105        {0xf, 0x7, 2, 0x7, 0x0400, 16}, /* PATTERN_FULL_SSO_2T */
 106        {0xf, 0x7, 2, 0x7, 0x0440, 16}, /* PATTERN_FULL_SSO_3T */
 107        {0xf, 0x7, 2, 0x7, 0x0480, 16}, /* PATTERN_FULL_SSO_4T */
 108        {0xf, 0x7, 2, 0x7, 0x04c0, 16}  /* PATTERN_VREF */
 109        /*Note: actual start_address is <<3 of defined addess */
 110};
 111
 112struct pattern_info pattern_table_32[] = {
 113        /*
 114         * num tx phases, tx burst, delay between, rx pattern,
 115         * start_address, pattern_len
 116         */
 117        {3, 3, 2, 3, 0x0080, 4},        /* PATTERN_PBS1 */
 118        {3, 3, 2, 3, 0x00c0, 4},        /* PATTERN_PBS2 */
 119        {3, 3, 2, 3, 0x0100, 4},        /* PATTERN_RL */
 120        {0x1f, 0xf, 2, 0xf, 0x0140, 32},        /* PATTERN_STATIC_PBS */
 121        {0x1f, 0xf, 2, 0xf, 0x0190, 32},        /* PATTERN_KILLER_DQ0 */
 122        {0x1f, 0xf, 2, 0xf, 0x01d0, 32},        /* PATTERN_KILLER_DQ1 */
 123        {0x1f, 0xf, 2, 0xf, 0x0210, 32},        /* PATTERN_KILLER_DQ2 */
 124        {0x1f, 0xf, 2, 0xf, 0x0250, 32},        /* PATTERN_KILLER_DQ3 */
 125        {0x1f, 0xf, 2, 0xf, 0x0290, 32},        /* PATTERN_KILLER_DQ4 */
 126        {0x1f, 0xf, 2, 0xf, 0x02d0, 32},        /* PATTERN_KILLER_DQ5 */
 127        {0x1f, 0xf, 2, 0xf, 0x0310, 32},        /* PATTERN_KILLER_DQ6 */
 128        {0x1f, 0xf, 2, 0xf, 0x0350, 32},        /* PATTERN_KILLER_DQ7 */
 129        {3, 3, 2, 3, 0x0380, 4},        /* PATTERN_PBS3 */
 130        {3, 3, 2, 3, 0x0000, 4},        /* PATTERN_RL2 */
 131        {3, 3, 2, 3, 0x0040, 4},        /* PATTERN_TEST */
 132        {0x1f, 0xf, 2, 0xf, 0x03c0, 32},        /* PATTERN_FULL_SSO_1T */
 133        {0x1f, 0xf, 2, 0xf, 0x0400, 32},        /* PATTERN_FULL_SSO_2T */
 134        {0x1f, 0xf, 2, 0xf, 0x0440, 32},        /* PATTERN_FULL_SSO_3T */
 135        {0x1f, 0xf, 2, 0xf, 0x0480, 32},        /* PATTERN_FULL_SSO_4T */
 136        {0x1f, 0xf, 2, 0xf, 0x04c0, 32} /* PATTERN_VREF */
 137        /*Note: actual start_address is <<3 of defined addess */
 138};
 139
 140u32 train_dev_num;
 141enum hws_ddr_cs traintrain_cs_type;
 142u32 train_pup_num;
 143enum hws_training_result train_result_type;
 144enum hws_control_element train_control_element;
 145enum hws_search_dir traine_search_dir;
 146enum hws_dir train_direction;
 147u32 train_if_select;
 148u32 train_init_value;
 149u32 train_number_iterations;
 150enum hws_pattern train_pattern;
 151enum hws_edge_compare train_edge_compare;
 152u32 train_cs_num;
 153u32 train_if_acess, train_if_id, train_pup_access;
 154u32 max_polling_for_done = 1000000;
 155
 156u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search,
 157                          enum hws_training_result result_type,
 158                          u32 interface_num)
 159{
 160        u32 *buf_ptr = NULL;
 161
 162        buf_ptr = &training_res
 163                [MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS * search +
 164                 interface_num * MAX_BUS_NUM * BUS_WIDTH_IN_BITS];
 165
 166        return buf_ptr;
 167}
 168
 169/*
 170 * IP Training search
 171 * Note: for one edge search only from fail to pass, else jitter can
 172 * be be entered into solution.
 173 */
 174int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
 175                         u32 interface_num,
 176                         enum hws_access_type pup_access_type,
 177                         u32 pup_num, enum hws_training_result result_type,
 178                         enum hws_control_element control_element,
 179                         enum hws_search_dir search_dir, enum hws_dir direction,
 180                         u32 interface_mask, u32 init_value, u32 num_iter,
 181                         enum hws_pattern pattern,
 182                         enum hws_edge_compare edge_comp,
 183                         enum hws_ddr_cs cs_type, u32 cs_num,
 184                         enum hws_training_ip_stat *train_status)
 185{
 186        u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt, poll_cnt,
 187                reg_data, pup_id;
 188        u32 tx_burst_size;
 189        u32 delay_between_burst;
 190        u32 rd_mode;
 191        u32 read_data[MAX_INTERFACE_NUM];
 192        struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
 193        u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
 194        u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
 195        struct hws_topology_map *tm = ddr3_get_topology_map();
 196
 197        if (pup_num >= tm->num_of_bus_per_interface) {
 198                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
 199                                         ("pup_num %d not valid\n", pup_num));
 200        }
 201        if (interface_num >= MAX_INTERFACE_NUM) {
 202                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
 203                                         ("if_id %d not valid\n",
 204                                          interface_num));
 205        }
 206        if (train_status == NULL) {
 207                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
 208                                         ("error param 4\n"));
 209                return MV_BAD_PARAM;
 210        }
 211
 212        /* load pattern */
 213        if (cs_type == CS_SINGLE) {
 214                /* All CSs to CS0     */
 215                CHECK_STATUS(ddr3_tip_if_write
 216                             (dev_num, access_type, interface_num,
 217                              CS_ENABLE_REG, 1 << 3, 1 << 3));
 218                /* All CSs to CS0     */
 219                CHECK_STATUS(ddr3_tip_if_write
 220                             (dev_num, access_type, interface_num,
 221                              ODPG_DATA_CONTROL_REG,
 222                              (0x3 | (effective_cs << 26)), 0xc000003));
 223        } else {
 224                CHECK_STATUS(ddr3_tip_if_write
 225                             (dev_num, access_type, interface_num,
 226                              CS_ENABLE_REG, 0, 1 << 3));
 227                /*  CS select */
 228                CHECK_STATUS(ddr3_tip_if_write
 229                             (dev_num, access_type, interface_num,
 230                              ODPG_DATA_CONTROL_REG, 0x3 | cs_num << 26,
 231                              0x3 | 3 << 26));
 232        }
 233
 234        /* load pattern to ODPG */
 235        ddr3_tip_load_pattern_to_odpg(dev_num, access_type, interface_num,
 236                                      pattern,
 237                                      pattern_table[pattern].start_addr);
 238        tx_burst_size = (direction == OPER_WRITE) ?
 239                pattern_table[pattern].tx_burst_size : 0;
 240        delay_between_burst = (direction == OPER_WRITE) ? 2 : 0;
 241        rd_mode = (direction == OPER_WRITE) ? 1 : 0;
 242        CHECK_STATUS(ddr3_tip_configure_odpg
 243                     (dev_num, access_type, interface_num, direction,
 244                      pattern_table[pattern].num_of_phases_tx, tx_burst_size,
 245                      pattern_table[pattern].num_of_phases_rx,
 246                      delay_between_burst, rd_mode, effective_cs, STRESS_NONE,
 247                      DURATION_SINGLE));
 248        reg_data = (direction == OPER_READ) ? 0 : (0x3 << 30);
 249        reg_data |= (direction == OPER_READ) ? 0x60 : 0xfa;
 250        CHECK_STATUS(ddr3_tip_if_write
 251                     (dev_num, access_type, interface_num,
 252                      ODPG_WRITE_READ_MODE_ENABLE_REG, reg_data,
 253                      MASK_ALL_BITS));
 254        reg_data = (edge_comp == EDGE_PF || edge_comp == EDGE_FP) ? 0 : 1 << 6;
 255        reg_data |= (edge_comp == EDGE_PF || edge_comp == EDGE_PFP) ?
 256                (1 << 7) : 0;
 257
 258        /* change from Pass to Fail will lock the result */
 259        if (pup_access_type == ACCESS_TYPE_MULTICAST)
 260                reg_data |= 0xe << 14;
 261        else
 262                reg_data |= pup_num << 14;
 263
 264        if (edge_comp == EDGE_FP) {
 265                /* don't search for readl edge change, only the state */
 266                reg_data |= (0 << 20);
 267        } else if (edge_comp == EDGE_FPF) {
 268                reg_data |= (0 << 20);
 269        } else {
 270                reg_data |= (3 << 20);
 271        }
 272
 273        CHECK_STATUS(ddr3_tip_if_write
 274                     (dev_num, access_type, interface_num,
 275                      ODPG_TRAINING_CONTROL_REG,
 276                      reg_data | (0x7 << 8) | (0x7 << 11),
 277                      (0x3 | (0x3 << 2) | (0x3 << 6) | (1 << 5) | (0x7 << 8) |
 278                       (0x7 << 11) | (0xf << 14) | (0x3 << 18) | (3 << 20))));
 279        reg_data = (search_dir == HWS_LOW2HIGH) ? 0 : (1 << 8);
 280        CHECK_STATUS(ddr3_tip_if_write
 281                     (dev_num, access_type, interface_num, ODPG_OBJ1_OPCODE_REG,
 282                      1 | reg_data | init_value << 9 | (1 << 25) | (1 << 26),
 283                      0xff | (1 << 8) | (0xffff << 9) | (1 << 25) | (1 << 26)));
 284
 285        /*
 286         * Write2_dunit(0x10b4, Number_iteration , [15:0])
 287         * Max number of iterations
 288         */
 289        CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num,
 290                                       ODPG_OBJ1_ITER_CNT_REG, num_iter,
 291                                       0xffff));
 292        if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
 293            direction == OPER_READ) {
 294                /*
 295                 * Write2_dunit(0x10c0, 0x5f , [7:0])
 296                 * MC PBS Reg Address at DDR PHY
 297                 */
 298                reg_data = 0x5f +
 299                        effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET;
 300        } else if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
 301                   direction == OPER_WRITE) {
 302                reg_data = 0x1f +
 303                        effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET;
 304        } else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
 305                   direction == OPER_WRITE) {
 306                /*
 307                 * LOOP         0x00000001 + 4*n:
 308                 * where n (0-3) represents M_CS number
 309                 */
 310                /*
 311                 * Write2_dunit(0x10c0, 0x1 , [7:0])
 312                 * ADLL WR Reg Address at DDR PHY
 313                 */
 314                reg_data = 1 + effective_cs * CS_REGISTER_ADDR_OFFSET;
 315        } else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
 316                   direction == OPER_READ) {
 317                /* ADLL RD Reg Address at DDR PHY */
 318                reg_data = 3 + effective_cs * CS_REGISTER_ADDR_OFFSET;
 319        } else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW &&
 320                   direction == OPER_WRITE) {
 321                /* TBD not defined in 0.5.0 requirement  */
 322        } else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW &&
 323                   direction == OPER_READ) {
 324                /* TBD not defined in 0.5.0 requirement */
 325        }
 326
 327        reg_data |= (0x6 << 28);
 328        CHECK_STATUS(ddr3_tip_if_write
 329                     (dev_num, access_type, interface_num, CALIB_OBJ_PRFA_REG,
 330                      reg_data | (init_value << 8),
 331                      0xff | (0xffff << 8) | (0xf << 24) | (u32) (0xf << 28)));
 332
 333        mask_dq_num_of_regs = tm->num_of_bus_per_interface * BUS_WIDTH_IN_BITS;
 334        mask_pup_num_of_regs = tm->num_of_bus_per_interface;
 335
 336        if (result_type == RESULT_PER_BIT) {
 337                for (index_cnt = 0; index_cnt < mask_dq_num_of_regs;
 338                     index_cnt++) {
 339                        CHECK_STATUS(ddr3_tip_if_write
 340                                     (dev_num, access_type, interface_num,
 341                                      mask_results_dq_reg_map[index_cnt], 0,
 342                                      1 << 24));
 343                }
 344
 345                /* Mask disabled buses */
 346                for (pup_id = 0; pup_id < tm->num_of_bus_per_interface;
 347                     pup_id++) {
 348                        if (IS_ACTIVE(tm->bus_act_mask, pup_id) == 1)
 349                                continue;
 350
 351                        for (index_cnt = (mask_dq_num_of_regs - pup_id * 8);
 352                             index_cnt <
 353                                     (mask_dq_num_of_regs - (pup_id + 1) * 8);
 354                             index_cnt++) {
 355                                CHECK_STATUS(ddr3_tip_if_write
 356                                             (dev_num, access_type,
 357                                              interface_num,
 358                                              mask_results_dq_reg_map
 359                                              [index_cnt], (1 << 24), 1 << 24));
 360                        }
 361                }
 362
 363                for (index_cnt = 0; index_cnt < mask_pup_num_of_regs;
 364                     index_cnt++) {
 365                        CHECK_STATUS(ddr3_tip_if_write
 366                                     (dev_num, access_type, interface_num,
 367                                      mask_results_pup_reg_map[index_cnt],
 368                                      (1 << 24), 1 << 24));
 369                }
 370        } else if (result_type == RESULT_PER_BYTE) {
 371                /* write to adll */
 372                for (index_cnt = 0; index_cnt < mask_pup_num_of_regs;
 373                     index_cnt++) {
 374                        CHECK_STATUS(ddr3_tip_if_write
 375                                     (dev_num, access_type, interface_num,
 376                                      mask_results_pup_reg_map[index_cnt], 0,
 377                                      1 << 24));
 378                }
 379                for (index_cnt = 0; index_cnt < mask_dq_num_of_regs;
 380                     index_cnt++) {
 381                        CHECK_STATUS(ddr3_tip_if_write
 382                                     (dev_num, access_type, interface_num,
 383                                      mask_results_dq_reg_map[index_cnt],
 384                                      (1 << 24), (1 << 24)));
 385                }
 386        }
 387
 388        /* Start Training Trigger */
 389        CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num,
 390                                       ODPG_TRAINING_TRIGGER_REG, 1, 1));
 391        /* wait for all RFU tests to finish (or timeout) */
 392        /* WA for 16 bit mode, more investigation needed */
 393        mdelay(1);
 394
 395        /* Training "Done ?" */
 396        for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) {
 397                if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0)
 398                        continue;
 399
 400                if (interface_mask & (1 << index_cnt)) {
 401                        /* need to check results for this Dunit */
 402                        for (poll_cnt = 0; poll_cnt < max_polling_for_done;
 403                             poll_cnt++) {
 404                                CHECK_STATUS(ddr3_tip_if_read
 405                                             (dev_num, ACCESS_TYPE_UNICAST,
 406                                              index_cnt,
 407                                              ODPG_TRAINING_STATUS_REG,
 408                                              &reg_data, MASK_ALL_BITS));
 409                                if ((reg_data & 0x2) != 0) {
 410                                        /*done */
 411                                        train_status[index_cnt] =
 412                                                HWS_TRAINING_IP_STATUS_SUCCESS;
 413                                        break;
 414                                }
 415                        }
 416
 417                        if (poll_cnt == max_polling_for_done) {
 418                                train_status[index_cnt] =
 419                                        HWS_TRAINING_IP_STATUS_TIMEOUT;
 420                        }
 421                }
 422                /* Be sure that ODPG done */
 423                CHECK_STATUS(is_odpg_access_done(dev_num, index_cnt));
 424        }
 425
 426        /* Write ODPG done in Dunit */
 427        CHECK_STATUS(ddr3_tip_if_write
 428                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
 429                      ODPG_STATUS_DONE_REG, 0, 0x1));
 430
 431        /* wait for all Dunit tests to finish (or timeout) */
 432        /* Training "Done ?" */
 433        /* Training "Pass ?" */
 434        for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) {
 435                if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0)
 436                        continue;
 437
 438                if (interface_mask & (1 << index_cnt)) {
 439                        /* need to check results for this Dunit */
 440                        for (poll_cnt = 0; poll_cnt < max_polling_for_done;
 441                             poll_cnt++) {
 442                                CHECK_STATUS(ddr3_tip_if_read
 443                                             (dev_num, ACCESS_TYPE_UNICAST,
 444                                              index_cnt,
 445                                              ODPG_TRAINING_TRIGGER_REG,
 446                                              read_data, MASK_ALL_BITS));
 447                                reg_data = read_data[index_cnt];
 448                                if ((reg_data & 0x2) != 0) {
 449                                        /* done */
 450                                        if ((reg_data & 0x4) == 0) {
 451                                                train_status[index_cnt] =
 452                                                        HWS_TRAINING_IP_STATUS_SUCCESS;
 453                                        } else {
 454                                                train_status[index_cnt] =
 455                                                        HWS_TRAINING_IP_STATUS_FAIL;
 456                                        }
 457                                        break;
 458                                }
 459                        }
 460
 461                        if (poll_cnt == max_polling_for_done) {
 462                                train_status[index_cnt] =
 463                                        HWS_TRAINING_IP_STATUS_TIMEOUT;
 464                        }
 465                }
 466        }
 467
 468        CHECK_STATUS(ddr3_tip_if_write
 469                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
 470                      ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS));
 471
 472        return MV_OK;
 473}
 474
 475/*
 476 * Load expected Pattern to ODPG
 477 */
 478int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type,
 479                                  u32 if_id, enum hws_pattern pattern,
 480                                  u32 load_addr)
 481{
 482        u32 pattern_length_cnt = 0;
 483        struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
 484
 485        for (pattern_length_cnt = 0;
 486             pattern_length_cnt < pattern_table[pattern].pattern_len;
 487             pattern_length_cnt++) {
 488                CHECK_STATUS(ddr3_tip_if_write
 489                             (dev_num, access_type, if_id,
 490                              ODPG_PATTERN_DATA_LOW_REG,
 491                              pattern_table_get_word(dev_num, pattern,
 492                                                     (u8) (pattern_length_cnt *
 493                                                           2)), MASK_ALL_BITS));
 494                CHECK_STATUS(ddr3_tip_if_write
 495                             (dev_num, access_type, if_id,
 496                              ODPG_PATTERN_DATA_HI_REG,
 497                              pattern_table_get_word(dev_num, pattern,
 498                                                     (u8) (pattern_length_cnt *
 499                                                           2 + 1)),
 500                              MASK_ALL_BITS));
 501                CHECK_STATUS(ddr3_tip_if_write
 502                             (dev_num, access_type, if_id,
 503                              ODPG_PATTERN_ADDR_REG, pattern_length_cnt,
 504                              MASK_ALL_BITS));
 505        }
 506
 507        CHECK_STATUS(ddr3_tip_if_write
 508                     (dev_num, access_type, if_id,
 509                      ODPG_PATTERN_ADDR_OFFSET_REG, load_addr, MASK_ALL_BITS));
 510
 511        return MV_OK;
 512}
 513
 514/*
 515 * Configure ODPG
 516 */
 517int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type,
 518                            u32 if_id, enum hws_dir direction, u32 tx_phases,
 519                            u32 tx_burst_size, u32 rx_phases,
 520                            u32 delay_between_burst, u32 rd_mode, u32 cs_num,
 521                            u32 addr_stress_jump, u32 single_pattern)
 522{
 523        u32 data_value = 0;
 524        int ret;
 525
 526        data_value = ((single_pattern << 2) | (tx_phases << 5) |
 527                      (tx_burst_size << 11) | (delay_between_burst << 15) |
 528                      (rx_phases << 21) | (rd_mode << 25) | (cs_num << 26) |
 529                      (addr_stress_jump << 29));
 530        ret = ddr3_tip_if_write(dev_num, access_type, if_id,
 531                                ODPG_DATA_CONTROL_REG, data_value, 0xaffffffc);
 532        if (ret != MV_OK)
 533                return ret;
 534
 535        return MV_OK;
 536}
 537
 538int ddr3_tip_process_result(u32 *ar_result, enum hws_edge e_edge,
 539                            enum hws_edge_search e_edge_search,
 540                            u32 *edge_result)
 541{
 542        u32 i, res;
 543        int tap_val, max_val = -10000, min_val = 10000;
 544        int lock_success = 1;
 545
 546        for (i = 0; i < BUS_WIDTH_IN_BITS; i++) {
 547                res = GET_LOCK_RESULT(ar_result[i]);
 548                if (res == 0) {
 549                        lock_success = 0;
 550                        break;
 551                }
 552                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
 553                                         ("lock failed for bit %d\n", i));
 554        }
 555
 556        if (lock_success == 1) {
 557                for (i = 0; i < BUS_WIDTH_IN_BITS; i++) {
 558                        tap_val = GET_TAP_RESULT(ar_result[i], e_edge);
 559                        if (tap_val > max_val)
 560                                max_val = tap_val;
 561                        if (tap_val < min_val)
 562                                min_val = tap_val;
 563                        if (e_edge_search == TRAINING_EDGE_MAX)
 564                                *edge_result = (u32) max_val;
 565                        else
 566                                *edge_result = (u32) min_val;
 567
 568                        DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
 569                                                 ("i %d ar_result[i] 0x%x tap_val %d max_val %d min_val %d Edge_result %d\n",
 570                                                  i, ar_result[i], tap_val,
 571                                                  max_val, min_val,
 572                                                  *edge_result));
 573                }
 574        } else {
 575                return MV_FAIL;
 576        }
 577
 578        return MV_OK;
 579}
 580
 581/*
 582 * Read training search result
 583 */
 584int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
 585                                  enum hws_access_type pup_access_type,
 586                                  u32 pup_num, u32 bit_num,
 587                                  enum hws_search_dir search,
 588                                  enum hws_dir direction,
 589                                  enum hws_training_result result_type,
 590                                  enum hws_training_load_op operation,
 591                                  u32 cs_num_type, u32 **load_res,
 592                                  int is_read_from_db, u8 cons_tap,
 593                                  int is_check_result_validity)
 594{
 595        u32 reg_offset, pup_cnt, start_pup, end_pup, start_reg, end_reg;
 596        u32 *interface_train_res = NULL;
 597        u16 *reg_addr = NULL;
 598        u32 read_data[MAX_INTERFACE_NUM];
 599        u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
 600        u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
 601        struct hws_topology_map *tm = ddr3_get_topology_map();
 602
 603        /*
 604         * Agreed assumption: all CS mask contain same number of bits,
 605         * i.e. in multi CS, the number of CS per memory is the same for
 606         * all pups
 607         */
 608        CHECK_STATUS(ddr3_tip_if_write
 609                     (dev_num, ACCESS_TYPE_UNICAST, if_id, CS_ENABLE_REG,
 610                      (cs_num_type == 0) ? 1 << 3 : 0, (1 << 3)));
 611        CHECK_STATUS(ddr3_tip_if_write
 612                     (dev_num, ACCESS_TYPE_UNICAST, if_id,
 613                      ODPG_DATA_CONTROL_REG, (cs_num_type << 26), (3 << 26)));
 614        DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE,
 615                                 ("Read_from_d_b %d cs_type %d oper %d result_type %d direction %d search %d pup_num %d if_id %d pup_access_type %d\n",
 616                                  is_read_from_db, cs_num_type, operation,
 617                                  result_type, direction, search, pup_num,
 618                                  if_id, pup_access_type));
 619
 620        if ((load_res == NULL) && (is_read_from_db == 1)) {
 621                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
 622                                         ("ddr3_tip_read_training_result load_res = NULL"));
 623                return MV_FAIL;
 624        }
 625        if (pup_num >= tm->num_of_bus_per_interface) {
 626                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
 627                                         ("pup_num %d not valid\n", pup_num));
 628        }
 629        if (if_id >= MAX_INTERFACE_NUM) {
 630                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
 631                                         ("if_id %d not valid\n", if_id));
 632        }
 633        if (result_type == RESULT_PER_BIT)
 634                reg_addr = mask_results_dq_reg_map;
 635        else
 636                reg_addr = mask_results_pup_reg_map;
 637        if (pup_access_type == ACCESS_TYPE_UNICAST) {
 638                start_pup = pup_num;
 639                end_pup = pup_num;
 640        } else {                /*pup_access_type == ACCESS_TYPE_MULTICAST) */
 641
 642                start_pup = 0;
 643                end_pup = tm->num_of_bus_per_interface - 1;
 644        }
 645
 646        for (pup_cnt = start_pup; pup_cnt <= end_pup; pup_cnt++) {
 647                VALIDATE_ACTIVE(tm->bus_act_mask, pup_cnt);
 648                DEBUG_TRAINING_IP_ENGINE(
 649                        DEBUG_LEVEL_TRACE,
 650                        ("if_id %d start_pup %d end_pup %d pup_cnt %d\n",
 651                         if_id, start_pup, end_pup, pup_cnt));
 652                if (result_type == RESULT_PER_BIT) {
 653                        if (bit_num == ALL_BITS_PER_PUP) {
 654                                start_reg = pup_cnt * BUS_WIDTH_IN_BITS;
 655                                end_reg = (pup_cnt + 1) * BUS_WIDTH_IN_BITS - 1;
 656                        } else {
 657                                start_reg =
 658                                        pup_cnt * BUS_WIDTH_IN_BITS + bit_num;
 659                                end_reg = pup_cnt * BUS_WIDTH_IN_BITS + bit_num;
 660                        }
 661                } else {
 662                        start_reg = pup_cnt;
 663                        end_reg = pup_cnt;
 664                }
 665
 666                interface_train_res =
 667                        ddr3_tip_get_buf_ptr(dev_num, search, result_type,
 668                                             if_id);
 669                DEBUG_TRAINING_IP_ENGINE(
 670                        DEBUG_LEVEL_TRACE,
 671                        ("start_reg %d end_reg %d interface %p\n",
 672                         start_reg, end_reg, interface_train_res));
 673                if (interface_train_res == NULL) {
 674                        DEBUG_TRAINING_IP_ENGINE(
 675                                DEBUG_LEVEL_ERROR,
 676                                ("interface_train_res is NULL\n"));
 677                        return MV_FAIL;
 678                }
 679
 680                for (reg_offset = start_reg; reg_offset <= end_reg;
 681                     reg_offset++) {
 682                        if (operation == TRAINING_LOAD_OPERATION_UNLOAD) {
 683                                if (is_read_from_db == 0) {
 684                                        CHECK_STATUS(ddr3_tip_if_read
 685                                                     (dev_num,
 686                                                      ACCESS_TYPE_UNICAST,
 687                                                      if_id,
 688                                                      reg_addr[reg_offset],
 689                                                      read_data,
 690                                                      MASK_ALL_BITS));
 691                                        if (is_check_result_validity == 1) {
 692                                                if ((read_data[if_id] &
 693                                                     0x02000000) == 0) {
 694                                                        interface_train_res
 695                                                                [reg_offset] =
 696                                                                0x02000000 +
 697                                                                64 + cons_tap;
 698                                                } else {
 699                                                        interface_train_res
 700                                                                [reg_offset] =
 701                                                                read_data
 702                                                                [if_id] +
 703                                                                cons_tap;
 704                                                }
 705                                        } else {
 706                                                interface_train_res[reg_offset]
 707                                                        = read_data[if_id] +
 708                                                        cons_tap;
 709                                        }
 710                                        DEBUG_TRAINING_IP_ENGINE
 711                                                (DEBUG_LEVEL_TRACE,
 712                                                 ("reg_offset %d value 0x%x addr %p\n",
 713                                                  reg_offset,
 714                                                  interface_train_res
 715                                                  [reg_offset],
 716                                                  &interface_train_res
 717                                                  [reg_offset]));
 718                                } else {
 719                                        *load_res =
 720                                                &interface_train_res[start_reg];
 721                                        DEBUG_TRAINING_IP_ENGINE
 722                                                (DEBUG_LEVEL_TRACE,
 723                                                 ("*load_res %p\n", *load_res));
 724                                }
 725                        } else {
 726                                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE,
 727                                                         ("not supported\n"));
 728                        }
 729                }
 730        }
 731
 732        return MV_OK;
 733}
 734
 735/*
 736 * Load all pattern to memory using ODPG
 737 */
 738int ddr3_tip_load_all_pattern_to_mem(u32 dev_num)
 739{
 740        u32 pattern = 0, if_id;
 741        struct hws_topology_map *tm = ddr3_get_topology_map();
 742
 743        for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
 744                VALIDATE_ACTIVE(tm->if_act_mask, if_id);
 745                training_result[training_stage][if_id] = TEST_SUCCESS;
 746        }
 747
 748        for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
 749                VALIDATE_ACTIVE(tm->if_act_mask, if_id);
 750                /* enable single cs */
 751                CHECK_STATUS(ddr3_tip_if_write
 752                             (dev_num, ACCESS_TYPE_UNICAST, if_id,
 753                              CS_ENABLE_REG, (1 << 3), (1 << 3)));
 754        }
 755
 756        for (pattern = 0; pattern < PATTERN_LIMIT; pattern++)
 757                ddr3_tip_load_pattern_to_mem(dev_num, pattern);
 758
 759        return MV_OK;
 760}
 761
 762/*
 763 * Wait till ODPG access is ready
 764 */
 765int is_odpg_access_done(u32 dev_num, u32 if_id)
 766{
 767        u32 poll_cnt = 0, data_value;
 768        u32 read_data[MAX_INTERFACE_NUM];
 769
 770        for (poll_cnt = 0; poll_cnt < MAX_POLLING_ITERATIONS; poll_cnt++) {
 771                CHECK_STATUS(ddr3_tip_if_read
 772                             (dev_num, ACCESS_TYPE_UNICAST, if_id,
 773                              ODPG_BIST_DONE, read_data, MASK_ALL_BITS));
 774                data_value = read_data[if_id];
 775                if (((data_value >> ODPG_BIST_DONE_BIT_OFFS) & 0x1) ==
 776                    ODPG_BIST_DONE_BIT_VALUE) {
 777                                data_value = data_value & 0xfffffffe;
 778                                CHECK_STATUS(ddr3_tip_if_write
 779                                             (dev_num, ACCESS_TYPE_UNICAST,
 780                                              if_id, ODPG_BIST_DONE, data_value,
 781                                              MASK_ALL_BITS));
 782                                break;
 783                        }
 784        }
 785
 786        if (poll_cnt >= MAX_POLLING_ITERATIONS) {
 787                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
 788                                         ("Bist Activate: poll failure 2\n"));
 789                return MV_FAIL;
 790        }
 791
 792        return MV_OK;
 793}
 794
 795/*
 796 * Load specific pattern to memory using ODPG
 797 */
 798int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern)
 799{
 800        u32 reg_data, if_id;
 801        struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
 802        struct hws_topology_map *tm = ddr3_get_topology_map();
 803
 804        /* load pattern to memory */
 805        /*
 806         * Write Tx mode, CS0, phases, Tx burst size, delay between burst,
 807         * rx pattern phases
 808         */
 809        reg_data =
 810                0x1 | (pattern_table[pattern].num_of_phases_tx << 5) |
 811                (pattern_table[pattern].tx_burst_size << 11) |
 812                (pattern_table[pattern].delay_between_bursts << 15) |
 813                (pattern_table[pattern].num_of_phases_rx << 21) | (0x1 << 25) |
 814                (effective_cs << 26);
 815        CHECK_STATUS(ddr3_tip_if_write
 816                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
 817                      ODPG_DATA_CONTROL_REG, reg_data, MASK_ALL_BITS));
 818        /* ODPG Write enable from BIST */
 819        CHECK_STATUS(ddr3_tip_if_write
 820                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
 821                      ODPG_DATA_CONTROL_REG, (0x1 | (effective_cs << 26)),
 822                      0xc000003));
 823        /* disable error injection */
 824        CHECK_STATUS(ddr3_tip_if_write
 825                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
 826                      ODPG_WRITE_DATA_ERROR_REG, 0, 0x1));
 827        /* load pattern to ODPG */
 828        ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST,
 829                                      PARAM_NOT_CARE, pattern,
 830                                      pattern_table[pattern].start_addr);
 831
 832        for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
 833                if (IS_ACTIVE(tm->if_act_mask, if_id) == 0)
 834                        continue;
 835
 836                CHECK_STATUS(ddr3_tip_if_write
 837                             (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1498,
 838                              0x3, 0xf));
 839        }
 840
 841        CHECK_STATUS(ddr3_tip_if_write
 842                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
 843                      ODPG_ENABLE_REG, 0x1 << ODPG_ENABLE_OFFS,
 844                      (0x1 << ODPG_ENABLE_OFFS)));
 845
 846        mdelay(1);
 847
 848        for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
 849                VALIDATE_ACTIVE(tm->if_act_mask, if_id);
 850                CHECK_STATUS(is_odpg_access_done(dev_num, if_id));
 851        }
 852
 853        /* Disable ODPG and stop write to memory */
 854        CHECK_STATUS(ddr3_tip_if_write
 855                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
 856                      ODPG_DATA_CONTROL_REG, (0x1 << 30), (u32) (0x3 << 30)));
 857
 858        /* return to default */
 859        CHECK_STATUS(ddr3_tip_if_write
 860                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
 861                      ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS));
 862
 863        /* Disable odt0 for CS0 training - need to adjust for multy CS */
 864        CHECK_STATUS(ddr3_tip_if_write
 865                     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x1498,
 866                      0x0, 0xf));
 867
 868        /* temporary added */
 869        mdelay(1);
 870
 871        return MV_OK;
 872}
 873
 874/*
 875 * Load specific pattern to memory using CPU
 876 */
 877int ddr3_tip_load_pattern_to_mem_by_cpu(u32 dev_num, enum hws_pattern pattern,
 878                                        u32 offset)
 879{
 880        /* eranba - TBD */
 881        return MV_OK;
 882}
 883
 884/*
 885 * Training search routine
 886 */
 887int ddr3_tip_ip_training_wrapper_int(u32 dev_num,
 888                                     enum hws_access_type access_type,
 889                                     u32 if_id,
 890                                     enum hws_access_type pup_access_type,
 891                                     u32 pup_num, u32 bit_num,
 892                                     enum hws_training_result result_type,
 893                                     enum hws_control_element control_element,
 894                                     enum hws_search_dir search_dir,
 895                                     enum hws_dir direction,
 896                                     u32 interface_mask, u32 init_value_l2h,
 897                                     u32 init_value_h2l, u32 num_iter,
 898                                     enum hws_pattern pattern,
 899                                     enum hws_edge_compare edge_comp,
 900                                     enum hws_ddr_cs train_cs_type, u32 cs_num,
 901                                     enum hws_training_ip_stat *train_status)
 902{
 903        u32 interface_num = 0, start_if, end_if, init_value_used;
 904        enum hws_search_dir search_dir_id, start_search, end_search;
 905        enum hws_edge_compare edge_comp_used;
 906        u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0);
 907        struct hws_topology_map *tm = ddr3_get_topology_map();
 908
 909        if (train_status == NULL) {
 910                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
 911                                         ("train_status is NULL\n"));
 912                return MV_FAIL;
 913        }
 914
 915        if ((train_cs_type > CS_NON_SINGLE) ||
 916            (edge_comp >= EDGE_PFP) ||
 917            (pattern >= PATTERN_LIMIT) ||
 918            (direction > OPER_WRITE_AND_READ) ||
 919            (search_dir > HWS_HIGH2LOW) ||
 920            (control_element > HWS_CONTROL_ELEMENT_DQS_SKEW) ||
 921            (result_type > RESULT_PER_BYTE) ||
 922            (pup_num >= tm->num_of_bus_per_interface) ||
 923            (pup_access_type > ACCESS_TYPE_MULTICAST) ||
 924            (if_id > 11) || (access_type > ACCESS_TYPE_MULTICAST)) {
 925                DEBUG_TRAINING_IP_ENGINE(
 926                        DEBUG_LEVEL_ERROR,
 927                        ("wrong parameter train_cs_type %d edge_comp %d pattern %d direction %d search_dir %d control_element %d result_type %d pup_num %d pup_access_type %d if_id %d access_type %d\n",
 928                         train_cs_type, edge_comp, pattern, direction,
 929                         search_dir, control_element, result_type, pup_num,
 930                         pup_access_type, if_id, access_type));
 931                return MV_FAIL;
 932        }
 933
 934        if (edge_comp == EDGE_FPF) {
 935                start_search = HWS_LOW2HIGH;
 936                end_search = HWS_HIGH2LOW;
 937                edge_comp_used = EDGE_FP;
 938        } else {
 939                start_search = search_dir;
 940                end_search = search_dir;
 941                edge_comp_used = edge_comp;
 942        }
 943
 944        for (search_dir_id = start_search; search_dir_id <= end_search;
 945             search_dir_id++) {
 946                init_value_used = (search_dir_id == HWS_LOW2HIGH) ?
 947                        init_value_l2h : init_value_h2l;
 948                DEBUG_TRAINING_IP_ENGINE(
 949                        DEBUG_LEVEL_TRACE,
 950                        ("dev_num %d, access_type %d, if_id %d, pup_access_type %d,pup_num %d, result_type %d, control_element %d search_dir_id %d, direction %d, interface_mask %d,init_value_used %d, num_iter %d, pattern %d, edge_comp_used %d, train_cs_type %d, cs_num %d\n",
 951                         dev_num, access_type, if_id, pup_access_type, pup_num,
 952                         result_type, control_element, search_dir_id,
 953                         direction, interface_mask, init_value_used, num_iter,
 954                         pattern, edge_comp_used, train_cs_type, cs_num));
 955
 956                ddr3_tip_ip_training(dev_num, access_type, if_id,
 957                                     pup_access_type, pup_num, result_type,
 958                                     control_element, search_dir_id, direction,
 959                                     interface_mask, init_value_used, num_iter,
 960                                     pattern, edge_comp_used, train_cs_type,
 961                                     cs_num, train_status);
 962                if (access_type == ACCESS_TYPE_MULTICAST) {
 963                        start_if = 0;
 964                        end_if = MAX_INTERFACE_NUM - 1;
 965                } else {
 966                        start_if = if_id;
 967                        end_if = if_id;
 968                }
 969
 970                for (interface_num = start_if; interface_num <= end_if;
 971                     interface_num++) {
 972                        VALIDATE_ACTIVE(tm->if_act_mask, interface_num);
 973                        cs_num = 0;
 974                        CHECK_STATUS(ddr3_tip_read_training_result
 975                                     (dev_num, interface_num, pup_access_type,
 976                                      pup_num, bit_num, search_dir_id,
 977                                      direction, result_type,
 978                                      TRAINING_LOAD_OPERATION_UNLOAD,
 979                                      train_cs_type, NULL, 0, cons_tap,
 980                                      0));
 981                }
 982        }
 983
 984        return MV_OK;
 985}
 986
 987/*
 988 * Training search & read result routine
 989 */
 990int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type,
 991                                 u32 if_id,
 992                                 enum hws_access_type pup_access_type,
 993                                 u32 pup_num,
 994                                 enum hws_training_result result_type,
 995                                 enum hws_control_element control_element,
 996                                 enum hws_search_dir search_dir,
 997                                 enum hws_dir direction, u32 interface_mask,
 998                                 u32 init_value_l2h, u32 init_value_h2l,
 999                                 u32 num_iter, enum hws_pattern pattern,
1000                                 enum hws_edge_compare edge_comp,
1001                                 enum hws_ddr_cs train_cs_type, u32 cs_num,
1002                                 enum hws_training_ip_stat *train_status)
1003{
1004        u8 e1, e2;
1005        u32 interface_cnt, bit_id, start_if, end_if, bit_end = 0;
1006        u32 *result[HWS_SEARCH_DIR_LIMIT] = { 0 };
1007        u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0);
1008        u8 bit_bit_mask[MAX_BUS_NUM] = { 0 }, bit_bit_mask_active = 0;
1009        u8 pup_id;
1010        struct hws_topology_map *tm = ddr3_get_topology_map();
1011
1012        if (pup_num >= tm->num_of_bus_per_interface) {
1013                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
1014                                         ("pup_num %d not valid\n", pup_num));
1015        }
1016
1017        if (if_id >= MAX_INTERFACE_NUM) {
1018                DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
1019                                         ("if_id %d not valid\n", if_id));
1020        }
1021
1022        CHECK_STATUS(ddr3_tip_ip_training_wrapper_int
1023                     (dev_num, access_type, if_id, pup_access_type, pup_num,
1024                      ALL_BITS_PER_PUP, result_type, control_element,
1025                      search_dir, direction, interface_mask, init_value_l2h,
1026                      init_value_h2l, num_iter, pattern, edge_comp,
1027                      train_cs_type, cs_num, train_status));
1028
1029        if (access_type == ACCESS_TYPE_MULTICAST) {
1030                start_if = 0;
1031                end_if = MAX_INTERFACE_NUM - 1;
1032        } else {
1033                start_if = if_id;
1034                end_if = if_id;
1035        }
1036
1037        for (interface_cnt = start_if; interface_cnt <= end_if;
1038             interface_cnt++) {
1039                VALIDATE_ACTIVE(tm->if_act_mask, interface_cnt);
1040                for (pup_id = 0;
1041                     pup_id <= (tm->num_of_bus_per_interface - 1); pup_id++) {
1042                        VALIDATE_ACTIVE(tm->bus_act_mask, pup_id);
1043                        if (result_type == RESULT_PER_BIT)
1044                                bit_end = BUS_WIDTH_IN_BITS - 1;
1045                        else
1046                                bit_end = 0;
1047
1048                        bit_bit_mask[pup_id] = 0;
1049                        for (bit_id = 0; bit_id <= bit_end; bit_id++) {
1050                                enum hws_search_dir search_dir_id;
1051                                for (search_dir_id = HWS_LOW2HIGH;
1052                                     search_dir_id <= HWS_HIGH2LOW;
1053                                     search_dir_id++) {
1054                                        CHECK_STATUS
1055                                                (ddr3_tip_read_training_result
1056                                                 (dev_num, interface_cnt,
1057                                                  ACCESS_TYPE_UNICAST, pup_id,
1058                                                  bit_id, search_dir_id,
1059                                                  direction, result_type,
1060                                                  TRAINING_LOAD_OPERATION_UNLOAD,
1061                                                  CS_SINGLE,
1062                                                  &result[search_dir_id],
1063                                                  1, 0, 0));
1064                                }
1065                                e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0],
1066                                                    EDGE_1);
1067                                e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0],
1068                                                    EDGE_1);
1069                                DEBUG_TRAINING_IP_ENGINE(
1070                                        DEBUG_LEVEL_INFO,
1071                                        ("wrapper if_id %d pup_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n",
1072                                         interface_cnt, pup_id, bit_id,
1073                                         result[HWS_LOW2HIGH][0], e1,
1074                                         result[HWS_HIGH2LOW][0], e2));
1075                                /* TBD validate is valid only for tx */
1076                                if (VALIDATE_TRAINING_LIMIT(e1, e2) == 1 &&
1077                                    GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) &&
1078                                    GET_LOCK_RESULT(result[HWS_LOW2HIGH][0])) {
1079                                        /* Mark problem bits */
1080                                        bit_bit_mask[pup_id] |= 1 << bit_id;
1081                                        bit_bit_mask_active = 1;
1082                                }
1083                        }       /* For all bits */
1084                }               /* For all PUPs */
1085
1086                /* Fix problem bits */
1087                if (bit_bit_mask_active != 0) {
1088                        u32 *l2h_if_train_res = NULL;
1089                        u32 *h2l_if_train_res = NULL;
1090                        l2h_if_train_res =
1091                                ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH,
1092                                                     result_type,
1093                                                     interface_cnt);
1094                        h2l_if_train_res =
1095                                ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW,
1096                                                     result_type,
1097                                                     interface_cnt);
1098
1099                        ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST,
1100                                             interface_cnt,
1101                                             ACCESS_TYPE_MULTICAST,
1102                                             PARAM_NOT_CARE, result_type,
1103                                             control_element, HWS_LOW2HIGH,
1104                                             direction, interface_mask,
1105                                             num_iter / 2, num_iter / 2,
1106                                             pattern, EDGE_FP, train_cs_type,
1107                                             cs_num, train_status);
1108
1109                        for (pup_id = 0;
1110                             pup_id <= (tm->num_of_bus_per_interface - 1);
1111                             pup_id++) {
1112                                VALIDATE_ACTIVE(tm->bus_act_mask, pup_id);
1113
1114                                if (bit_bit_mask[pup_id] == 0)
1115                                        continue;
1116
1117                                for (bit_id = 0; bit_id <= bit_end; bit_id++) {
1118                                        if ((bit_bit_mask[pup_id] &
1119                                             (1 << bit_id)) == 0)
1120                                                continue;
1121                                        CHECK_STATUS
1122                                                (ddr3_tip_read_training_result
1123                                                 (dev_num, interface_cnt,
1124                                                  ACCESS_TYPE_UNICAST, pup_id,
1125                                                  bit_id, HWS_LOW2HIGH,
1126                                                  direction,
1127                                                  result_type,
1128                                                  TRAINING_LOAD_OPERATION_UNLOAD,
1129                                                  CS_SINGLE, &l2h_if_train_res,
1130                                                  0, 0, 1));
1131                                }
1132                        }
1133
1134                        ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST,
1135                                             interface_cnt,
1136                                             ACCESS_TYPE_MULTICAST,
1137                                             PARAM_NOT_CARE, result_type,
1138                                             control_element, HWS_HIGH2LOW,
1139                                             direction, interface_mask,
1140                                             num_iter / 2, num_iter / 2,
1141                                             pattern, EDGE_FP, train_cs_type,
1142                                             cs_num, train_status);
1143
1144                        for (pup_id = 0;
1145                             pup_id <= (tm->num_of_bus_per_interface - 1);
1146                             pup_id++) {
1147                                VALIDATE_ACTIVE(tm->bus_act_mask, pup_id);
1148
1149                                if (bit_bit_mask[pup_id] == 0)
1150                                        continue;
1151
1152                                for (bit_id = 0; bit_id <= bit_end; bit_id++) {
1153                                        if ((bit_bit_mask[pup_id] &
1154                                             (1 << bit_id)) == 0)
1155                                                continue;
1156                                        CHECK_STATUS
1157                                                (ddr3_tip_read_training_result
1158                                                 (dev_num, interface_cnt,
1159                                                  ACCESS_TYPE_UNICAST, pup_id,
1160                                                  bit_id, HWS_HIGH2LOW, direction,
1161                                                  result_type,
1162                                                  TRAINING_LOAD_OPERATION_UNLOAD,
1163                                                  CS_SINGLE, &h2l_if_train_res,
1164                                                  0, cons_tap, 1));
1165                                }
1166                        }
1167                }               /* if bit_bit_mask_active */
1168        }                       /* For all Interfacess */
1169
1170        return MV_OK;
1171}
1172
1173/*
1174 * Load phy values
1175 */
1176int ddr3_tip_load_phy_values(int b_load)
1177{
1178        u32 bus_cnt = 0, if_id, dev_num = 0;
1179        struct hws_topology_map *tm = ddr3_get_topology_map();
1180
1181        for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
1182                VALIDATE_ACTIVE(tm->if_act_mask, if_id);
1183                for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES();
1184                     bus_cnt++) {
1185                        VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt);
1186                        if (b_load == 1) {
1187                                CHECK_STATUS(ddr3_tip_bus_read
1188                                             (dev_num, if_id,
1189                                              ACCESS_TYPE_UNICAST, bus_cnt,
1190                                              DDR_PHY_DATA,
1191                                              WRITE_CENTRALIZATION_PHY_REG +
1192                                              (effective_cs *
1193                                               CS_REGISTER_ADDR_OFFSET),
1194                                              &phy_reg_bk[if_id][bus_cnt]
1195                                              [0]));
1196                                CHECK_STATUS(ddr3_tip_bus_read
1197                                             (dev_num, if_id,
1198                                              ACCESS_TYPE_UNICAST, bus_cnt,
1199                                              DDR_PHY_DATA,
1200                                              RL_PHY_REG +
1201                                              (effective_cs *
1202                                               CS_REGISTER_ADDR_OFFSET),
1203                                              &phy_reg_bk[if_id][bus_cnt]
1204                                              [1]));
1205                                CHECK_STATUS(ddr3_tip_bus_read
1206                                             (dev_num, if_id,
1207                                              ACCESS_TYPE_UNICAST, bus_cnt,
1208                                              DDR_PHY_DATA,
1209                                              READ_CENTRALIZATION_PHY_REG +
1210                                              (effective_cs *
1211                                               CS_REGISTER_ADDR_OFFSET),
1212                                              &phy_reg_bk[if_id][bus_cnt]
1213                                              [2]));
1214                        } else {
1215                                CHECK_STATUS(ddr3_tip_bus_write
1216                                             (dev_num, ACCESS_TYPE_UNICAST,
1217                                              if_id, ACCESS_TYPE_UNICAST,
1218                                              bus_cnt, DDR_PHY_DATA,
1219                                              WRITE_CENTRALIZATION_PHY_REG +
1220                                              (effective_cs *
1221                                               CS_REGISTER_ADDR_OFFSET),
1222                                              phy_reg_bk[if_id][bus_cnt]
1223                                              [0]));
1224                                CHECK_STATUS(ddr3_tip_bus_write
1225                                             (dev_num, ACCESS_TYPE_UNICAST,
1226                                              if_id, ACCESS_TYPE_UNICAST,
1227                                              bus_cnt, DDR_PHY_DATA,
1228                                              RL_PHY_REG +
1229                                              (effective_cs *
1230                                               CS_REGISTER_ADDR_OFFSET),
1231                                              phy_reg_bk[if_id][bus_cnt]
1232                                              [1]));
1233                                CHECK_STATUS(ddr3_tip_bus_write
1234                                             (dev_num, ACCESS_TYPE_UNICAST,
1235                                              if_id, ACCESS_TYPE_UNICAST,
1236                                              bus_cnt, DDR_PHY_DATA,
1237                                              READ_CENTRALIZATION_PHY_REG +
1238                                              (effective_cs *
1239                                               CS_REGISTER_ADDR_OFFSET),
1240                                              phy_reg_bk[if_id][bus_cnt]
1241                                              [2]));
1242                        }
1243                }
1244        }
1245
1246        return MV_OK;
1247}
1248
1249int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type,
1250                              enum hws_search_dir search_dir,
1251                              enum hws_dir direction,
1252                              enum hws_edge_compare edge,
1253                              u32 init_val1, u32 init_val2,
1254                              u32 num_of_iterations,
1255                              u32 start_pattern, u32 end_pattern)
1256{
1257        u32 pattern, if_id, pup_id;
1258        enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM];
1259        u32 *res = NULL;
1260        u32 search_state = 0;
1261        struct hws_topology_map *tm = ddr3_get_topology_map();
1262
1263        ddr3_tip_load_phy_values(1);
1264
1265        for (pattern = start_pattern; pattern <= end_pattern; pattern++) {
1266                for (search_state = 0; search_state < HWS_SEARCH_DIR_LIMIT;
1267                     search_state++) {
1268                        ddr3_tip_ip_training_wrapper(dev_num,
1269                                                     ACCESS_TYPE_MULTICAST, 0,
1270                                                     ACCESS_TYPE_MULTICAST, 0,
1271                                                     result_type,
1272                                                     HWS_CONTROL_ELEMENT_ADLL,
1273                                                     search_dir, direction,
1274                                                     0xfff, init_val1,
1275                                                     init_val2,
1276                                                     num_of_iterations, pattern,
1277                                                     edge, CS_SINGLE,
1278                                                     PARAM_NOT_CARE,
1279                                                     train_status);
1280
1281                        for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
1282                             if_id++) {
1283                                VALIDATE_ACTIVE(tm->if_act_mask, if_id);
1284                                for (pup_id = 0; pup_id <
1285                                             tm->num_of_bus_per_interface;
1286                                     pup_id++) {
1287                                        VALIDATE_ACTIVE(tm->bus_act_mask,
1288                                                        pup_id);
1289                                        CHECK_STATUS
1290                                                (ddr3_tip_read_training_result
1291                                                 (dev_num, if_id,
1292                                                  ACCESS_TYPE_UNICAST, pup_id,
1293                                                  ALL_BITS_PER_PUP,
1294                                                  search_state,
1295                                                  direction, result_type,
1296                                                  TRAINING_LOAD_OPERATION_UNLOAD,
1297                                                  CS_SINGLE, &res, 1, 0,
1298                                                  0));
1299                                        if (result_type == RESULT_PER_BYTE) {
1300                                                DEBUG_TRAINING_IP_ENGINE
1301                                                        (DEBUG_LEVEL_INFO,
1302                                                         ("search_state %d if_id %d pup_id %d 0x%x\n",
1303                                                          search_state, if_id,
1304                                                          pup_id, res[0]));
1305                                        } else {
1306                                                DEBUG_TRAINING_IP_ENGINE
1307                                                        (DEBUG_LEVEL_INFO,
1308                                                         ("search_state %d if_id %d pup_id %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
1309                                                          search_state, if_id,
1310                                                          pup_id, res[0],
1311                                                          res[1], res[2],
1312                                                          res[3], res[4],
1313                                                          res[5], res[6],
1314                                                          res[7]));
1315                                        }
1316                                }
1317                        }       /* interface */
1318                }               /* search */
1319        }                       /* pattern */
1320
1321        ddr3_tip_load_phy_values(0);
1322
1323        return MV_OK;
1324}
1325
1326struct pattern_info *ddr3_tip_get_pattern_table()
1327{
1328        struct hws_topology_map *tm = ddr3_get_topology_map();
1329
1330        if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0)
1331                return pattern_table_32;
1332        else
1333                return pattern_table_16;
1334}
1335
1336u16 *ddr3_tip_get_mask_results_dq_reg()
1337{
1338        struct hws_topology_map *tm = ddr3_get_topology_map();
1339
1340        if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
1341                return mask_results_dq_reg_map_pup3_ecc;
1342        else
1343                return mask_results_dq_reg_map;
1344}
1345
1346u16 *ddr3_tip_get_mask_results_pup_reg_map()
1347{
1348        struct hws_topology_map *tm = ddr3_get_topology_map();
1349
1350        if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
1351                return mask_results_pup_reg_map_pup3_ecc;
1352        else
1353                return mask_results_pup_reg_map;
1354}
1355