1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) Marvell International Ltd. and its affiliates 4 */ 5 6#include "ddr3_init.h" 7#include "mv_ddr_regs.h" 8#include "ddr_training_ip_db.h" 9 10#define PATTERN_1 0x55555555 11#define PATTERN_2 0xaaaaaaaa 12 13#define VALIDATE_TRAINING_LIMIT(e1, e2) \ 14 ((((e2) - (e1) + 1) > 33) && ((e1) < 67)) 15 16u32 phy_reg_bk[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; 17 18u32 training_res[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS * 19 HWS_SEARCH_DIR_LIMIT]; 20u8 byte_status[MAX_INTERFACE_NUM][MAX_BUS_NUM]; /* holds the bit status in the byte in wrapper function*/ 21 22u16 mask_results_dq_reg_map[] = { 23 RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG, 24 RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG, 25 RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG, 26 RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG, 27 RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG, 28 RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG, 29 RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG, 30 RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG, 31 RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG, 32 RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG, 33 RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG, 34 RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_BIT_7_REG, 35 RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG, 36 RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG, 37 RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG, 38 RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG, 39 RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG, 40 RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, 41 RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, 42 RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, 43#if MAX_BUS_NUM == 9 44 RESULT_CONTROL_PUP_5_BIT_0_REG, RESULT_CONTROL_PUP_5_BIT_1_REG, 45 RESULT_CONTROL_PUP_5_BIT_2_REG, RESULT_CONTROL_PUP_5_BIT_3_REG, 46 RESULT_CONTROL_PUP_5_BIT_4_REG, RESULT_CONTROL_PUP_5_BIT_5_REG, 47 RESULT_CONTROL_PUP_5_BIT_6_REG, RESULT_CONTROL_PUP_5_BIT_7_REG, 48 RESULT_CONTROL_PUP_6_BIT_0_REG, RESULT_CONTROL_PUP_6_BIT_1_REG, 49 RESULT_CONTROL_PUP_6_BIT_2_REG, RESULT_CONTROL_PUP_6_BIT_3_REG, 50 RESULT_CONTROL_PUP_6_BIT_4_REG, RESULT_CONTROL_PUP_6_BIT_5_REG, 51 RESULT_CONTROL_PUP_6_BIT_6_REG, RESULT_CONTROL_PUP_6_BIT_7_REG, 52 RESULT_CONTROL_PUP_7_BIT_0_REG, RESULT_CONTROL_PUP_7_BIT_1_REG, 53 RESULT_CONTROL_PUP_7_BIT_2_REG, RESULT_CONTROL_PUP_7_BIT_3_REG, 54 RESULT_CONTROL_PUP_7_BIT_4_REG, RESULT_CONTROL_PUP_7_BIT_5_REG, 55 RESULT_CONTROL_PUP_7_BIT_6_REG, RESULT_CONTROL_PUP_7_BIT_7_REG, 56 RESULT_CONTROL_PUP_8_BIT_0_REG, RESULT_CONTROL_PUP_8_BIT_1_REG, 57 RESULT_CONTROL_PUP_8_BIT_2_REG, RESULT_CONTROL_PUP_8_BIT_3_REG, 58 RESULT_CONTROL_PUP_8_BIT_4_REG, RESULT_CONTROL_PUP_8_BIT_5_REG, 59 RESULT_CONTROL_PUP_8_BIT_6_REG, RESULT_CONTROL_PUP_8_BIT_7_REG, 60#endif 61 0xffff 62}; 63 64u16 mask_results_pup_reg_map[] = { 65 RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG, 66 RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_3_REG, 67 RESULT_CONTROL_BYTE_PUP_4_REG, 68#if MAX_BUS_NUM == 9 69 RESULT_CONTROL_BYTE_PUP_5_REG, RESULT_CONTROL_BYTE_PUP_6_REG, 70 RESULT_CONTROL_BYTE_PUP_7_REG, RESULT_CONTROL_BYTE_PUP_8_REG, 71#endif 72 0xffff 73}; 74 75#if MAX_BUS_NUM == 5 76u16 mask_results_dq_reg_map_pup3_ecc[] = { 77 RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG, 78 RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG, 79 RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG, 80 RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG, 81 RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG, 82 RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG, 83 RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG, 84 RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG, 85 RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG, 86 RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG, 87 RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG, 88 RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_BIT_7_REG, 89 RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG, 90 RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, 91 RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, 92 RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, 93 RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG, 94 RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG, 95 RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG, 96 RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG 97}; 98#endif 99 100#if MAX_BUS_NUM == 5 101u16 mask_results_pup_reg_map_pup3_ecc[] = { 102 RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG, 103 RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_4_REG, 104 RESULT_CONTROL_BYTE_PUP_4_REG 105}; 106#endif 107 108struct pattern_info pattern_table_64[] = { 109 /* 110 * num_of_phases_tx, tx_burst_size; 111 * delay_between_bursts, num_of_phases_rx, 112 * start_addr, pattern_len 113 */ 114 {0x7, 0x7, 2, 0x7, 0x00000, 8}, /* PATTERN_PBS1 */ 115 {0x7, 0x7, 2, 0x7, 0x00080, 8}, /* PATTERN_PBS2 */ 116 {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_PBS3 */ 117 {0x7, 0x7, 2, 0x7, 0x00030, 8}, /* PATTERN_TEST */ 118 {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_RL */ 119 {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_RL2 */ 120 {0x1f, 0xf, 2, 0xf, 0x00680, 32}, /* PATTERN_STATIC_PBS */ 121 {0x1f, 0xf, 2, 0xf, 0x00a80, 32}, /* PATTERN_KILLER_DQ0 */ 122 {0x1f, 0xf, 2, 0xf, 0x01280, 32}, /* PATTERN_KILLER_DQ1 */ 123 {0x1f, 0xf, 2, 0xf, 0x01a80, 32}, /* PATTERN_KILLER_DQ2 */ 124 {0x1f, 0xf, 2, 0xf, 0x02280, 32}, /* PATTERN_KILLER_DQ3 */ 125 {0x1f, 0xf, 2, 0xf, 0x02a80, 32}, /* PATTERN_KILLER_DQ4 */ 126 {0x1f, 0xf, 2, 0xf, 0x03280, 32}, /* PATTERN_KILLER_DQ5 */ 127 {0x1f, 0xf, 2, 0xf, 0x03a80, 32}, /* PATTERN_KILLER_DQ6 */ 128 {0x1f, 0xf, 2, 0xf, 0x04280, 32}, /* PATTERN_KILLER_DQ7 */ 129 {0x1f, 0xf, 2, 0xf, 0x00e80, 32}, /* PATTERN_KILLER_DQ0_64 */ 130 {0x1f, 0xf, 2, 0xf, 0x01680, 32}, /* PATTERN_KILLER_DQ1_64 */ 131 {0x1f, 0xf, 2, 0xf, 0x01e80, 32}, /* PATTERN_KILLER_DQ2_64 */ 132 {0x1f, 0xf, 2, 0xf, 0x02680, 32}, /* PATTERN_KILLER_DQ3_64 */ 133 {0x1f, 0xf, 2, 0xf, 0x02e80, 32}, /* PATTERN_KILLER_DQ4_64 */ 134 {0x1f, 0xf, 2, 0xf, 0x03680, 32}, /* PATTERN_KILLER_DQ5_64 */ 135 {0x1f, 0xf, 2, 0xf, 0x03e80, 32}, /* PATTERN_KILLER_DQ6_64 */ 136 {0x1f, 0xf, 2, 0xf, 0x04680, 32}, /* PATTERN_KILLER_DQ7_64 */ 137 {0x1f, 0xf, 2, 0xf, 0x04a80, 32}, /* PATTERN_KILLER_DQ0_INV */ 138 {0x1f, 0xf, 2, 0xf, 0x05280, 32}, /* PATTERN_KILLER_DQ1_INV */ 139 {0x1f, 0xf, 2, 0xf, 0x05a80, 32}, /* PATTERN_KILLER_DQ2_INV */ 140 {0x1f, 0xf, 2, 0xf, 0x06280, 32}, /* PATTERN_KILLER_DQ3_INV */ 141 {0x1f, 0xf, 2, 0xf, 0x06a80, 32}, /* PATTERN_KILLER_DQ4_INV */ 142 {0x1f, 0xf, 2, 0xf, 0x07280, 32}, /* PATTERN_KILLER_DQ5_INV */ 143 {0x1f, 0xf, 2, 0xf, 0x07a80, 32}, /* PATTERN_KILLER_DQ6_INV */ 144 {0x1f, 0xf, 2, 0xf, 0x08280, 32}, /* PATTERN_KILLER_DQ7_INV */ 145 {0x1f, 0xf, 2, 0xf, 0x04e80, 32}, /* PATTERN_KILLER_DQ0_INV_64 */ 146 {0x1f, 0xf, 2, 0xf, 0x05680, 32}, /* PATTERN_KILLER_DQ1_INV_64 */ 147 {0x1f, 0xf, 2, 0xf, 0x05e80, 32}, /* PATTERN_KILLER_DQ2_INV_64 */ 148 {0x1f, 0xf, 2, 0xf, 0x06680, 32}, /* PATTERN_KILLER_DQ3_INV_64 */ 149 {0x1f, 0xf, 2, 0xf, 0x06e80, 32}, /* PATTERN_KILLER_DQ4_INV_64 */ 150 {0x1f, 0xf, 2, 0xf, 0x07680, 32}, /* PATTERN_KILLER_DQ5_INV_64 */ 151 {0x1f, 0xf, 2, 0xf, 0x07e80, 32}, /* PATTERN_KILLER_DQ6_INV_64 */ 152 {0x1f, 0xf, 2, 0xf, 0x08680, 32}, /* PATTERN_KILLER_DQ7_INV_64 */ 153 {0x1f, 0xf, 2, 0xf, 0x08a80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0 */ 154 {0x1f, 0xf, 2, 0xf, 0x09280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ 155 {0x1f, 0xf, 2, 0xf, 0x09a80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ 156 {0x1f, 0xf, 2, 0xf, 0x0a280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ 157 {0x1f, 0xf, 2, 0xf, 0x0aa80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ 158 {0x1f, 0xf, 2, 0xf, 0x0b280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ 159 {0x1f, 0xf, 2, 0xf, 0x0ba80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ 160 {0x1f, 0xf, 2, 0xf, 0x0c280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ 161 {0x1f, 0xf, 2, 0xf, 0x08e80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0_64 */ 162 {0x1f, 0xf, 2, 0xf, 0x09680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1_64 */ 163 {0x1f, 0xf, 2, 0xf, 0x09e80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2_64 */ 164 {0x1f, 0xf, 2, 0xf, 0x0a680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3_64 */ 165 {0x1f, 0xf, 2, 0xf, 0x0ae80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4_64 */ 166 {0x1f, 0xf, 2, 0xf, 0x0b680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5_64 */ 167 {0x1f, 0xf, 2, 0xf, 0x0be80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6_64 */ 168 {0x1f, 0xf, 2, 0xf, 0x0c680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7_64 */ 169 {0x1f, 0xf, 2, 0xf, 0x0ca80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ 170 {0x1f, 0xf, 2, 0xf, 0x0d280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ 171 {0x1f, 0xf, 2, 0xf, 0x0da80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ 172 {0x1f, 0xf, 2, 0xf, 0x0e280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ 173 {0x1f, 0xf, 2, 0xf, 0x0ea80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ 174 {0x1f, 0xf, 2, 0xf, 0x0f280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ 175 {0x1f, 0xf, 2, 0xf, 0x0fa80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ 176 {0x1f, 0xf, 2, 0xf, 0x10280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ 177 {0x1f, 0xf, 2, 0xf, 0x0ce80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0_64 */ 178 {0x1f, 0xf, 2, 0xf, 0x0d680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1_64 */ 179 {0x1f, 0xf, 2, 0xf, 0x0de80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2_64 */ 180 {0x1f, 0xf, 2, 0xf, 0x0e680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3_64 */ 181 {0x1f, 0xf, 2, 0xf, 0x0ee80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4_64 */ 182 {0x1f, 0xf, 2, 0xf, 0x0f680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5_64 */ 183 {0x1f, 0xf, 2, 0xf, 0x0fe80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6_64 */ 184 {0x1f, 0xf, 2, 0xf, 0x10680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7_64 */ 185 {0x1f, 0xf, 2, 0xf, 0x10a80, 32}, /* PATTERN_ISI_XTALK_FREE */ 186 {0x1f, 0xf, 2, 0xf, 0x10e80, 32}, /* PATTERN_ISI_XTALK_FREE_64 */ 187 {0x1f, 0xf, 2, 0xf, 0x11280, 32}, /* PATTERN_VREF */ 188 {0x1f, 0xf, 2, 0xf, 0x11680, 32}, /* PATTERN_VREF_64 */ 189 {0x1f, 0xf, 2, 0xf, 0x11a80, 32}, /* PATTERN_VREF_INV */ 190 {0x1f, 0xf, 2, 0xf, 0x11e80, 32}, /* PATTERN_FULL_SSO_0T */ 191 {0x1f, 0xf, 2, 0xf, 0x12280, 32}, /* PATTERN_FULL_SSO_1T */ 192 {0x1f, 0xf, 2, 0xf, 0x12680, 32}, /* PATTERN_FULL_SSO_2T */ 193 {0x1f, 0xf, 2, 0xf, 0x12a80, 32}, /* PATTERN_FULL_SSO_3T */ 194 {0x1f, 0xf, 2, 0xf, 0x12e80, 32}, /* PATTERN_RESONANCE_1T */ 195 {0x1f, 0xf, 2, 0xf, 0x13280, 32}, /* PATTERN_RESONANCE_2T */ 196 {0x1f, 0xf, 2, 0xf, 0x13680, 32}, /* PATTERN_RESONANCE_3T */ 197 {0x1f, 0xf, 2, 0xf, 0x13a80, 32}, /* PATTERN_RESONANCE_4T */ 198 {0x1f, 0xf, 2, 0xf, 0x13e80, 32}, /* PATTERN_RESONANCE_5T */ 199 {0x1f, 0xf, 2, 0xf, 0x14280, 32}, /* PATTERN_RESONANCE_6T */ 200 {0x1f, 0xf, 2, 0xf, 0x14680, 32}, /* PATTERN_RESONANCE_7T */ 201 {0x1f, 0xf, 2, 0xf, 0x14a80, 32}, /* PATTERN_RESONANCE_8T */ 202 {0x1f, 0xf, 2, 0xf, 0x14e80, 32}, /* PATTERN_RESONANCE_9T */ 203 {0x1f, 0xf, 2, 0xf, 0x15280, 32}, /* PATTERN_ZERO */ 204 {0x1f, 0xf, 2, 0xf, 0x15680, 32} /* PATTERN_ONE */ 205 /* Note: actual start_address is "<< 3" of defined address */ 206}; 207 208#if defined(CONFIG_DDR4) 209struct pattern_info pattern_table_16[] = { 210 /* 211 * num tx phases, tx burst, delay between, rx pattern, 212 * start_address, pattern_len 213 */ 214 {0x1, 0x1, 2, 0x1, 0x0000, 2}, /* PATTERN_PBS1*/ 215 {0x1, 0x1, 2, 0x1, 0x0080, 2}, /* PATTERN_PBS2*/ 216 {0x1, 0x1, 2, 0x1, 0x0100, 2}, /* PATTERN_PBS3*/ 217 {0x1, 0x1, 2, 0x1, 0x0180, 2}, /* PATTERN_TEST*/ 218 {0x1, 0x1, 2, 0x1, 0x0200, 2}, /* PATTERN_RL*/ 219 {0x1, 0x1, 2, 0x1, 0x0280, 2}, /* PATTERN_RL2*/ 220 {0xf, 0x7, 2, 0x7, 0x0680, 16}, /* PATTERN_STATIC_PBS*/ 221 {0xf, 0x7, 2, 0x7, 0x0A80, 16}, /* PATTERN_KILLER_DQ0*/ 222 {0xf, 0x7, 2, 0x7, 0x0E80, 16}, /* PATTERN_KILLER_DQ1*/ 223 {0xf, 0x7, 2, 0x7, 0x1280, 16}, /* PATTERN_KILLER_DQ2*/ 224 {0xf, 0x7, 2, 0x7, 0x1680, 16}, /* PATTERN_KILLER_DQ3*/ 225 {0xf, 0x7, 2, 0x7, 0x1A80, 16}, /* PATTERN_KILLER_DQ4*/ 226 {0xf, 0x7, 2, 0x7, 0x1E80, 16}, /* PATTERN_KILLER_DQ5*/ 227 {0xf, 0x7, 2, 0x7, 0x2280, 16}, /* PATTERN_KILLER_DQ6*/ 228 {0xf, 0x7, 2, 0x7, 0x2680, 16}, /* PATTERN_KILLER_DQ7*/ 229 {0xf, 0x7, 2, 0x7, 0x2A80, 16}, /* PATTERN_KILLER_DQ0_INV*/ 230 {0xf, 0x7, 2, 0x7, 0x2E80, 16}, /* PATTERN_KILLER_DQ1_INV*/ 231 {0xf, 0x7, 2, 0x7, 0x3280, 16}, /* PATTERN_KILLER_DQ2_INV*/ 232 {0xf, 0x7, 2, 0x7, 0x3680, 16}, /* PATTERN_KILLER_DQ3_INV*/ 233 {0xf, 0x7, 2, 0x7, 0x3A80, 16}, /* PATTERN_KILLER_DQ4_INV*/ 234 {0xf, 0x7, 2, 0x7, 0x3E80, 16}, /* PATTERN_KILLER_DQ5_INV*/ 235 {0xf, 0x7, 2, 0x7, 0x4280, 16}, /* PATTERN_KILLER_DQ6_INV*/ 236 {0xf, 0x7, 2, 0x7, 0x4680, 16}, /* PATTERN_KILLER_DQ7_INV*/ 237 {0xf, 0x7, 2, 0x7, 0x4A80, 16}, /* PATTERN_VREF*/ 238 {0xf, 0x7, 2, 0x7, 0x4E80, 16}, /* PATTERN_VREF_INV*/ 239 {0xf, 0x7, 2, 0x7, 0x5280, 16}, /* PATTERN_FULL_SSO_0T*/ 240 {0xf, 0x7, 2, 0x7, 0x5680, 16}, /* PATTERN_FULL_SSO_1T*/ 241 {0xf, 0x7, 2, 0x7, 0x5A80, 16}, /* PATTERN_FULL_SSO_2T*/ 242 {0xf, 0x7, 2, 0x7, 0x5E80, 16}, /* PATTERN_FULL_SSO_3T*/ 243 {0xf, 0x7, 2, 0x7, 0x6280, 16}, /* PATTERN_ZERO */ 244 {0xf, 0x7, 2, 0x7, 0x6680, 16}, /* PATTERN_ONE */ 245 {0xf, 0x7, 2, 0x7, 0x6A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ0*/ 246 {0xf, 0x7, 2, 0x7, 0x6E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ1*/ 247 {0xf, 0x7, 2, 0x7, 0x7280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ2*/ 248 {0xf, 0x7, 2, 0x7, 0x7680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ3*/ 249 {0xf, 0x7, 2, 0x7, 0x7A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ4*/ 250 {0xf, 0x7, 2, 0x7, 0x7E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ5*/ 251 {0xf, 0x7, 2, 0x7, 0x8280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ6*/ 252 {0xf, 0x7, 2, 0x7, 0x8680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ7*/ 253 {0xf, 0x7, 2, 0x7, 0x8A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ0*/ 254 {0xf, 0x7, 2, 0x7, 0x8E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ1*/ 255 {0xf, 0x7, 2, 0x7, 0x9280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ2*/ 256 {0xf, 0x7, 2, 0x7, 0x9680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ3*/ 257 {0xf, 0x7, 2, 0x7, 0x9A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ4*/ 258 {0xf, 0x7, 2, 0x7, 0x9E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ5*/ 259 {0xf, 0x7, 2, 0x7, 0xA280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ6*/ 260 {0xf, 0x7, 2, 0x7, 0xA680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ7*/ 261 {0xf, 0x7, 2, 0x7, 0xAA80, 16}, /* PATTERN_ISI_XTALK_FREE*/ 262 {0xf, 0x7, 2, 0x7, 0xAE80, 16}, /* PATTERN_RESONANCE_1T*/ 263 {0xf, 0x7, 2, 0x7, 0xB280, 16}, /* PATTERN_RESONANCE_2T*/ 264 {0xf, 0x7, 2, 0x7, 0xB680, 16}, /* PATTERN_RESONANCE_3T*/ 265 {0xf, 0x7, 2, 0x7, 0xBA80, 16}, /* PATTERN_RESONANCE_4T*/ 266 {0xf, 0x7, 2, 0x7, 0xBE80, 16}, /* PATTERN_RESONANCE_5T*/ 267 {0xf, 0x7, 2, 0x7, 0xC280, 16}, /* PATTERN_RESONANCE_6T*/ 268 {0xf, 0x7, 2, 0x7, 0xC680, 16}, /* PATTERN_RESONANCE_7T*/ 269 {0xf, 0x7, 2, 0x7, 0xca80, 16}, /* PATTERN_RESONANCE_8T*/ 270 {0xf, 0x7, 2, 0x7, 0xce80, 16} /* PATTERN_RESONANCE_9T*/ 271 /* Note: actual start_address is "<< 3" of defined address */ 272}; 273 274struct pattern_info pattern_table_32[] = { 275 /* 276 * num tx phases, tx burst, delay between, rx pattern, 277 * start_address, pattern_len 278 */ 279 {0x3, 0x3, 2, 0x3, 0x0000, 4}, /* PATTERN_PBS1*/ 280 {0x3, 0x3, 2, 0x3, 0x0020, 4}, /* PATTERN_PBS2*/ 281 {0x3, 0x3, 2, 0x3, 0x0040, 4}, /* PATTERN_PBS3*/ 282 {0x3, 0x3, 2, 0x3, 0x0060, 4}, /* PATTERN_TEST*/ 283 {0x3, 0x3, 2, 0x3, 0x0080, 4}, /* PATTERN_RL*/ 284 {0x3, 0x3, 2, 0x3, 0x00a0, 4}, /* PATTERN_RL2*/ 285 {0x1f, 0xf, 2, 0xf, 0x00c0, 32}, /* PATTERN_STATIC_PBS*/ 286 {0x1f, 0xf, 2, 0xf, 0x00e0, 32}, /* PATTERN_KILLER_DQ0*/ 287 {0x1f, 0xf, 2, 0xf, 0x0100, 32}, /* PATTERN_KILLER_DQ1*/ 288 {0x1f, 0xf, 2, 0xf, 0x0120, 32}, /* PATTERN_KILLER_DQ2*/ 289 {0x1f, 0xf, 2, 0xf, 0x0140, 32}, /* PATTERN_KILLER_DQ3*/ 290 {0x1f, 0xf, 2, 0xf, 0x0160, 32}, /* PATTERN_KILLER_DQ4*/ 291 {0x1f, 0xf, 2, 0xf, 0x0180, 32}, /* PATTERN_KILLER_DQ5*/ 292 {0x1f, 0xf, 2, 0xf, 0x01a0, 32}, /* PATTERN_KILLER_DQ6*/ 293 {0x1f, 0xf, 2, 0xf, 0x01c0, 32}, /* PATTERN_KILLER_DQ7*/ 294 {0x1f, 0xf, 2, 0xf, 0x01e0, 32}, /* PATTERN_KILLER_DQ0_INV*/ 295 {0x1f, 0xf, 2, 0xf, 0x0200, 32}, /* PATTERN_KILLER_DQ1_INV*/ 296 {0x1f, 0xf, 2, 0xf, 0x0220, 32}, /* PATTERN_KILLER_DQ2_INV*/ 297 {0x1f, 0xf, 2, 0xf, 0x0240, 32}, /* PATTERN_KILLER_DQ3_INV*/ 298 {0x1f, 0xf, 2, 0xf, 0x0260, 32}, /* PATTERN_KILLER_DQ4_INV*/ 299 {0x1f, 0xf, 2, 0xf, 0x0280, 32}, /* PATTERN_KILLER_DQ5_INV*/ 300 {0x1f, 0xf, 2, 0xf, 0x02a0, 32}, /* PATTERN_KILLER_DQ6_INV*/ 301 {0x1f, 0xf, 2, 0xf, 0x02c0, 32}, /* PATTERN_KILLER_DQ7_INV*/ 302 {0x1f, 0xf, 2, 0xf, 0x02e0, 32}, /* PATTERN_VREF*/ 303 {0x1f, 0xf, 2, 0xf, 0x0300, 32}, /* PATTERN_VREF_INV*/ 304 {0x1f, 0xf, 2, 0xf, 0x0320, 32}, /* PATTERN_FULL_SSO_0T*/ 305 {0x1f, 0xf, 2, 0xf, 0x0340, 32}, /* PATTERN_FULL_SSO_1T*/ 306 {0x1f, 0xf, 2, 0xf, 0x0360, 32}, /* PATTERN_FULL_SSO_2T*/ 307 {0x1f, 0xf, 2, 0xf, 0x0380, 32}, /* PATTERN_FULL_SSO_3T*/ 308 {0x1f, 0xf, 2, 0xf, 0x6280, 32}, /* PATTERN_ZERO */ 309 {0x1f, 0xf, 2, 0xf, 0x6680, 32}, /* PATTERN_ONE */ 310 {0x1f, 0xf, 2, 0xf, 0x6A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0*/ 311 {0x1f, 0xf, 2, 0xf, 0x6E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1*/ 312 {0x1f, 0xf, 2, 0xf, 0x7280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2*/ 313 {0x1f, 0xf, 2, 0xf, 0x7680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3*/ 314 {0x1f, 0xf, 2, 0xf, 0x7A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4*/ 315 {0x1f, 0xf, 2, 0xf, 0x7E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5*/ 316 {0x1f, 0xf, 2, 0xf, 0x8280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6*/ 317 {0x1f, 0xf, 2, 0xf, 0x8680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7*/ 318 {0x1f, 0xf, 2, 0xf, 0x8A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0*/ 319 {0x1f, 0xf, 2, 0xf, 0x8E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1*/ 320 {0x1f, 0xf, 2, 0xf, 0x9280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2*/ 321 {0x1f, 0xf, 2, 0xf, 0x9680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3*/ 322 {0x1f, 0xf, 2, 0xf, 0x9A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4*/ 323 {0x1f, 0xf, 2, 0xf, 0x9E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5*/ 324 {0x1f, 0xf, 2, 0xf, 0xA280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6*/ 325 {0x1f, 0xf, 2, 0xf, 0xA680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7*/ 326 {0x1f, 0xf, 2, 0xf, 0xAA80, 32}, /* PATTERN_ISI_XTALK_FREE*/ 327 {0x1f, 0xf, 2, 0xf, 0xAE80, 32}, /* PATTERN_RESONANCE_1T*/ 328 {0x1f, 0xf, 2, 0xf, 0xB280, 32}, /* PATTERN_RESONANCE_2T*/ 329 {0x1f, 0xf, 2, 0xf, 0xB680, 32}, /* PATTERN_RESONANCE_3T*/ 330 {0x1f, 0xf, 2, 0xf, 0xBA80, 32}, /* PATTERN_RESONANCE_4T*/ 331 {0x1f, 0xf, 2, 0xf, 0xBE80, 32}, /* PATTERN_RESONANCE_5T*/ 332 {0x1f, 0xf, 2, 0xf, 0xC280, 32}, /* PATTERN_RESONANCE_6T*/ 333 {0x1f, 0xf, 2, 0xf, 0xC680, 32}, /* PATTERN_RESONANCE_7T*/ 334 {0x1f, 0xf, 2, 0xf, 0xca80, 32}, /* PATTERN_RESONANCE_8T*/ 335 {0x1f, 0xf, 2, 0xf, 0xce80, 32} /* PATTERN_RESONANCE_9T*/ 336 /* Note: actual start_address is "<< 3" of defined address */ 337}; 338#else /* CONFIG_DDR4 */ 339struct pattern_info pattern_table_16[] = { 340 /* 341 * num tx phases, tx burst, delay between, rx pattern, 342 * start_address, pattern_len 343 */ 344 {1, 1, 2, 1, 0x0080, 2}, /* PATTERN_PBS1 */ 345 {1, 1, 2, 1, 0x00c0, 2}, /* PATTERN_PBS2 */ 346 {1, 1, 2, 1, 0x0380, 2}, /* PATTERN_PBS3 */ 347 {1, 1, 2, 1, 0x0040, 2}, /* PATTERN_TEST */ 348 {1, 1, 2, 1, 0x0100, 2}, /* PATTERN_RL */ 349 {1, 1, 2, 1, 0x0000, 2}, /* PATTERN_RL2 */ 350 {0xf, 0x7, 2, 0x7, 0x0140, 16}, /* PATTERN_STATIC_PBS */ 351 {0xf, 0x7, 2, 0x7, 0x0190, 16}, /* PATTERN_KILLER_DQ0 */ 352 {0xf, 0x7, 2, 0x7, 0x01d0, 16}, /* PATTERN_KILLER_DQ1 */ 353 {0xf, 0x7, 2, 0x7, 0x0210, 16}, /* PATTERN_KILLER_DQ2 */ 354 {0xf, 0x7, 2, 0x7, 0x0250, 16}, /* PATTERN_KILLER_DQ3 */ 355 {0xf, 0x7, 2, 0x7, 0x0290, 16}, /* PATTERN_KILLER_DQ4 */ 356 {0xf, 0x7, 2, 0x7, 0x02d0, 16}, /* PATTERN_KILLER_DQ5 */ 357 {0xf, 0x7, 2, 0x7, 0x0310, 16}, /* PATTERN_KILLER_DQ6 */ 358 {0xf, 0x7, 2, 0x7, 0x0350, 16}, /* PATTERN_KILLER_DQ7 */ 359 {0xf, 0x7, 2, 0x7, 0x04c0, 16}, /* PATTERN_VREF */ 360 {0xf, 0x7, 2, 0x7, 0x03c0, 16}, /* PATTERN_FULL_SSO_1T */ 361 {0xf, 0x7, 2, 0x7, 0x0400, 16}, /* PATTERN_FULL_SSO_2T */ 362 {0xf, 0x7, 2, 0x7, 0x0440, 16}, /* PATTERN_FULL_SSO_3T */ 363 {0xf, 0x7, 2, 0x7, 0x0480, 16}, /* PATTERN_FULL_SSO_4T */ 364 {0xf, 7, 2, 7, 0x6280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ 365 {0xf, 7, 2, 7, 0x6680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ 366 {0xf, 7, 2, 7, 0x6A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ 367 {0xf, 7, 2, 7, 0x6E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ 368 {0xf, 7, 2, 7, 0x7280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ 369 {0xf, 7, 2, 7, 0x7680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ 370 {0xf, 7, 2, 7, 0x7A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ 371 {0xf, 7, 2, 7, 0x7E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ 372 {0xf, 7, 2, 7, 0x8280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ 373 {0xf, 7, 2, 7, 0x8680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ 374 {0xf, 7, 2, 7, 0x8A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ 375 {0xf, 7, 2, 7, 0x8E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ 376 {0xf, 7, 2, 7, 0x9280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ 377 {0xf, 7, 2, 7, 0x9680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ 378 {0xf, 7, 2, 7, 0x9A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ 379 {0xf, 7, 2, 7, 0x9E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ 380 {0xf, 7, 2, 7, 0xA280, 16} /* PATTERN_ISI_XTALK_FREE */ 381 /* Note: actual start_address is "<< 3" of defined address */ 382}; 383 384struct pattern_info pattern_table_32[] = { 385 /* 386 * num tx phases, tx burst, delay between, rx pattern, 387 * start_address, pattern_len 388 */ 389 {3, 3, 2, 3, 0x0080, 4}, /* PATTERN_PBS1 */ 390 {3, 3, 2, 3, 0x00c0, 4}, /* PATTERN_PBS2 */ 391 {3, 3, 2, 3, 0x0380, 4}, /* PATTERN_PBS3 */ 392 {3, 3, 2, 3, 0x0040, 4}, /* PATTERN_TEST */ 393 {3, 3, 2, 3, 0x0100, 4}, /* PATTERN_RL */ 394 {3, 3, 2, 3, 0x0000, 4}, /* PATTERN_RL2 */ 395 {0x1f, 0xf, 2, 0xf, 0x0140, 32}, /* PATTERN_STATIC_PBS */ 396 {0x1f, 0xf, 2, 0xf, 0x0190, 32}, /* PATTERN_KILLER_DQ0 */ 397 {0x1f, 0xf, 2, 0xf, 0x01d0, 32}, /* PATTERN_KILLER_DQ1 */ 398 {0x1f, 0xf, 2, 0xf, 0x0210, 32}, /* PATTERN_KILLER_DQ2 */ 399 {0x1f, 0xf, 2, 0xf, 0x0250, 32}, /* PATTERN_KILLER_DQ3 */ 400 {0x1f, 0xf, 2, 0xf, 0x0290, 32}, /* PATTERN_KILLER_DQ4 */ 401 {0x1f, 0xf, 2, 0xf, 0x02d0, 32}, /* PATTERN_KILLER_DQ5 */ 402 {0x1f, 0xf, 2, 0xf, 0x0310, 32}, /* PATTERN_KILLER_DQ6 */ 403 {0x1f, 0xf, 2, 0xf, 0x0350, 32}, /* PATTERN_KILLER_DQ7 */ 404 {0x1f, 0xf, 2, 0xf, 0x04c0, 32}, /* PATTERN_VREF */ 405 {0x1f, 0xf, 2, 0xf, 0x03c0, 32}, /* PATTERN_FULL_SSO_1T */ 406 {0x1f, 0xf, 2, 0xf, 0x0400, 32}, /* PATTERN_FULL_SSO_2T */ 407 {0x1f, 0xf, 2, 0xf, 0x0440, 32}, /* PATTERN_FULL_SSO_3T */ 408 {0x1f, 0xf, 2, 0xf, 0x0480, 32}, /* PATTERN_FULL_SSO_4T */ 409 {0x1f, 0xF, 2, 0xf, 0x6280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0 */ 410 {0x1f, 0xF, 2, 0xf, 0x6680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ 411 {0x1f, 0xF, 2, 0xf, 0x6A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ 412 {0x1f, 0xF, 2, 0xf, 0x6E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ 413 {0x1f, 0xF, 2, 0xf, 0x7280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ 414 {0x1f, 0xF, 2, 0xf, 0x7680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ 415 {0x1f, 0xF, 2, 0xf, 0x7A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ 416 {0x1f, 0xF, 2, 0xf, 0x7E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ 417 {0x1f, 0xF, 2, 0xf, 0x8280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ 418 {0x1f, 0xF, 2, 0xf, 0x8680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ 419 {0x1f, 0xF, 2, 0xf, 0x8A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ 420 {0x1f, 0xF, 2, 0xf, 0x8E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ 421 {0x1f, 0xF, 2, 0xf, 0x9280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ 422 {0x1f, 0xF, 2, 0xf, 0x9680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ 423 {0x1f, 0xF, 2, 0xf, 0x9A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ 424 {0x1f, 0xF, 2, 0xf, 0x9E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ 425 {0x1f, 0xF, 2, 0xf, 0xA280, 32} /* PATTERN_ISI_XTALK_FREE */ 426 /* Note: actual start_address is "<< 3" of defined address */ 427}; 428#endif /* CONFIG_DDR4 */ 429 430u32 train_dev_num; 431enum hws_ddr_cs traintrain_cs_type; 432u32 train_pup_num; 433enum hws_training_result train_result_type; 434enum hws_control_element train_control_element; 435enum hws_search_dir traine_search_dir; 436enum hws_dir train_direction; 437u32 train_if_select; 438u32 train_init_value; 439u32 train_number_iterations; 440enum hws_pattern train_pattern; 441enum hws_edge_compare train_edge_compare; 442u32 train_cs_num; 443u32 train_if_acess, train_if_id, train_pup_access; 444#if defined(CONFIG_DDR4) 445/* The counter was increased for DDR4 because of A390 DB-GP DDR4 failure */ 446u32 max_polling_for_done = 100000000; 447#else /* CONFIG_DDR4 */ 448u32 max_polling_for_done = 1000000; 449#endif /* CONFIG_DDR4 */ 450 451u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search, 452 enum hws_training_result result_type, 453 u32 interface_num) 454{ 455 u32 *buf_ptr = NULL; 456 457 buf_ptr = &training_res 458 [MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS * search + 459 interface_num * MAX_BUS_NUM * BUS_WIDTH_IN_BITS]; 460 461 return buf_ptr; 462} 463 464enum { 465 PASS, 466 FAIL 467}; 468/* 469 * IP Training search 470 * Note: for one edge search only from fail to pass, else jitter can 471 * be be entered into solution. 472 */ 473int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, 474 u32 interface_num, 475 enum hws_access_type pup_access_type, 476 u32 pup_num, enum hws_training_result result_type, 477 enum hws_control_element control_element, 478 enum hws_search_dir search_dir, enum hws_dir direction, 479 u32 interface_mask, u32 init_value, u32 num_iter, 480 enum hws_pattern pattern, 481 enum hws_edge_compare edge_comp, 482 enum hws_ddr_cs cs_type, u32 cs_num, 483 enum hws_training_ip_stat *train_status) 484{ 485 u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt, 486 reg_data, pup_id; 487 u32 tx_burst_size; 488 u32 delay_between_burst; 489 u32 rd_mode; 490 u32 data; 491 struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); 492 u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); 493 u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); 494 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); 495 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 496 497 if (pup_num >= octets_per_if_num) { 498 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 499 ("pup_num %d not valid\n", pup_num)); 500 } 501 if (interface_num >= MAX_INTERFACE_NUM) { 502 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 503 ("if_id %d not valid\n", 504 interface_num)); 505 } 506 if (train_status == NULL) { 507 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 508 ("error param 4\n")); 509 return MV_BAD_PARAM; 510 } 511 512 /* load pattern */ 513 if (cs_type == CS_SINGLE) { 514 /* All CSs to CS0 */ 515 CHECK_STATUS(ddr3_tip_if_write 516 (dev_num, access_type, interface_num, 517 DUAL_DUNIT_CFG_REG, 1 << 3, 1 << 3)); 518 /* All CSs to CS0 */ 519 CHECK_STATUS(ddr3_tip_if_write 520 (dev_num, access_type, interface_num, 521 ODPG_DATA_CTRL_REG, 522 (0x3 | (effective_cs << 26)), 0xc000003)); 523 } else { 524 CHECK_STATUS(ddr3_tip_if_write 525 (dev_num, access_type, interface_num, 526 DUAL_DUNIT_CFG_REG, 0, 1 << 3)); 527 /* CS select */ 528 CHECK_STATUS(ddr3_tip_if_write 529 (dev_num, access_type, interface_num, 530 ODPG_DATA_CTRL_REG, 0x3 | cs_num << 26, 531 0x3 | 3 << 26)); 532 } 533 534 /* load pattern to ODPG */ 535 ddr3_tip_load_pattern_to_odpg(dev_num, access_type, interface_num, 536 pattern, 537 pattern_table[pattern].start_addr); 538 tx_burst_size = (direction == OPER_WRITE) ? 539 pattern_table[pattern].tx_burst_size : 0; 540 delay_between_burst = (direction == OPER_WRITE) ? 2 : 0; 541 rd_mode = (direction == OPER_WRITE) ? 1 : 0; 542 CHECK_STATUS(ddr3_tip_configure_odpg 543 (dev_num, access_type, interface_num, direction, 544 pattern_table[pattern].num_of_phases_tx, tx_burst_size, 545 pattern_table[pattern].num_of_phases_rx, 546 delay_between_burst, rd_mode, effective_cs, STRESS_NONE, 547 DURATION_SINGLE)); 548 reg_data = (direction == OPER_READ) ? 0 : (0x3 << 30); 549 reg_data |= (direction == OPER_READ) ? 0x60 : 0xfa; 550 CHECK_STATUS(ddr3_tip_if_write 551 (dev_num, access_type, interface_num, 552 ODPG_WR_RD_MODE_ENA_REG, reg_data, 553 MASK_ALL_BITS)); 554 reg_data = (edge_comp == EDGE_PF || edge_comp == EDGE_FP) ? 0 : 1 << 6; 555 reg_data |= (edge_comp == EDGE_PF || edge_comp == EDGE_PFP) ? 556 (1 << 7) : 0; 557 558 /* change from Pass to Fail will lock the result */ 559 if (pup_access_type == ACCESS_TYPE_MULTICAST) 560 reg_data |= 0xe << 14; 561 else 562 reg_data |= pup_num << 14; 563 564 if (edge_comp == EDGE_FP) { 565 /* don't search for readl edge change, only the state */ 566 reg_data |= (0 << 20); 567 } else if (edge_comp == EDGE_FPF) { 568 reg_data |= (0 << 20); 569 } else { 570 reg_data |= (3 << 20); 571 } 572 573 CHECK_STATUS(ddr3_tip_if_write 574 (dev_num, access_type, interface_num, 575 GENERAL_TRAINING_OPCODE_REG, 576 reg_data | (0x7 << 8) | (0x7 << 11), 577 (0x3 | (0x3 << 2) | (0x3 << 6) | (1 << 5) | (0x7 << 8) | 578 (0x7 << 11) | (0xf << 14) | (0x3 << 18) | (3 << 20)))); 579 reg_data = (search_dir == HWS_LOW2HIGH) ? 0 : (1 << 8); 580 CHECK_STATUS(ddr3_tip_if_write 581 (dev_num, access_type, interface_num, OPCODE_REG0_REG(1), 582 1 | reg_data | init_value << 9 | (1 << 25) | (1 << 26), 583 0xff | (1 << 8) | (0xffff << 9) | (1 << 25) | (1 << 26))); 584 585 /* 586 * Write2_dunit(0x10b4, Number_iteration , [15:0]) 587 * Max number of iterations 588 */ 589 CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num, 590 OPCODE_REG1_REG(1), num_iter, 591 0xffff)); 592 if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW && 593 direction == OPER_READ) { 594 /* 595 * Write2_dunit(0x10c0, 0x5f , [7:0]) 596 * MC PBS Reg Address at DDR PHY 597 */ 598 reg_data = PBS_RX_BCAST_PHY_REG(effective_cs); 599 } else if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW && 600 direction == OPER_WRITE) { 601 reg_data = PBS_TX_BCAST_PHY_REG(effective_cs); 602 } else if (control_element == HWS_CONTROL_ELEMENT_ADLL && 603 direction == OPER_WRITE) { 604 /* 605 * LOOP 0x00000001 + 4*n: 606 * where n (0-3) represents M_CS number 607 */ 608 /* 609 * Write2_dunit(0x10c0, 0x1 , [7:0]) 610 * ADLL WR Reg Address at DDR PHY 611 */ 612 reg_data = CTX_PHY_REG(effective_cs); 613 } else if (control_element == HWS_CONTROL_ELEMENT_ADLL && 614 direction == OPER_READ) { 615 /* ADLL RD Reg Address at DDR PHY */ 616 reg_data = CRX_PHY_REG(effective_cs); 617 } else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW && 618 direction == OPER_WRITE) { 619 /* TBD not defined in 0.5.0 requirement */ 620 } else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW && 621 direction == OPER_READ) { 622 /* TBD not defined in 0.5.0 requirement */ 623 } 624 625 reg_data |= (0x6 << 28); 626 CHECK_STATUS(ddr3_tip_if_write 627 (dev_num, access_type, interface_num, CAL_PHY_REG(1), 628 reg_data | (init_value << 8), 629 0xff | (0xffff << 8) | (0xf << 24) | (u32) (0xf << 28))); 630 631 mask_dq_num_of_regs = octets_per_if_num * BUS_WIDTH_IN_BITS; 632 mask_pup_num_of_regs = octets_per_if_num; 633 634 if (result_type == RESULT_PER_BIT) { 635 for (index_cnt = 0; index_cnt < mask_dq_num_of_regs; 636 index_cnt++) { 637 CHECK_STATUS(ddr3_tip_if_write 638 (dev_num, access_type, interface_num, 639 mask_results_dq_reg_map[index_cnt], 0, 640 1 << 24)); 641 } 642 643 /* Mask disabled buses */ 644 for (pup_id = 0; pup_id < octets_per_if_num; 645 pup_id++) { 646 if (IS_BUS_ACTIVE(tm->bus_act_mask, pup_id) == 1) 647 continue; 648 649 for (index_cnt = (pup_id * 8); index_cnt < (pup_id + 1) * 8; index_cnt++) { 650 CHECK_STATUS(ddr3_tip_if_write 651 (dev_num, access_type, 652 interface_num, 653 mask_results_dq_reg_map 654 [index_cnt], (1 << 24), 1 << 24)); 655 } 656 } 657 658 for (index_cnt = 0; index_cnt < mask_pup_num_of_regs; 659 index_cnt++) { 660 CHECK_STATUS(ddr3_tip_if_write 661 (dev_num, access_type, interface_num, 662 mask_results_pup_reg_map[index_cnt], 663 (1 << 24), 1 << 24)); 664 } 665 } else if (result_type == RESULT_PER_BYTE) { 666 /* write to adll */ 667 for (index_cnt = 0; index_cnt < mask_pup_num_of_regs; 668 index_cnt++) { 669 CHECK_STATUS(ddr3_tip_if_write 670 (dev_num, access_type, interface_num, 671 mask_results_pup_reg_map[index_cnt], 0, 672 1 << 24)); 673 } 674 for (index_cnt = 0; index_cnt < mask_dq_num_of_regs; 675 index_cnt++) { 676 CHECK_STATUS(ddr3_tip_if_write 677 (dev_num, access_type, interface_num, 678 mask_results_dq_reg_map[index_cnt], 679 (1 << 24), (1 << 24))); 680 } 681 } 682 683 /* trigger training */ 684 mv_ddr_training_enable(); 685 686 /* wa for 16-bit mode: wait for all rfu tests to finish or timeout */ 687 mdelay(1); 688 689 /* check for training done */ 690 if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) { 691 train_status[0] = HWS_TRAINING_IP_STATUS_TIMEOUT; 692 } else { /* training done; check for pass */ 693 if (data == PASS) 694 train_status[0] = HWS_TRAINING_IP_STATUS_SUCCESS; 695 else 696 train_status[0] = HWS_TRAINING_IP_STATUS_FAIL; 697 } 698 699 ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 700 ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); 701#if defined(CONFIG_DDR4) 702 if (tm->debug_level != DEBUG_LEVEL_ERROR) 703 refresh(); 704#endif 705 706 return MV_OK; 707} 708 709/* 710 * Load expected Pattern to ODPG 711 */ 712int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type, 713 u32 if_id, enum hws_pattern pattern, 714 u32 load_addr) 715{ 716 u32 pattern_length_cnt = 0; 717 struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); 718 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 719 720 for (pattern_length_cnt = 0; 721 pattern_length_cnt < pattern_table[pattern].pattern_len; 722 pattern_length_cnt++) { /* FIXME: the ecc patch below is only for a7040 A0 */ 723 if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)/* || tm->bus_act_mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK*/) { 724 CHECK_STATUS(ddr3_tip_if_write 725 (dev_num, access_type, if_id, 726 ODPG_DATA_WR_DATA_LOW_REG, 727 pattern_table_get_word(dev_num, pattern, 728 (u8) (pattern_length_cnt)), 729 MASK_ALL_BITS)); 730 CHECK_STATUS(ddr3_tip_if_write 731 (dev_num, access_type, if_id, 732 ODPG_DATA_WR_DATA_HIGH_REG, 733 pattern_table_get_word(dev_num, pattern, 734 (u8) (pattern_length_cnt)), 735 MASK_ALL_BITS)); 736 } else { 737 CHECK_STATUS(ddr3_tip_if_write 738 (dev_num, access_type, if_id, 739 ODPG_DATA_WR_DATA_LOW_REG, 740 pattern_table_get_word(dev_num, pattern, 741 (u8) (pattern_length_cnt * 2)), 742 MASK_ALL_BITS)); 743 CHECK_STATUS(ddr3_tip_if_write 744 (dev_num, access_type, if_id, 745 ODPG_DATA_WR_DATA_HIGH_REG, 746 pattern_table_get_word(dev_num, pattern, 747 (u8) (pattern_length_cnt * 2 + 1)), 748 MASK_ALL_BITS)); 749 } 750 CHECK_STATUS(ddr3_tip_if_write 751 (dev_num, access_type, if_id, 752 ODPG_DATA_WR_ADDR_REG, pattern_length_cnt, 753 MASK_ALL_BITS)); 754 } 755 756 CHECK_STATUS(ddr3_tip_if_write 757 (dev_num, access_type, if_id, 758 ODPG_DATA_BUFFER_OFFS_REG, load_addr, MASK_ALL_BITS)); 759 760 return MV_OK; 761} 762 763/* 764 * Configure ODPG 765 */ 766int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type, 767 u32 if_id, enum hws_dir direction, u32 tx_phases, 768 u32 tx_burst_size, u32 rx_phases, 769 u32 delay_between_burst, u32 rd_mode, u32 cs_num, 770 u32 addr_stress_jump, u32 single_pattern) 771{ 772 u32 data_value = 0; 773 int ret; 774 775 data_value = ((single_pattern << 2) | (tx_phases << 5) | 776 (tx_burst_size << 11) | (delay_between_burst << 15) | 777 (rx_phases << 21) | (rd_mode << 25) | (cs_num << 26) | 778 (addr_stress_jump << 29)); 779 ret = ddr3_tip_if_write(dev_num, access_type, if_id, 780 ODPG_DATA_CTRL_REG, data_value, 0xaffffffc); 781 if (ret != MV_OK) 782 return ret; 783 784 return MV_OK; 785} 786 787int ddr3_tip_process_result(u32 *ar_result, enum hws_edge e_edge, 788 enum hws_edge_search e_edge_search, 789 u32 *edge_result) 790{ 791 u32 i, res; 792 int tap_val, max_val = -10000, min_val = 10000; 793 int lock_success = 1; 794 795 for (i = 0; i < BUS_WIDTH_IN_BITS; i++) { 796 res = GET_LOCK_RESULT(ar_result[i]); 797 if (res == 0) { 798 lock_success = 0; 799 break; 800 } 801 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 802 ("lock failed for bit %d\n", i)); 803 } 804 805 if (lock_success == 1) { 806 for (i = 0; i < BUS_WIDTH_IN_BITS; i++) { 807 tap_val = GET_TAP_RESULT(ar_result[i], e_edge); 808 if (tap_val > max_val) 809 max_val = tap_val; 810 if (tap_val < min_val) 811 min_val = tap_val; 812 if (e_edge_search == TRAINING_EDGE_MAX) 813 *edge_result = (u32) max_val; 814 else 815 *edge_result = (u32) min_val; 816 817 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 818 ("i %d ar_result[i] 0x%x tap_val %d max_val %d min_val %d Edge_result %d\n", 819 i, ar_result[i], tap_val, 820 max_val, min_val, 821 *edge_result)); 822 } 823 } else { 824 return MV_FAIL; 825 } 826 827 return MV_OK; 828} 829 830/* 831 * Read training search result 832 */ 833int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, 834 enum hws_access_type pup_access_type, 835 u32 pup_num, u32 bit_num, 836 enum hws_search_dir search, 837 enum hws_dir direction, 838 enum hws_training_result result_type, 839 enum hws_training_load_op operation, 840 u32 cs_num_type, u32 **load_res, 841 int is_read_from_db, u8 cons_tap, 842 int is_check_result_validity) 843{ 844 u32 reg_offset, pup_cnt, start_pup, end_pup, start_reg, end_reg; 845 u32 *interface_train_res = NULL; 846 u16 *reg_addr = NULL; 847 u32 read_data[MAX_INTERFACE_NUM]; 848 u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); 849 u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); 850 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); 851 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 852 853 /* 854 * Agreed assumption: all CS mask contain same number of bits, 855 * i.e. in multi CS, the number of CS per memory is the same for 856 * all pups 857 */ 858 CHECK_STATUS(ddr3_tip_if_write 859 (dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG, 860 (cs_num_type == 0) ? 1 << 3 : 0, (1 << 3))); 861 CHECK_STATUS(ddr3_tip_if_write 862 (dev_num, ACCESS_TYPE_UNICAST, if_id, 863 ODPG_DATA_CTRL_REG, (cs_num_type << 26), (3 << 26))); 864 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE, 865 ("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", 866 is_read_from_db, cs_num_type, operation, 867 result_type, direction, search, pup_num, 868 if_id, pup_access_type)); 869 870 if ((load_res == NULL) && (is_read_from_db == 1)) { 871 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 872 ("ddr3_tip_read_training_result load_res = NULL")); 873 return MV_FAIL; 874 } 875 if (pup_num >= octets_per_if_num) { 876 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 877 ("pup_num %d not valid\n", pup_num)); 878 } 879 if (if_id >= MAX_INTERFACE_NUM) { 880 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 881 ("if_id %d not valid\n", if_id)); 882 } 883 if (result_type == RESULT_PER_BIT) 884 reg_addr = mask_results_dq_reg_map; 885 else 886 reg_addr = mask_results_pup_reg_map; 887 if (pup_access_type == ACCESS_TYPE_UNICAST) { 888 start_pup = pup_num; 889 end_pup = pup_num; 890 } else { /*pup_access_type == ACCESS_TYPE_MULTICAST) */ 891 892 start_pup = 0; 893 end_pup = octets_per_if_num - 1; 894 } 895 896 for (pup_cnt = start_pup; pup_cnt <= end_pup; pup_cnt++) { 897 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_cnt); 898 DEBUG_TRAINING_IP_ENGINE( 899 DEBUG_LEVEL_TRACE, 900 ("if_id %d start_pup %d end_pup %d pup_cnt %d\n", 901 if_id, start_pup, end_pup, pup_cnt)); 902 if (result_type == RESULT_PER_BIT) { 903 if (bit_num == ALL_BITS_PER_PUP) { 904 start_reg = pup_cnt * BUS_WIDTH_IN_BITS; 905 end_reg = (pup_cnt + 1) * BUS_WIDTH_IN_BITS - 1; 906 } else { 907 start_reg = 908 pup_cnt * BUS_WIDTH_IN_BITS + bit_num; 909 end_reg = pup_cnt * BUS_WIDTH_IN_BITS + bit_num; 910 } 911 } else { 912 start_reg = pup_cnt; 913 end_reg = pup_cnt; 914 } 915 916 interface_train_res = 917 ddr3_tip_get_buf_ptr(dev_num, search, result_type, 918 if_id); 919 DEBUG_TRAINING_IP_ENGINE( 920 DEBUG_LEVEL_TRACE, 921 ("start_reg %d end_reg %d interface %p\n", 922 start_reg, end_reg, interface_train_res)); 923 if (interface_train_res == NULL) { 924 DEBUG_TRAINING_IP_ENGINE( 925 DEBUG_LEVEL_ERROR, 926 ("interface_train_res is NULL\n")); 927 return MV_FAIL; 928 } 929 930 for (reg_offset = start_reg; reg_offset <= end_reg; 931 reg_offset++) { 932 if (operation == TRAINING_LOAD_OPERATION_UNLOAD) { 933 if (is_read_from_db == 0) { 934 CHECK_STATUS(ddr3_tip_if_read 935 (dev_num, 936 ACCESS_TYPE_UNICAST, 937 if_id, 938 reg_addr[reg_offset], 939 read_data, 940 MASK_ALL_BITS)); 941 if (is_check_result_validity == 1) { 942 if ((read_data[if_id] & 943 TIP_ENG_LOCK) == 0) { 944 interface_train_res 945 [reg_offset] = 946 TIP_ENG_LOCK + 947 TIP_TX_DLL_RANGE_MAX; 948 } else { 949 interface_train_res 950 [reg_offset] = 951 read_data 952 [if_id] + 953 cons_tap; 954 } 955 } else { 956 interface_train_res[reg_offset] 957 = read_data[if_id] + 958 cons_tap; 959 } 960 DEBUG_TRAINING_IP_ENGINE 961 (DEBUG_LEVEL_TRACE, 962 ("reg_offset %d value 0x%x addr %p\n", 963 reg_offset, 964 interface_train_res 965 [reg_offset], 966 &interface_train_res 967 [reg_offset])); 968 } else { 969 *load_res = 970 &interface_train_res[start_reg]; 971 DEBUG_TRAINING_IP_ENGINE 972 (DEBUG_LEVEL_TRACE, 973 ("*load_res %p\n", *load_res)); 974 } 975 } else { 976 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE, 977 ("not supported\n")); 978 } 979 } 980 } 981#if defined(CONFIG_DDR4) 982 if (tm->debug_level != DEBUG_LEVEL_ERROR) 983 refresh(); 984#endif 985 986 return MV_OK; 987} 988 989/* 990 * Load all pattern to memory using ODPG 991 */ 992int ddr3_tip_load_all_pattern_to_mem(u32 dev_num) 993{ 994 u32 pattern = 0, if_id; 995 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 996 997 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { 998 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); 999 training_result[training_stage][if_id] = TEST_SUCCESS; 1000 } 1001 1002 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { 1003 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); 1004 /* enable single cs */ 1005 CHECK_STATUS(ddr3_tip_if_write 1006 (dev_num, ACCESS_TYPE_UNICAST, if_id, 1007 DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); 1008 } 1009 1010 for (pattern = 0; pattern < PATTERN_LAST; pattern++) { 1011 if (pattern == PATTERN_TEST) 1012 continue; 1013 ddr3_tip_load_pattern_to_mem(dev_num, pattern); 1014 } 1015 1016 return MV_OK; 1017} 1018 1019/* 1020 * Load specific pattern to memory using ODPG 1021 */ 1022int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern) 1023{ 1024 u32 reg_data, if_id; 1025 struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); 1026 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 1027 1028 /* load pattern to memory */ 1029 /* 1030 * Write Tx mode, CS0, phases, Tx burst size, delay between burst, 1031 * rx pattern phases 1032 */ 1033 reg_data = 1034 0x1 | (pattern_table[pattern].num_of_phases_tx << 5) | 1035 (pattern_table[pattern].tx_burst_size << 11) | 1036 (pattern_table[pattern].delay_between_bursts << 15) | 1037 (pattern_table[pattern].num_of_phases_rx << 21) | (0x1 << 25) | 1038 (effective_cs << 26); 1039 CHECK_STATUS(ddr3_tip_if_write 1040 (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 1041 ODPG_DATA_CTRL_REG, reg_data, MASK_ALL_BITS)); 1042 /* ODPG Write enable from BIST */ 1043 CHECK_STATUS(ddr3_tip_if_write 1044 (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 1045 ODPG_DATA_CTRL_REG, (0x1 | (effective_cs << 26)), 1046 0xc000003)); 1047 /* disable error injection */ 1048 CHECK_STATUS(ddr3_tip_if_write 1049 (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 1050 ODPG_DATA_WR_DATA_ERR_REG, 0, 0x1)); 1051 /* load pattern to ODPG */ 1052 ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST, 1053 PARAM_NOT_CARE, pattern, 1054 pattern_table[pattern].start_addr); 1055 1056 if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { 1057 for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { 1058 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); 1059 1060 CHECK_STATUS(ddr3_tip_if_write 1061 (dev_num, ACCESS_TYPE_UNICAST, if_id, 1062 SDRAM_ODT_CTRL_HIGH_REG, 1063 0x3, 0xf)); 1064 } 1065 1066 mv_ddr_odpg_enable(); 1067 } else { 1068 CHECK_STATUS(ddr3_tip_if_write 1069 (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 1070 ODPG_DATA_CTRL_REG, (u32)(0x1 << 31), 1071 (u32)(0x1 << 31))); 1072 } 1073 mdelay(1); 1074 1075 if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) 1076 return MV_FAIL; 1077 1078 /* Disable ODPG and stop write to memory */ 1079 CHECK_STATUS(ddr3_tip_if_write 1080 (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 1081 ODPG_DATA_CTRL_REG, (0x1 << 30), (u32) (0x3 << 30))); 1082 1083 /* return to default */ 1084 CHECK_STATUS(ddr3_tip_if_write 1085 (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 1086 ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS)); 1087 1088 if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { 1089 /* Disable odt0 for CS0 training - need to adjust for multy CS */ 1090 CHECK_STATUS(ddr3_tip_if_write 1091 (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 1092 SDRAM_ODT_CTRL_HIGH_REG, 0x0, 0xf)); 1093 } 1094 /* temporary added */ 1095 mdelay(1); 1096 1097 return MV_OK; 1098} 1099 1100/* 1101 * Training search routine 1102 */ 1103int ddr3_tip_ip_training_wrapper_int(u32 dev_num, 1104 enum hws_access_type access_type, 1105 u32 if_id, 1106 enum hws_access_type pup_access_type, 1107 u32 pup_num, u32 bit_num, 1108 enum hws_training_result result_type, 1109 enum hws_control_element control_element, 1110 enum hws_search_dir search_dir, 1111 enum hws_dir direction, 1112 u32 interface_mask, u32 init_value_l2h, 1113 u32 init_value_h2l, u32 num_iter, 1114 enum hws_pattern pattern, 1115 enum hws_edge_compare edge_comp, 1116 enum hws_ddr_cs train_cs_type, u32 cs_num, 1117 enum hws_training_ip_stat *train_status) 1118{ 1119 u32 interface_num = 0, start_if, end_if, init_value_used; 1120 enum hws_search_dir search_dir_id, start_search, end_search; 1121 enum hws_edge_compare edge_comp_used; 1122 u8 cons_tap = 0; 1123 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); 1124 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 1125 1126 if (train_status == NULL) { 1127 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 1128 ("train_status is NULL\n")); 1129 return MV_FAIL; 1130 } 1131 1132 if ((train_cs_type > CS_NON_SINGLE) || 1133 (edge_comp >= EDGE_PFP) || 1134 (pattern >= PATTERN_LAST) || 1135 (direction > OPER_WRITE_AND_READ) || 1136 (search_dir > HWS_HIGH2LOW) || 1137 (control_element > HWS_CONTROL_ELEMENT_DQS_SKEW) || 1138 (result_type > RESULT_PER_BYTE) || 1139 (pup_num >= octets_per_if_num) || 1140 (pup_access_type > ACCESS_TYPE_MULTICAST) || 1141 (if_id > 11) || (access_type > ACCESS_TYPE_MULTICAST)) { 1142 DEBUG_TRAINING_IP_ENGINE( 1143 DEBUG_LEVEL_ERROR, 1144 ("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", 1145 train_cs_type, edge_comp, pattern, direction, 1146 search_dir, control_element, result_type, pup_num, 1147 pup_access_type, if_id, access_type)); 1148 return MV_FAIL; 1149 } 1150 1151 if (edge_comp == EDGE_FPF) { 1152 start_search = HWS_LOW2HIGH; 1153 end_search = HWS_HIGH2LOW; 1154 edge_comp_used = EDGE_FP; 1155 } else { 1156 start_search = search_dir; 1157 end_search = search_dir; 1158 edge_comp_used = edge_comp; 1159 } 1160 1161 for (search_dir_id = start_search; search_dir_id <= end_search; 1162 search_dir_id++) { 1163 init_value_used = (search_dir_id == HWS_LOW2HIGH) ? 1164 init_value_l2h : init_value_h2l; 1165 DEBUG_TRAINING_IP_ENGINE( 1166 DEBUG_LEVEL_TRACE, 1167 ("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", 1168 dev_num, access_type, if_id, pup_access_type, pup_num, 1169 result_type, control_element, search_dir_id, 1170 direction, interface_mask, init_value_used, num_iter, 1171 pattern, edge_comp_used, train_cs_type, cs_num)); 1172 1173 ddr3_tip_ip_training(dev_num, access_type, if_id, 1174 pup_access_type, pup_num, result_type, 1175 control_element, search_dir_id, direction, 1176 interface_mask, init_value_used, num_iter, 1177 pattern, edge_comp_used, train_cs_type, 1178 cs_num, train_status); 1179 if (access_type == ACCESS_TYPE_MULTICAST) { 1180 start_if = 0; 1181 end_if = MAX_INTERFACE_NUM - 1; 1182 } else { 1183 start_if = if_id; 1184 end_if = if_id; 1185 } 1186 1187 for (interface_num = start_if; interface_num <= end_if; 1188 interface_num++) { 1189 VALIDATE_IF_ACTIVE(tm->if_act_mask, interface_num); 1190 cs_num = 0; 1191 CHECK_STATUS(ddr3_tip_read_training_result 1192 (dev_num, interface_num, pup_access_type, 1193 pup_num, bit_num, search_dir_id, 1194 direction, result_type, 1195 TRAINING_LOAD_OPERATION_UNLOAD, 1196 train_cs_type, NULL, 0, cons_tap, 1197 0)); 1198 } 1199 } 1200 1201 return MV_OK; 1202} 1203/* 1204 * Training search & read result routine 1205 * This function implements the search algorithm 1206 * first it calls the function ddr3_tip_ip_training_wrapper_int which triggers the search from l2h and h2l 1207 * this function handles rx and tx search cases 1208 * in case of rx it only triggers the search (l2h and h2l) 1209 * in case of tx there are 3 optional algorithm phases: 1210 * phase 1: 1211 * it first triggers the search and handles the results as following (phase 1): 1212 * each bit, which defined by the search two edges (e1 or VW_L and e2 or VW_H), match on of cases: 1213 * 1. BIT_LOW_UI 0 =< VW =< 31 in case of jitter use: VW_L <= 31, VW_H <= 31 1214 * 2. BIT_HIGH_UI 32 =< VW =< 63 in case of jitter use: VW_L >= 32, VW_H >= 32 1215 * 3. BIT_SPLIT_IN VW_L <= 31 & VW_H >= 32 1216 * 4. BIT_SPLIT_OUT* VW_H < 32 & VW_L > 32 1217 * note: the VW units is adll taps 1218 * phase 2: 1219 * only bit case BIT_SPLIT_OUT requires another search (phase 2) from the middle range in two directions h2l and l2h 1220 * because only this case is not locked by the search engine in the first search trigger (phase 1). 1221 * phase 3: 1222 * each subphy is categorized according to its bits definition. 1223 * the sub-phy cases are as follows: 1224 * 1.BYTE_NOT_DEFINED the byte has not yet been categorized 1225 * 2.BYTE_HOMOGENEOUS_LOW 0 =< VW =< 31 1226 * 3.BYTE_HOMOGENEOUS_HIGH 32 =< VW =< 63 1227 * 4.BYTE_HOMOGENEOUS_SPLIT_IN VW_L <= 31 & VW_H >= 32 1228 * or the center of all bits in the byte =< 31 1229 * 5.BYTE_HOMOGENEOUS_SPLIT_OUT VW_H < 32 & VW_L > 32 1230 * 6.BYTE_SPLIT_OUT_MIX at least one bits is in split out state and one bit is in other 1231 * or the center of all bits in the byte => 32 1232 * after the two phases above a center valid window for each subphy is calculated accordingly: 1233 * center valid window = maximum center of all bits in the subphy - minimum center of all bits in the subphy. 1234 * now decisions are made in each subphy as following: 1235 * all subphys which are homogeneous remains as is 1236 * all subphys which are homogeneous low | homogeneous high and the subphy center valid window is less than 32 1237 * mark this subphy as homogeneous split in. 1238 * now the bits in the bytes which are BYTE_SPLIT_OUT_MIX needed to be reorganized and handles as following 1239 * all bits which are BIT_LOW_UI will be added with 64 adll, 1240 * this will hopefully ensures that all the bits in the sub phy can be sampled by the dqs 1241 */ 1242int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type, 1243 u32 if_id, 1244 enum hws_access_type pup_access_type, 1245 u32 pup_num, 1246 enum hws_training_result result_type, 1247 enum hws_control_element control_element, 1248 enum hws_search_dir search_dir, 1249 enum hws_dir direction, u32 interface_mask, 1250 u32 init_value_l2h, u32 init_value_h2l, 1251 u32 num_iter, enum hws_pattern pattern, 1252 enum hws_edge_compare edge_comp, 1253 enum hws_ddr_cs train_cs_type, u32 cs_num, 1254 enum hws_training_ip_stat *train_status) 1255{ 1256 u8 e1, e2; 1257 u32 bit_id, start_if, end_if, bit_end = 0; 1258 u32 *result[HWS_SEARCH_DIR_LIMIT] = { 0 }; 1259 u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0); 1260 u8 bit_bit_mask[MAX_BUS_NUM] = { 0 }, bit_bit_mask_active = 0; 1261 u8 bit_state[MAX_BUS_NUM * BUS_WIDTH_IN_BITS] = {0}; 1262 u8 h2l_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; 1263 u8 l2h_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; 1264 u8 center_subphy_adll_window[MAX_BUS_NUM]; 1265 u8 min_center_subphy_adll[MAX_BUS_NUM]; 1266 u8 max_center_subphy_adll[MAX_BUS_NUM]; 1267 u32 *l2h_if_train_res = NULL; 1268 u32 *h2l_if_train_res = NULL; 1269 enum hws_search_dir search_dir_id; 1270 int status; 1271 u32 bit_lock_result; 1272 1273 u8 sybphy_id; 1274 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); 1275 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 1276 1277 if (pup_num >= octets_per_if_num) { 1278 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 1279 ("pup_num %d not valid\n", pup_num)); 1280 } 1281 1282 if (if_id >= MAX_INTERFACE_NUM) { 1283 DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, 1284 ("if_id %d not valid\n", if_id)); 1285 } 1286 1287 status = ddr3_tip_ip_training_wrapper_int 1288 (dev_num, access_type, if_id, pup_access_type, pup_num, 1289 ALL_BITS_PER_PUP, result_type, control_element, 1290 search_dir, direction, interface_mask, init_value_l2h, 1291 init_value_h2l, num_iter, pattern, edge_comp, 1292 train_cs_type, cs_num, train_status); 1293 1294 if (MV_OK != status) 1295 return status; 1296 1297 if (access_type == ACCESS_TYPE_MULTICAST) { 1298 start_if = 0; 1299 end_if = MAX_INTERFACE_NUM - 1; 1300 } else { 1301 start_if = if_id; 1302 end_if = if_id; 1303 } 1304 1305 for (if_id = start_if; if_id <= end_if; if_id++) { 1306 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); 1307 /* zero the database */ 1308 bit_bit_mask_active = 0; /* clean the flag for level2 search */ 1309 memset(bit_state, 0, sizeof(bit_state)); 1310 /* phase 1 */ 1311 for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { 1312 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); 1313 if (result_type == RESULT_PER_BIT) 1314 bit_end = BUS_WIDTH_IN_BITS; 1315 else 1316 bit_end = 0; 1317 1318 /* zero the data base */ 1319 bit_bit_mask[sybphy_id] = 0; 1320 byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED; 1321 for (bit_id = 0; bit_id < bit_end; bit_id++) { 1322 h2l_adll_value[sybphy_id][bit_id] = 64; 1323 l2h_adll_value[sybphy_id][bit_id] = 0; 1324 for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW; 1325 search_dir_id++) { 1326 status = ddr3_tip_read_training_result 1327 (dev_num, if_id, 1328 ACCESS_TYPE_UNICAST, sybphy_id, bit_id, 1329 search_dir_id, direction, result_type, 1330 TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, 1331 &result[search_dir_id], 1, 0, 0); 1332 1333 if (MV_OK != status) 1334 return status; 1335 } 1336 1337 e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0], EDGE_1); 1338 e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0], EDGE_1); 1339 DEBUG_TRAINING_IP_ENGINE 1340 (DEBUG_LEVEL_INFO, 1341 ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n", 1342 if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1, 1343 result[HWS_HIGH2LOW][0], e2)); 1344 bit_lock_result = 1345 (GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) && 1346 GET_LOCK_RESULT(result[HWS_HIGH2LOW][0])); 1347 1348 if (bit_lock_result) { 1349 /* in case of read operation set the byte status as homogeneous low */ 1350 if (direction == OPER_READ) { 1351 byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW; 1352 } else if ((e2 - e1) > 32) { /* oper_write */ 1353 /* split out */ 1354 bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = 1355 BIT_SPLIT_OUT; 1356 byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_SPLIT_OUT; 1357 /* mark problem bits */ 1358 bit_bit_mask[sybphy_id] |= (1 << bit_id); 1359 bit_bit_mask_active = 1; 1360 DEBUG_TRAINING_IP_ENGINE 1361 (DEBUG_LEVEL_TRACE, 1362 ("if_id %d sybphy_id %d bit %d BIT_SPLIT_OUT\n", 1363 if_id, sybphy_id, bit_id)); 1364 } else { 1365 /* low ui */ 1366 if (e1 <= 31 && e2 <= 31) { 1367 bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = 1368 BIT_LOW_UI; 1369 byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW; 1370 l2h_adll_value[sybphy_id][bit_id] = e1; 1371 h2l_adll_value[sybphy_id][bit_id] = e2; 1372 DEBUG_TRAINING_IP_ENGINE 1373 (DEBUG_LEVEL_TRACE, 1374 ("if_id %d sybphy_id %d bit %d BIT_LOW_UI\n", 1375 if_id, sybphy_id, bit_id)); 1376 } 1377 /* high ui */ 1378 if (e1 >= 32 && e2 >= 32) { 1379 bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = 1380 BIT_HIGH_UI; 1381 byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_HIGH; 1382 l2h_adll_value[sybphy_id][bit_id] = e1; 1383 h2l_adll_value[sybphy_id][bit_id] = e2; 1384 DEBUG_TRAINING_IP_ENGINE 1385 (DEBUG_LEVEL_TRACE, 1386 ("if_id %d sybphy_id %d bit %d BIT_HIGH_UI\n", 1387 if_id, sybphy_id, bit_id)); 1388 } 1389 /* split in */ 1390 if (e1 <= 31 && e2 >= 32) { 1391 bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = 1392 BIT_SPLIT_IN; 1393 byte_status[if_id][sybphy_id] |= 1394 BYTE_HOMOGENEOUS_SPLIT_IN; 1395 l2h_adll_value[sybphy_id][bit_id] = e1; 1396 h2l_adll_value[sybphy_id][bit_id] = e2; 1397 DEBUG_TRAINING_IP_ENGINE 1398 (DEBUG_LEVEL_TRACE, 1399 ("if_id %d sybphy_id %d bit %d BIT_SPLIT_IN\n", 1400 if_id, sybphy_id, bit_id)); 1401 } 1402 } 1403 } else { 1404 DEBUG_TRAINING_IP_ENGINE 1405 (DEBUG_LEVEL_INFO, 1406 ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x)" 1407 "h2l 0x%x (e2 0x%x): bit cannot be categorized\n", 1408 if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1, 1409 result[HWS_HIGH2LOW][0], e2)); 1410 /* mark the byte as not defined */ 1411 byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED; 1412 break; /* continue to next pup - no reason to analyze this byte */ 1413 } 1414 } /* for all bits */ 1415 } /* for all PUPs */ 1416 1417 /* phase 2 will occur only in write operation */ 1418 if (bit_bit_mask_active != 0) { 1419 l2h_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH, result_type, if_id); 1420 h2l_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW, result_type, if_id); 1421 /* search from middle to end */ 1422 ddr3_tip_ip_training 1423 (dev_num, ACCESS_TYPE_UNICAST, 1424 if_id, ACCESS_TYPE_MULTICAST, 1425 PARAM_NOT_CARE, result_type, 1426 control_element, HWS_LOW2HIGH, 1427 direction, interface_mask, 1428 num_iter / 2, num_iter / 2, 1429 pattern, EDGE_FP, train_cs_type, 1430 cs_num, train_status); 1431 1432 for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { 1433 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); 1434 if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) { 1435 if (bit_bit_mask[sybphy_id] == 0) 1436 continue; /* this byte bits have no split out state */ 1437 1438 for (bit_id = 0; bit_id < bit_end; bit_id++) { 1439 if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0) 1440 continue; /* this bit is non split goto next bit */ 1441 1442 /* enter the result to the data base */ 1443 status = ddr3_tip_read_training_result 1444 (dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id, 1445 bit_id, HWS_LOW2HIGH, direction, result_type, 1446 TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, 1447 &l2h_if_train_res, 0, 0, 1); 1448 1449 if (MV_OK != status) 1450 return status; 1451 1452 l2h_adll_value[sybphy_id][bit_id] = 1453 l2h_if_train_res[sybphy_id * 1454 BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK; 1455 } 1456 } 1457 } 1458 /* Search from middle to start */ 1459 ddr3_tip_ip_training 1460 (dev_num, ACCESS_TYPE_UNICAST, 1461 if_id, ACCESS_TYPE_MULTICAST, 1462 PARAM_NOT_CARE, result_type, 1463 control_element, HWS_HIGH2LOW, 1464 direction, interface_mask, 1465 num_iter / 2, num_iter / 2, 1466 pattern, EDGE_FP, train_cs_type, 1467 cs_num, train_status); 1468 1469 for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { 1470 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); 1471 if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) { 1472 if (bit_bit_mask[sybphy_id] == 0) 1473 continue; 1474 1475 for (bit_id = 0; bit_id < bit_end; bit_id++) { 1476 if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0) 1477 continue; 1478 1479 status = ddr3_tip_read_training_result 1480 (dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id, 1481 bit_id, HWS_HIGH2LOW, direction, result_type, 1482 TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, 1483 &h2l_if_train_res, 0, cons_tap, 1); 1484 1485 if (MV_OK != status) 1486 return status; 1487 1488 h2l_adll_value[sybphy_id][bit_id] = 1489 h2l_if_train_res[sybphy_id * 1490 BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK; 1491 } 1492 } 1493 } 1494 } /* end if bit_bit_mask_active */ 1495 /* 1496 * phase 3 will occur only in write operation 1497 * find the maximum and the minimum center of each subphy 1498 */ 1499 for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { 1500 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); 1501 1502 if ((byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) && (direction == OPER_WRITE)) { 1503 /* clear the arrays and parameters */ 1504 center_subphy_adll_window[sybphy_id] = 0; 1505 max_center_subphy_adll[sybphy_id] = 0; 1506 min_center_subphy_adll[sybphy_id] = 64; 1507 /* find the max and min center adll value in the current subphy */ 1508 for (bit_id = 0; bit_id < bit_end; bit_id++) { 1509 /* debug print all the bit edges after alignment */ 1510 DEBUG_TRAINING_IP_ENGINE 1511 (DEBUG_LEVEL_TRACE, 1512 ("if_id %d sybphy_id %d bit %d l2h %d h2l %d\n", 1513 if_id, sybphy_id, bit_id, l2h_adll_value[sybphy_id][bit_id], 1514 h2l_adll_value[sybphy_id][bit_id])); 1515 1516 if (((l2h_adll_value[sybphy_id][bit_id] + 1517 h2l_adll_value[sybphy_id][bit_id]) / 2) > 1518 max_center_subphy_adll[sybphy_id]) 1519 max_center_subphy_adll[sybphy_id] = 1520 (l2h_adll_value[sybphy_id][bit_id] + 1521 h2l_adll_value[sybphy_id][bit_id]) / 2; 1522 if (((l2h_adll_value[sybphy_id][bit_id] + 1523 h2l_adll_value[sybphy_id][bit_id]) / 2) < 1524 min_center_subphy_adll[sybphy_id]) 1525 min_center_subphy_adll[sybphy_id] = 1526 (l2h_adll_value[sybphy_id][bit_id] + 1527 h2l_adll_value[sybphy_id][bit_id]) / 2; 1528 } 1529 1530 /* calculate the center of the current subphy */ 1531 center_subphy_adll_window[sybphy_id] = 1532 max_center_subphy_adll[sybphy_id] - 1533 min_center_subphy_adll[sybphy_id]; 1534 DEBUG_TRAINING_IP_ENGINE 1535 (DEBUG_LEVEL_TRACE, 1536 ("if_id %d sybphy_id %d min center %d max center %d center %d\n", 1537 if_id, sybphy_id, min_center_subphy_adll[sybphy_id], 1538 max_center_subphy_adll[sybphy_id], 1539 center_subphy_adll_window[sybphy_id])); 1540 } 1541 } 1542 /* 1543 * check byte state and fix bits state if needed 1544 * in case the level 1 and 2 above subphy results are 1545 * homogeneous continue to the next subphy 1546 */ 1547 for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { 1548 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); 1549 if ((byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_LOW) || 1550 (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_HIGH) || 1551 (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_IN) || 1552 (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_OUT) || 1553 (byte_status[if_id][sybphy_id] == BYTE_NOT_DEFINED)) 1554 continue; 1555 1556 /* 1557 * in case all of the bits in the current subphy are 1558 * less than 32 which will find alignment in the subphy bits 1559 * mark this subphy as homogeneous split in 1560 */ 1561 if (center_subphy_adll_window[sybphy_id] <= 31) 1562 byte_status[if_id][sybphy_id] = BYTE_HOMOGENEOUS_SPLIT_IN; 1563 1564 /* 1565 * in case the current byte is split_out and the center is bigger than 31 1566 * the byte can be aligned. in this case add 64 to the the low ui bits aligning it 1567 * to the other ui bits 1568 */ 1569 if (center_subphy_adll_window[sybphy_id] >= 32) { 1570 byte_status[if_id][sybphy_id] = BYTE_SPLIT_OUT_MIX; 1571 1572 DEBUG_TRAINING_IP_ENGINE 1573 (DEBUG_LEVEL_TRACE, 1574 ("if_id %d sybphy_id %d byte state 0x%x\n", 1575 if_id, sybphy_id, byte_status[if_id][sybphy_id])); 1576 for (bit_id = 0; bit_id < bit_end; bit_id++) { 1577 if (bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] == BIT_LOW_UI) { 1578 l2h_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64; 1579 h2l_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64; 1580 } 1581 DEBUG_TRAINING_IP_ENGINE 1582 (DEBUG_LEVEL_TRACE, 1583 ("if_id %d sybphy_id %d bit_id %d added 64 adlls\n", 1584 if_id, sybphy_id, bit_id)); 1585 } 1586 } 1587 } 1588 } /* for all interfaces */ 1589 1590 return MV_OK; 1591} 1592 1593u8 mv_ddr_tip_sub_phy_byte_status_get(u32 if_id, u32 subphy_id) 1594{ 1595 return byte_status[if_id][subphy_id]; 1596} 1597 1598void mv_ddr_tip_sub_phy_byte_status_set(u32 if_id, u32 subphy_id, u8 byte_status_data) 1599{ 1600 byte_status[if_id][subphy_id] = byte_status_data; 1601} 1602 1603/* 1604 * Load phy values 1605 */ 1606int ddr3_tip_load_phy_values(int b_load) 1607{ 1608 u32 bus_cnt = 0, if_id, dev_num = 0; 1609 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); 1610 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 1611 1612 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { 1613 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); 1614 for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { 1615 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); 1616 if (b_load == 1) { 1617 CHECK_STATUS(ddr3_tip_bus_read 1618 (dev_num, if_id, 1619 ACCESS_TYPE_UNICAST, bus_cnt, 1620 DDR_PHY_DATA, 1621 CTX_PHY_REG(effective_cs), 1622 &phy_reg_bk[if_id][bus_cnt] 1623 [0])); 1624 CHECK_STATUS(ddr3_tip_bus_read 1625 (dev_num, if_id, 1626 ACCESS_TYPE_UNICAST, bus_cnt, 1627 DDR_PHY_DATA, 1628 RL_PHY_REG(effective_cs), 1629 &phy_reg_bk[if_id][bus_cnt] 1630 [1])); 1631 CHECK_STATUS(ddr3_tip_bus_read 1632 (dev_num, if_id, 1633 ACCESS_TYPE_UNICAST, bus_cnt, 1634 DDR_PHY_DATA, 1635 CRX_PHY_REG(effective_cs), 1636 &phy_reg_bk[if_id][bus_cnt] 1637 [2])); 1638 } else { 1639 CHECK_STATUS(ddr3_tip_bus_write 1640 (dev_num, ACCESS_TYPE_UNICAST, 1641 if_id, ACCESS_TYPE_UNICAST, 1642 bus_cnt, DDR_PHY_DATA, 1643 CTX_PHY_REG(effective_cs), 1644 phy_reg_bk[if_id][bus_cnt] 1645 [0])); 1646 CHECK_STATUS(ddr3_tip_bus_write 1647 (dev_num, ACCESS_TYPE_UNICAST, 1648 if_id, ACCESS_TYPE_UNICAST, 1649 bus_cnt, DDR_PHY_DATA, 1650 RL_PHY_REG(effective_cs), 1651 phy_reg_bk[if_id][bus_cnt] 1652 [1])); 1653 CHECK_STATUS(ddr3_tip_bus_write 1654 (dev_num, ACCESS_TYPE_UNICAST, 1655 if_id, ACCESS_TYPE_UNICAST, 1656 bus_cnt, DDR_PHY_DATA, 1657 CRX_PHY_REG(effective_cs), 1658 phy_reg_bk[if_id][bus_cnt] 1659 [2])); 1660 } 1661 } 1662 } 1663 1664 return MV_OK; 1665} 1666 1667int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, 1668 enum hws_search_dir search_dir, 1669 enum hws_dir direction, 1670 enum hws_edge_compare edge, 1671 u32 init_val1, u32 init_val2, 1672 u32 num_of_iterations, 1673 u32 start_pattern, u32 end_pattern) 1674{ 1675 u32 pattern, if_id, pup_id; 1676 enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM]; 1677 u32 *res = NULL; 1678 u32 search_state = 0; 1679 u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); 1680 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 1681 1682 ddr3_tip_load_phy_values(1); 1683 1684 for (pattern = start_pattern; pattern <= end_pattern; pattern++) { 1685 for (search_state = 0; search_state < HWS_SEARCH_DIR_LIMIT; 1686 search_state++) { 1687 ddr3_tip_ip_training_wrapper(dev_num, 1688 ACCESS_TYPE_MULTICAST, 0, 1689 ACCESS_TYPE_MULTICAST, 0, 1690 result_type, 1691 HWS_CONTROL_ELEMENT_ADLL, 1692 search_dir, direction, 1693 0xfff, init_val1, 1694 init_val2, 1695 num_of_iterations, pattern, 1696 edge, CS_SINGLE, 1697 PARAM_NOT_CARE, 1698 train_status); 1699 1700 for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; 1701 if_id++) { 1702 VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); 1703 for (pup_id = 0; pup_id < 1704 octets_per_if_num; 1705 pup_id++) { 1706 VALIDATE_BUS_ACTIVE(tm->bus_act_mask, 1707 pup_id); 1708 CHECK_STATUS 1709 (ddr3_tip_read_training_result 1710 (dev_num, if_id, 1711 ACCESS_TYPE_UNICAST, pup_id, 1712 ALL_BITS_PER_PUP, 1713 search_state, 1714 direction, result_type, 1715 TRAINING_LOAD_OPERATION_UNLOAD, 1716 CS_SINGLE, &res, 1, 0, 1717 0)); 1718 if (result_type == RESULT_PER_BYTE) { 1719 DEBUG_TRAINING_IP_ENGINE 1720 (DEBUG_LEVEL_INFO, 1721 ("search_state %d if_id %d pup_id %d 0x%x\n", 1722 search_state, if_id, 1723 pup_id, res[0])); 1724 } else { 1725 DEBUG_TRAINING_IP_ENGINE 1726 (DEBUG_LEVEL_INFO, 1727 ("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", 1728 search_state, if_id, 1729 pup_id, res[0], 1730 res[1], res[2], 1731 res[3], res[4], 1732 res[5], res[6], 1733 res[7])); 1734 } 1735 } 1736 } /* interface */ 1737 } /* search */ 1738 } /* pattern */ 1739 1740 ddr3_tip_load_phy_values(0); 1741 1742 return MV_OK; 1743} 1744 1745int mv_ddr_pattern_start_addr_set(struct pattern_info *pattern_tbl, enum hws_pattern pattern, u32 addr) 1746{ 1747 pattern_tbl[pattern].start_addr = addr; 1748 1749 return 0; 1750} 1751 1752struct pattern_info *ddr3_tip_get_pattern_table() 1753{ 1754 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 1755 1756 if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) 1757 return pattern_table_64; 1758 else if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) 1759 return pattern_table_32; 1760 else 1761 return pattern_table_16; 1762} 1763 1764u16 *ddr3_tip_get_mask_results_dq_reg() 1765{ 1766#if MAX_BUS_NUM == 5 1767 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 1768 1769 if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) 1770 return mask_results_dq_reg_map_pup3_ecc; 1771 else 1772#endif 1773 return mask_results_dq_reg_map; 1774} 1775 1776u16 *ddr3_tip_get_mask_results_pup_reg_map() 1777{ 1778#if MAX_BUS_NUM == 5 1779 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 1780 1781 if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) 1782 return mask_results_pup_reg_map_pup3_ecc; 1783 else 1784#endif 1785 return mask_results_pup_reg_map; 1786} 1787 1788/* load expected dm pattern to odpg */ 1789#define LOW_NIBBLE_BYTE_MASK 0xf 1790#define HIGH_NIBBLE_BYTE_MASK 0xf0 1791int mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type, enum hws_pattern pattern, 1792 enum dm_direction dm_dir) 1793{ 1794 struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); 1795 struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); 1796 u32 pattern_len = 0; 1797 u32 data_low, data_high; 1798 u8 dm_data; 1799 1800 for (pattern_len = 0; 1801 pattern_len < pattern_table[pattern].pattern_len; 1802 pattern_len++) { 1803 if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) { 1804 data_low = pattern_table_get_word(0, pattern, (u8)pattern_len); 1805 data_high = data_low; 1806 } else { 1807 data_low = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2)); 1808 data_high = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2 + 1)); 1809 } 1810 1811 /* odpg mbus dm definition is opposite to ddr4 protocol */ 1812 if (dm_dir == DM_DIR_INVERSE) 1813 dm_data = ~((data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK)); 1814 else 1815 dm_data = (data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK); 1816 1817 ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_LOW_REG, data_low, MASK_ALL_BITS); 1818 ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_HIGH_REG, data_high, MASK_ALL_BITS); 1819 ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_ADDR_REG, 1820 pattern_len | ((dm_data & ODPG_DATA_WR_DATA_MASK) << ODPG_DATA_WR_DATA_OFFS), 1821 MASK_ALL_BITS); 1822 } 1823 1824 return MV_OK; 1825} 1826