memtune.c (172564B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: memtune.c 8 * Purpose: External memory interface tuning routines. 9 * Notes: Framework for memory tuning sequences. 10 */ 11 12 #include <soc/defs.h> 13 #include <shared/bsl.h> 14 #include <soc/cm.h> 15 #include <soc/debug.h> 16 #include <soc/error.h> 17 #include <soc/cmic.h> 18 #include <soc/mem.h> 19 #include <soc/memtune.h> 20 #include <soc/er_tcam.h> 21 22 #include <shared/alloc.h> 23 24 #if defined(BCM_TRIUMPH_SUPPORT) 25 26 #ifdef BCM_TRIUMPH_SUPPORT 27 #include <soc/triumph.h> 28 #endif /* BCM_TRIUMPH_SUPPORT */ 29 30 #ifndef NO_MEMTUNE 31 STATIC int 32 _mem_config_set(char *name, char *value) 33 { 34 if (soc_mem_config_set) { 35 return soc_mem_config_set(name, value); 36 } 37 return SOC_E_UNAVAIL; 38 } 39 #endif 40 41 #ifdef BCM_TRIUMPH_SUPPORT 42 STATIC int 43 _soc_tr_ddr_phase_sel_prog_hw_cb(soc_memtune_data_t *mt_data) 44 { 45 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 46 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 47 soc_reg_t reg; 48 uint32 oval, rval, addr; 49 50 reg = tr_mt_data->config_reg3; 51 if (mt_ctrl->phase_sel_cur != -1) { 52 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 53 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 54 oval = rval; 55 soc_reg_field_set(mt_ctrl->unit, reg, &rval, PHASE_SELf, 56 mt_ctrl->phase_sel_cur); 57 soc_reg_field_set(mt_ctrl->unit, reg, &rval, OVRD_SM_ENf, 1); 58 if (rval != oval) { 59 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 60 } 61 } 62 63 return SOC_E_NONE; 64 } 65 66 STATIC int 67 _soc_tr_ddr_latency_prog_hw_cb(soc_memtune_data_t *mt_data) 68 { 69 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 70 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 71 soc_reg_t reg; 72 uint32 oval, rval, addr, sel_early2, sel_early1; 73 74 /* EM latency setting */ 75 if (mt_ctrl->em_latency_cur != -1) { 76 reg = tr_mt_data->tmode0; 77 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 78 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 79 oval = rval; 80 soc_reg_field_set(mt_ctrl->unit, reg, &rval, EM_LATENCYf, 81 mt_ctrl->em_latency_cur & 0x7); 82 if (soc_reg_field_valid(mt_ctrl->unit, reg, EM_LATENCY8f)) { 83 soc_reg_field_set(mt_ctrl->unit, reg, &rval, EM_LATENCY8f, 84 mt_ctrl->em_latency_cur >> 3); 85 } 86 if (rval != oval) { 87 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 88 } 89 } 90 91 /* DDR latency setting */ 92 if (mt_ctrl->ddr_latency_cur != -1) { 93 /* 94 * DDR latency settings 95 * if latency == 0, select result from 2 steps earlier 96 * if latency == 1, select result from 1 step earlier 97 * if latency == 2, select regular result 98 */ 99 sel_early1 = 0; 100 sel_early2 = 0; 101 if (mt_ctrl->ddr_latency_cur == 0) { 102 sel_early2 = 1; 103 } else if (mt_ctrl->ddr_latency_cur == 1) { 104 sel_early1 = 1; 105 } 106 107 reg = tr_mt_data->config_reg2; 108 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 109 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 110 oval = rval; 111 if (mt_data->slice_mask & 0x1) { 112 soc_reg_field_set(mt_ctrl->unit, reg, &rval, SEL_EARLY2_0f, 113 sel_early2); 114 soc_reg_field_set(mt_ctrl->unit, reg, &rval, SEL_EARLY1_0f, 115 sel_early1); 116 } 117 if (mt_data->slice_mask & 0x2) { 118 soc_reg_field_set(mt_ctrl->unit, reg, &rval, SEL_EARLY2_1f, 119 sel_early2); 120 soc_reg_field_set(mt_ctrl->unit, reg, &rval, SEL_EARLY1_1f, 121 sel_early1); 122 } 123 if (rval != oval) { 124 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 125 } 126 } 127 128 return SOC_E_NONE; 129 } 130 131 STATIC int 132 _soc_tr_ddr_txrx_prog_hw_cb(soc_memtune_data_t *mt_data) 133 { 134 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 135 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 136 soc_reg_t reg; 137 uint32 oval, rval, addr; 138 139 reg = tr_mt_data->config_reg1; 140 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 141 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 142 oval = rval; 143 144 /* TX phase offset settings */ 145 if (mt_ctrl->tx_offset_cur != -1) { 146 soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_TXf, 147 mt_ctrl->tx_offset_cur & 0x0f); 148 soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_TX4f, 149 mt_ctrl->tx_offset_cur >> 4); 150 } 151 152 /* RX phase offset settings */ 153 if (mt_ctrl->rx_offset_cur != -1) { 154 soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_QKf, 155 mt_ctrl->rx_offset_cur & 0xf); 156 soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_QKBf, 157 mt_ctrl->rx_offset_cur & 0xf); 158 soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_QK4f, 159 mt_ctrl->rx_offset_cur >> 4); 160 soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_QKB4f, 161 mt_ctrl->rx_offset_cur >> 4); 162 } 163 164 if (rval != oval) { 165 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 166 } 167 168 return SOC_E_NONE; 169 } 170 171 STATIC int 172 _soc_tr_ddr_nops_prog_hw_cb(soc_memtune_data_t *mt_data) 173 { 174 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 175 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 176 soc_reg_t reg; 177 uint32 oval, rval, addr; 178 179 reg = tr_mt_data->sram_ctl; 180 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 181 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 182 oval = rval; 183 if (mt_ctrl->r2w_nops_cur != -1) { 184 soc_reg_field_set(mt_ctrl->unit, reg, &rval, NUM_R2W_NOPSf, 185 mt_ctrl->r2w_nops_cur); 186 } 187 if (mt_ctrl->w2r_nops_cur != -1) { 188 soc_reg_field_set(mt_ctrl->unit, reg, &rval, NUM_W2R_NOPSf, 189 mt_ctrl->w2r_nops_cur); 190 } 191 if (rval != oval) { 192 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 193 } 194 195 return SOC_E_NONE; 196 } 197 198 STATIC int 199 _soc_tr_ddr_per_rx_cb(soc_memtune_data_t *mt_data) 200 { 201 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 202 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 203 soc_reg_t reg; 204 uint32 rval, addr; 205 206 reg = tr_mt_data->config_reg1; 207 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 208 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 209 soc_reg_field_set(mt_ctrl->unit, reg, &rval, EN_RDFIFOf, 0); 210 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 211 soc_reg_field_set(mt_ctrl->unit, reg, &rval, EN_RDFIFOf, 1); 212 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 213 214 return SOC_E_NONE; 215 } 216 217 STATIC int 218 _soc_tr_tcam_invert_clk_prog_hw_cb(soc_memtune_data_t *mt_data) 219 { 220 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 221 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 222 soc_reg_t reg; 223 uint32 oval, rval, addr; 224 225 reg = tr_mt_data->config_reg3; 226 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 227 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 228 oval = rval; 229 if (mt_ctrl->invert_txclk_cur != -1) { 230 soc_reg_field_set(mt_ctrl->unit, reg, &rval, INVERT_TXCLKf, 231 mt_ctrl->invert_txclk_cur); 232 } 233 if (mt_ctrl->invert_rxclk_cur != -1) { 234 soc_reg_field_set(mt_ctrl->unit, reg, &rval, INVERT_RXCLKf, 235 mt_ctrl->invert_rxclk_cur); 236 } 237 if (rval != oval) { 238 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 239 } 240 241 return SOC_E_NONE; 242 } 243 244 STATIC int 245 _soc_tr_tcam_txrx_prog_hw_cb(soc_memtune_data_t *mt_data) 246 { 247 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 248 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 249 soc_reg_t reg; 250 uint32 oval, rval, addr; 251 252 reg = tr_mt_data->config_reg1; 253 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 254 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 255 oval = rval; 256 if (mt_ctrl->tx_offset_cur != -1) { 257 soc_reg_field_set(mt_ctrl->unit, reg, &rval, VCDL_TX_OFFSETf, 258 mt_ctrl->tx_offset_cur & 0x1f); 259 soc_reg_field_set(mt_ctrl->unit, reg, &rval, MSBMIDL_OFFSET_TXf, 260 mt_ctrl->tx_offset_cur >> 5); 261 } 262 if (mt_ctrl->rx_offset_cur != -1) { 263 soc_reg_field_set(mt_ctrl->unit, reg, &rval, VCDL_RX_OFFSETf, 264 mt_ctrl->rx_offset_cur & 0x1f); 265 soc_reg_field_set(mt_ctrl->unit, reg, &rval, MSBMIDL_OFFSET_RXf, 266 mt_ctrl->rx_offset_cur >> 5); 267 } 268 if (rval != oval) { 269 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 270 } 271 272 return SOC_E_NONE; 273 } 274 275 STATIC int 276 _soc_tr_tcam_dpeo_rbus_prog_hw_cb(soc_memtune_data_t *mt_data) 277 { 278 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 279 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 280 soc_reg_t reg; 281 uint32 oval, rval, addr; 282 283 reg = tr_mt_data->config_reg3; 284 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 285 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 286 oval = rval; 287 if (mt_ctrl->fcd_dpeo_cur != -1) { 288 /* 289 * DPEO_0 is connected to DPEO pin of first TCAM 290 * DPEO_1 is connected to DPEO pin of optional second TCAM 291 */ 292 if (!mt_ctrl->dpeo_sel_cur) { 293 soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_DPEO_0f, 294 mt_ctrl->fcd_dpeo_cur); 295 } else { 296 soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_DPEO_1f, 297 mt_ctrl->fcd_dpeo_cur); 298 } 299 } 300 if (mt_ctrl->fcd_rbus_cur != -1) { 301 /* use fcd_rbus + 1 for FCD_SMFL_0 and FCD_SMFL_1 */ 302 soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_SMFL_0f, 303 mt_ctrl->fcd_rbus_cur + 1); 304 soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_SMFL_1f, 305 mt_ctrl->fcd_rbus_cur + 1); 306 /* use same value for FCD_RBUS and FCD_RV */ 307 soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_RBUSf, 308 mt_ctrl->fcd_rbus_cur); 309 soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_RVf, 310 mt_ctrl->fcd_rbus_cur); 311 } 312 if (rval != oval) { 313 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 314 } 315 316 reg = tr_mt_data->etc_ctl; 317 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 318 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 319 oval = rval; 320 if (mt_ctrl->rbus_sync_dly_cur != -1) { 321 soc_reg_field_set(mt_ctrl->unit, reg, &rval, RBUS_SYNC_DLYf, 322 mt_ctrl->rbus_sync_dly_cur); 323 } 324 if (mt_ctrl->dpeo_sync_dly_cur != -1) { 325 soc_reg_field_set(mt_ctrl->unit, reg, &rval, DPEO_SYNC_DLYf, 326 mt_ctrl->dpeo_sync_dly_cur); 327 } 328 if (rval != oval) { 329 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 330 } 331 332 return SOC_E_NONE; 333 } 334 335 STATIC int 336 _soc_tr_tcam_per_tx_cb(soc_memtune_data_t *mt_data) 337 { 338 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 339 uint32 rval; 340 341 if (SAL_BOOT_SIMULATION) { 342 return SOC_E_NONE; 343 } 344 345 /* 346 * Following is the notes from DE for TCAM reset: 347 * Without this fix 348 * - we see flaky extt result for 1 board which has 349 * 36Mb__MCM_ext_tcam Eye will be completely 0 and then switch to normal 350 * (even for same rc) 351 * Why does it work? 352 * - My guess is that changing of tx, disturbs the clock going to ext_tcam 353 * and can throw PLL in ext_tcam off, and more so for dual-die ext_tcam 354 */ 355 /* coverity[result_independent_of_operands] */ 356 SOC_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, &rval)); 357 soc_reg_field_set(mt_ctrl->unit, CMIC_SOFT_RESET_REGr, &rval, 358 EXT_TCAM_RSTf, 1); 359 /* coverity[result_independent_of_operands] */ 360 SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, rval)); 361 sal_usleep(1000); 362 soc_reg_field_set(mt_ctrl->unit, CMIC_SOFT_RESET_REGr, &rval, 363 EXT_TCAM_RSTf, 0); 364 /* coverity[result_independent_of_operands] */ 365 SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, rval)); 366 sal_usleep(1000); 367 368 ((soc_tcam_info_t *)SOC_CONTROL(mt_ctrl->unit)->tcam_info)->num_tcams = 0; 369 370 return SOC_E_NONE; 371 } 372 373 STATIC int 374 _soc_tr_tcam_per_rx_cb(soc_memtune_data_t *mt_data) 375 { 376 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 377 uint32 rval; 378 379 if (SAL_BOOT_SIMULATION) { 380 return SOC_E_NONE; 381 } 382 383 /* 384 * Notes from DE for TCAM_PHY reset: 385 * Without this fix 386 * - we will see intermittent hard-failures in middle of tcam eye 387 * which leads to change in Tcam area when extt is run severa times 388 * Why does it work? 389 * - My guess is that changing of rx, changes the rx_clock in 390 * tcam_phy and disturbs the FIFO synchronizer logic 391 */ 392 /* coverity[result_independent_of_operands] */ 393 SOC_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, &rval)); 394 soc_reg_field_set(mt_ctrl->unit, CMIC_SOFT_RESET_REGr, &rval, 395 CMIC_TCAM_RST_Lf, 0); 396 /* coverity[result_independent_of_operands] */ 397 SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, rval)); 398 sal_usleep(10); 399 soc_reg_field_set(mt_ctrl->unit, CMIC_SOFT_RESET_REGr, &rval, 400 CMIC_TCAM_RST_Lf, 1); 401 /* coverity[result_independent_of_operands] */ 402 SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, rval)); 403 sal_usleep(10); 404 405 return SOC_E_NONE; 406 } 407 408 STATIC int 409 _soc_tr_sram_tune_test_cb(soc_memtune_data_t *mt_data) 410 { 411 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 412 tr_ext_sram_bist_t *sram_bist = mt_ctrl->sram_bist; 413 int loop_mode, i; 414 415 sram_bist->w2r_nops = mt_ctrl->w2r_nops_cur; 416 sram_bist->r2w_nops = mt_ctrl->r2w_nops_cur; 417 sram_bist->bg_tcam_loop_count = 1; 418 419 for (i = 0; i < mt_data->test_count; i++) { 420 for (loop_mode = 1; loop_mode < 4; loop_mode++) { 421 if (loop_mode == 1) { /* RR */ 422 sram_bist->loop_mode = 0; /* WW */ 423 SOC_IF_ERROR_RETURN 424 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, 425 mt_data->sub_interface, 426 TRUE, TRUE)); 427 SOC_IF_ERROR_RETURN 428 (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, 429 mt_data->sub_interface, 430 sram_bist)); 431 SOC_IF_ERROR_RETURN 432 (soc_triumph_ext_sram_op(mt_ctrl->unit, 433 mt_data->sub_interface, 434 sram_bist, NULL)); 435 } 436 sram_bist->loop_mode = loop_mode; 437 SOC_IF_ERROR_RETURN 438 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, 439 mt_data->sub_interface, 440 TRUE, TRUE)); 441 SOC_IF_ERROR_RETURN 442 (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, 443 mt_data->sub_interface, 444 sram_bist)); 445 SOC_IF_ERROR_RETURN 446 (soc_triumph_ext_sram_op(mt_ctrl->unit, mt_data->sub_interface, 447 sram_bist, NULL)); 448 SOC_IF_ERROR_RETURN 449 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, 450 mt_data->sub_interface, 451 FALSE, FALSE)); 452 if (sram_bist->err_cnt) { 453 mt_ctrl->cur_fail_count++; 454 if (mt_ctrl->cur_fail_count >= mt_data->max_fail_count) { 455 return SOC_E_NONE; 456 } 457 continue; 458 } 459 } 460 } 461 462 if (mt_ctrl->cur_fail_count == 0) { 463 SOC_IF_ERROR_RETURN 464 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, 465 mt_data->sub_interface, 466 TRUE, TRUE)); 467 sram_bist->loop_mode = 3; /* WW_RR */ 468 sram_bist->bg_tcam_loop_count = 469 mt_data->bg_tcam_bist ? mt_data->bg_tcam_loop_count : 1; 470 SOC_IF_ERROR_RETURN 471 (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, 472 mt_data->sub_interface, 473 sram_bist)); 474 SOC_IF_ERROR_RETURN 475 (soc_triumph_ext_sram_op(mt_ctrl->unit, mt_data->sub_interface, 476 sram_bist, NULL)); 477 SOC_IF_ERROR_RETURN 478 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, 479 mt_data->sub_interface, 480 FALSE, FALSE)); 481 if (sram_bist->err_cnt) { 482 mt_ctrl->cur_fail_count++; 483 } 484 } 485 486 return SOC_E_NONE; 487 } 488 489 STATIC int 490 _soc_tr_tcam_tune_test_cb(soc_memtune_data_t *mt_data) 491 { 492 soc_tcam_info_t *tcam_info; 493 soc_tcam_partition_t *partitions; 494 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 495 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 496 uint32 rval; 497 int rv, addr, i; 498 uint32 exp_dpeo_rise, exp_dpeo_fall; 499 uint32 pattern[4]; 500 uint32 data[8], data_miss[8]; 501 int index, exp_result0[2], exp_result1[2], result0, result1, valid; 502 uint32 mask[4]; 503 504 tcam_info = SOC_CONTROL(mt_ctrl->unit)->tcam_info; 505 partitions = tcam_info->partitions; 506 507 addr = soc_reg_addr(mt_ctrl->unit, tr_mt_data->inst_status, REG_PORT_ANY, 508 0); 509 510 switch (mt_data->sub_interface) { 511 case 0: /* DBUS */ 512 pattern[0] = 0xffffffff; 513 pattern[1] = 0x00000000; 514 pattern[2] = 0x55555555; 515 pattern[3] = 0xaaaaaaaa; 516 mask[0] = mask[1] = mask[2] = mask[3] = 0; 517 518 /* Use the last few entries in the firts block of the first device */ 519 index = 16380; 520 for (i = 0; i < 4; i ++) { 521 data[0] = 0; 522 data[1] = pattern[i] & 0xff; 523 data[2] = data[3] = pattern[i]; 524 SOC_IF_ERROR_RETURN 525 (soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL72, 526 index + i, mask, data)); 527 } 528 for (i = 0; i < 4; i ++) { 529 rv = soc_tcam_read_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL72, 530 index + i, mask, data, &valid); 531 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 532 if (rv < 0 || (rval & tr_mt_data->dbus_fail_mask)) { 533 mt_ctrl->cur_fail_count = mt_data->test_count; 534 mt_ctrl->cur_fail_reason = 0x10000; 535 mt_ctrl->cur_fail_detail0 = rval; 536 break; 537 } 538 if (data[1] != (pattern[i] & 0xff) || data[2] != pattern[i] || 539 data[3] != pattern[i]) { 540 mt_ctrl->cur_fail_count = mt_data->test_count; 541 mt_ctrl->cur_fail_reason = 0x20000; 542 mt_ctrl->cur_fail_detail0 = i; 543 break; 544 } 545 } 546 if (mt_ctrl->cur_fail_count) { 547 break; 548 } 549 550 if (tcam_info->num_tcams == 1 || tcam_info->monolith_dev) { 551 /* not MCM device */ 552 break; 553 } 554 555 /* Use the last few entries in the first block of the second device */ 556 index = 16380; 557 for (i = 0; i < 4; i ++) { 558 data[0] = 0; 559 data[1] = pattern[i] & 0xff; 560 data[2] = data[3] = pattern[i]; 561 SOC_IF_ERROR_RETURN 562 (soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL72, 563 index + i, mask, data)); 564 } 565 for (i = 0; i < 4; i ++) { 566 rv = soc_tcam_read_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL72, 567 index + i, mask, data, &valid); 568 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 569 if (rv < 0 || (rval & tr_mt_data->dbus_fail_mask)) { 570 mt_ctrl->cur_fail_count = mt_data->test_count; 571 mt_ctrl->cur_fail_reason = 0x10001; 572 mt_ctrl->cur_fail_detail0 = rval; 573 break; 574 } 575 if (data[1] != (pattern[i] & 0xff) || data[2] != pattern[i] || 576 data[3] != pattern[i]) { 577 mt_ctrl->cur_fail_count = mt_data->test_count; 578 mt_ctrl->cur_fail_reason = 0x20001; 579 mt_ctrl->cur_fail_detail0 = i; 580 break; 581 } 582 } 583 break; 584 585 case 1: /* DBUS_out (DPEO) */ 586 sal_memset(data, 0, sizeof(data)); 587 data[0] = data[4] = 0xabcd; 588 SOC_IF_ERROR_RETURN 589 (soc_tr_tcam_type1_memtest_dpeo(mt_ctrl->unit, 2, 0x3, data)); 590 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 591 /* 592 * DPEO_0 is connected to DPEO pin of first TCAM 593 * DPEO_1 is connected to DPEO pin of optional second TCAM 594 */ 595 if (!mt_ctrl->dpeo_sel_cur) { /* DPEO_0 */ 596 exp_dpeo_rise = 1; 597 exp_dpeo_fall = 1; 598 } else { /* DPEO_1 */ 599 exp_dpeo_rise = 2; 600 exp_dpeo_fall = 2; 601 } 602 if (!soc_reg_field_get(mt_ctrl->unit, tr_mt_data->inst_status, rval, 603 SEQ_DPEO_ERRf) || 604 soc_reg_field_get(mt_ctrl->unit, tr_mt_data->inst_status, rval, 605 DPEO_RISEf) != exp_dpeo_rise || 606 soc_reg_field_get(mt_ctrl->unit, tr_mt_data->inst_status, rval, 607 DPEO_FALLf) != exp_dpeo_fall) { 608 mt_ctrl->cur_fail_count = mt_data->test_count; 609 mt_ctrl->cur_fail_detail0 = rval; 610 } 611 break; 612 613 case 2: /* RBUS */ 614 if (mt_data->mask[0] == 0xffffffff) { 615 sal_memset(mask, 0, sizeof(mask)); 616 sal_memset(data, 0, sizeof(data)); 617 /* all '1's for lower 72-bit, all '0's for upper 72-bit */ 618 data[5] = 0xff; 619 data[6] = data[7] = 0xffffffff; 620 } else { 621 sal_memcpy(mask, mt_data->mask, sizeof(mask)); 622 sal_memcpy(data, mt_data->data, sizeof(data)); 623 } 624 sal_memcpy(data_miss, data, sizeof(data_miss)); 625 data_miss[7] ^= 1; /* use a bogus key to cause a miss */ 626 627 /* first do a search miss, ignore result index */ 628 rv = soc_tcam_search_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL72, 629 TCAM_PARTITION_DEV0_TBL144, data_miss, 630 &result0, &result1); 631 if (SOC_FAILURE(rv) && rv != SOC_E_NOT_FOUND) { 632 return rv; 633 } 634 /* then do a search hit, ignore result index, only check for status */ 635 rv = soc_tcam_search_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL72, 636 TCAM_PARTITION_DEV0_TBL144, data, 637 &result0, &result1); 638 if (SOC_FAILURE(rv) && rv != SOC_E_NOT_FOUND) { 639 return rv; 640 } 641 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 642 if (rval & tr_mt_data->rbus_fail_mask) { 643 mt_ctrl->cur_fail_count = mt_data->test_count; 644 mt_ctrl->cur_fail_reason = 0x10000; 645 mt_ctrl->cur_fail_detail0 = rval; 646 break; 647 } 648 if ((rval & tr_mt_data->rbus_valid_mask) != 649 tr_mt_data->rbus_valid_mask) { 650 mt_ctrl->cur_fail_count = mt_data->test_count; 651 mt_ctrl->cur_fail_reason = 0x20000; 652 mt_ctrl->cur_fail_detail0 = rval; 653 break; 654 } 655 656 if (!partitions[TCAM_PARTITION_DEV1_TBL72].num_entries || 657 !partitions[TCAM_PARTITION_DEV1_TBL144].num_entries) { 658 /* not MCM device */ 659 break; 660 } 661 662 /* first do a search miss, ignore result index */ 663 rv = soc_tcam_search_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL72, 664 TCAM_PARTITION_DEV1_TBL144, data_miss, 665 &result0, &result1); 666 if (SOC_FAILURE(rv) && rv != SOC_E_NOT_FOUND) { 667 return rv; 668 } 669 /* then do a search hit, ignore result index, only check for status */ 670 rv = soc_tcam_search_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL72, 671 TCAM_PARTITION_DEV1_TBL144, data, 672 &result0, &result1); 673 if (SOC_FAILURE(rv) && rv != SOC_E_NOT_FOUND) { 674 return rv; 675 } 676 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 677 if (rval & tr_mt_data->rbus_fail_mask) { 678 mt_ctrl->cur_fail_count = mt_data->test_count; 679 mt_ctrl->cur_fail_reason = 0x10001; 680 mt_ctrl->cur_fail_detail0 = rval; 681 break; 682 } 683 if ((rval & tr_mt_data->rbus_valid_mask) != 684 tr_mt_data->rbus_valid_mask) { 685 mt_ctrl->cur_fail_count = mt_data->test_count; 686 mt_ctrl->cur_fail_reason = 0x20001; 687 mt_ctrl->cur_fail_detail0 = rval; 688 break; 689 } 690 break; 691 692 case 3: /* search test */ 693 /* No reset on simulation, put test entry at index 0 to avoid hitting 694 * leftover entries */ 695 index = SAL_BOOT_SIMULATION ? 0 : 0x1555; 696 if (mt_data->mask[0] == 0xffffffff) { 697 sal_memset(mask, 0, sizeof(mask)); 698 sal_memset(data, 0, sizeof(data)); 699 /* all '1's for lower 72-bit, all '0's for upper 72-bit */ 700 data[5] = 0xff; 701 data[6] = data[7] = 0xffffffff; 702 } else { 703 sal_memcpy(mask, mt_data->mask, sizeof(mask)); 704 sal_memcpy(data, mt_data->data, sizeof(data)); 705 } 706 707 exp_result0[0] = partitions[TCAM_PARTITION_DEV0_TBL72].tcam_base + 708 (index << partitions[TCAM_PARTITION_DEV0_TBL72].tcam_width_shift); 709 exp_result1[0] = partitions[TCAM_PARTITION_DEV0_TBL144].tcam_base + 710 (index << 711 partitions[TCAM_PARTITION_DEV0_TBL144].tcam_width_shift); 712 exp_result0[1] = partitions[TCAM_PARTITION_DEV1_TBL72].tcam_base + 713 (index << partitions[TCAM_PARTITION_DEV1_TBL72].tcam_width_shift); 714 exp_result1[1] = partitions[TCAM_PARTITION_DEV1_TBL144].tcam_base + 715 (index << 716 partitions[TCAM_PARTITION_DEV1_TBL144].tcam_width_shift); 717 718 for (i = 0; i < mt_data->test_count; i++) { 719 rv = soc_tcam_search_entry(mt_ctrl->unit, 720 TCAM_PARTITION_DEV0_TBL72, 721 TCAM_PARTITION_DEV0_TBL144, 722 data, &result0, &result1); 723 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 724 if (rv < 0 || (rval & tr_mt_data->rbus_fail_mask)) { 725 mt_ctrl->cur_fail_count++; 726 mt_ctrl->cur_fail_reason = 0x10000; 727 mt_ctrl->cur_fail_detail0 = rval; 728 continue; 729 } 730 731 if (result0 != exp_result0[0] || result1 != exp_result1[0]) { 732 mt_ctrl->cur_fail_count++; 733 mt_ctrl->cur_fail_reason = 0x20000; 734 mt_ctrl->cur_fail_detail0 = result0; 735 mt_ctrl->cur_fail_detail1 = result1; 736 continue; 737 } 738 739 rv = soc_triumph_tcam_search_bist(mt_ctrl->unit, 740 TCAM_PARTITION_DEV0_TBL72, 741 TCAM_PARTITION_DEV0_TBL144, 742 data, 743 exp_result0[0], exp_result1[0], 744 mt_data->tcam_loop_count); 745 if (rv < 0) { 746 mt_ctrl->cur_fail_count++; 747 mt_ctrl->cur_fail_reason = 0x30000; 748 continue; 749 } 750 751 if (!partitions[TCAM_PARTITION_DEV1_TBL72].num_entries || 752 !partitions[TCAM_PARTITION_DEV1_TBL144].num_entries) { 753 /* not MCM device */ 754 continue; 755 } 756 757 rv = soc_tcam_search_entry(mt_ctrl->unit, 758 TCAM_PARTITION_DEV1_TBL72, 759 TCAM_PARTITION_DEV1_TBL144, 760 data, &result0, &result1); 761 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 762 if (rv < 0 || (rval & tr_mt_data->rbus_fail_mask)) { 763 mt_ctrl->cur_fail_count++; 764 mt_ctrl->cur_fail_reason = 0x10001; 765 continue; 766 } 767 768 if (result0 != exp_result0[1] || result1 != exp_result1[1]) { 769 mt_ctrl->cur_fail_count++; 770 mt_ctrl->cur_fail_reason = 0x20001; 771 mt_ctrl->cur_fail_detail0 = result0; 772 mt_ctrl->cur_fail_detail1 = result1; 773 continue; 774 } 775 776 rv = soc_triumph_tcam_search_bist(mt_ctrl->unit, 777 TCAM_PARTITION_DEV1_TBL72, 778 TCAM_PARTITION_DEV1_TBL144, 779 data, 780 exp_result0[1], exp_result1[1], 781 mt_data->tcam_loop_count); 782 if (rv < 0) { 783 mt_ctrl->cur_fail_count++; 784 mt_ctrl->cur_fail_reason = 0x30001; 785 continue; 786 } 787 } 788 789 break; 790 791 default: 792 break; 793 } 794 795 return SOC_E_NONE; 796 } 797 798 STATIC int 799 _soc_tr_tune_generate_config(soc_memtune_data_t *mt_data) 800 { 801 #ifndef NO_MEMTUNE 802 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 803 soc_memtune_result_t *result; 804 uint32 rval, val, pvt_val; 805 char name_str[23], val_str[11]; 806 int use_midl; 807 808 pvt_val = 0; 809 if (mt_ctrl->odtres_val != -1) { 810 pvt_val |= SOC_TR_MEMTUNE_OVRD_ODTRES_MASK << 811 SOC_TR_MEMTUNE_OVRD_ODTRES_SHIFT; 812 pvt_val |= (mt_ctrl->odtres_val & SOC_TR_MEMTUNE_ODTRES_MASK) << 813 SOC_TR_MEMTUNE_ODTRES_SHIFT; 814 } 815 if (mt_ctrl->ndrive_val != -1 && mt_ctrl->pdrive_val != -1) { 816 pvt_val |= SOC_TR_MEMTUNE_OVRD_DRIVER_MASK << 817 SOC_TR_MEMTUNE_OVRD_DRIVER_SHIFT; 818 pvt_val |= (mt_ctrl->pdrive_val & SOC_TR_MEMTUNE_PDRIVE_MASK) << 819 SOC_TR_MEMTUNE_PDRIVE_SHIFT; 820 pvt_val |= (mt_ctrl->ndrive_val & SOC_TR_MEMTUNE_NDRIVE_MASK) << 821 SOC_TR_MEMTUNE_NDRIVE_SHIFT; 822 } 823 if (mt_ctrl->slew_val != -1) { 824 pvt_val |= SOC_TR_MEMTUNE_OVRD_SLEW_MASK << 825 SOC_TR_MEMTUNE_OVRD_SLEW_SHIFT; 826 pvt_val |= (mt_ctrl->slew_val & SOC_TR_MEMTUNE_SLEW_MASK) << 827 SOC_TR_MEMTUNE_SLEW_SHIFT; 828 } 829 830 switch (mt_data->interface) { 831 case SOC_MEM_INTERFACE_SRAM: 832 val = 0; 833 if (mt_ctrl->phase_sel_cur != -1) { 834 val |= SOC_TR_MEMTUNE_OVRD_SM_MASK << 835 SOC_TR_MEMTUNE_OVRD_SM_SHIFT; 836 val |= (mt_ctrl->phase_sel_cur & SOC_TR_MEMTUNE_PHASE_SEL_MASK) << 837 SOC_TR_MEMTUNE_PHASE_SEL_SHIFT; 838 } 839 if (mt_ctrl->ddr_latency_cur != -1) { 840 val |= 841 (mt_ctrl->ddr_latency_cur & SOC_TR_MEMTUNE_DDR_LATENCY_MASK) << 842 SOC_TR_MEMTUNE_DDR_LATENCY_SHIFT; 843 } 844 845 sal_sprintf(val_str, "0x%08x", 846 SOC_TR_MEMTUNE_CONFIG_VALID_MASK | 847 val | 848 /* use 0 in the 3-bit field to represent EM_LATENCY is 8 */ 849 ((mt_ctrl->em_latency_cur & 850 SOC_TR_MEMTUNE_EM_LATENCY_MASK) << 851 SOC_TR_MEMTUNE_EM_LATENCY_SHIFT) | 852 ((mt_ctrl->tx_offset_cur & 853 SOC_TR_MEMTUNE_DDR_TX_OFFSET_MASK) << 854 SOC_TR_MEMTUNE_DDR_TX_OFFSET_SHIFT) | 855 ((mt_ctrl->rx_offset_cur & 856 SOC_TR_MEMTUNE_DDR_RX_OFFSET_MASK) << 857 SOC_TR_MEMTUNE_DDR_RX_OFFSET_SHIFT) | 858 ((mt_ctrl->w2r_nops_cur & SOC_TR_MEMTUNE_W2R_NOPS_MASK) << 859 SOC_TR_MEMTUNE_W2R_NOPS_SHIFT) | 860 ((mt_ctrl->r2w_nops_cur & SOC_TR_MEMTUNE_R2W_NOPS_MASK) << 861 SOC_TR_MEMTUNE_R2W_NOPS_SHIFT) | 862 ((mt_data->freq & SOC_TR_MEMTUNE_DDR_FREQ_MASK) << 863 SOC_TR_MEMTUNE_DDR_FREQ_SHIFT)); 864 sal_sprintf(name_str, "%s%d.%d", spn_EXT_SRAM_TUNING, 865 mt_data->sub_interface, mt_ctrl->unit); 866 if (_mem_config_set(name_str, val_str) < 0) { 867 return SOC_E_MEMORY; 868 } 869 if (pvt_val) { 870 sal_sprintf(val_str, "0x%08x", 871 SOC_TR_MEMTUNE_CONFIG_VALID_MASK | pvt_val); 872 sal_sprintf(name_str, "%s%d.%d", spn_EXT_SRAM_PVT, 873 mt_data->sub_interface, mt_ctrl->unit); 874 if (_mem_config_set(name_str, val_str) < 0) { 875 return SOC_E_MEMORY; 876 } 877 } 878 if (mt_ctrl->tx_offset_min == mt_ctrl->tx_offset_max || 879 mt_ctrl->rx_offset_min == mt_ctrl->rx_offset_max) { 880 break; 881 } 882 if (mt_ctrl->phase_sel_cur != -1) { 883 result = mt_ctrl->ps_data[mt_ctrl->phase_sel_cur]; 884 } else { 885 result = mt_ctrl->ps_data[0]; 886 } 887 sal_sprintf(val_str, "0x%08x", 888 SOC_TR_MEMTUNE_CONFIG_VALID_MASK | 889 ((result->width & SOC_TR_MEMTUNE_STATS_WIDTH_MASK) << 890 SOC_TR_MEMTUNE_STATS_WIDTH_SHIFT) | 891 ((result->height & SOC_TR_MEMTUNE_STATS_HEIGHT_MASK) << 892 SOC_TR_MEMTUNE_STATS_HEIGHT_SHIFT) | 893 ((result->fail_count & SOC_TR_MEMTUNE_STATS_FAIL_MASK) << 894 SOC_TR_MEMTUNE_STATS_FAIL_SHIFT)); 895 sal_sprintf(name_str, "%s%d.%d", spn_EXT_SRAM_TUNING_STATS, 896 mt_data->sub_interface, mt_ctrl->unit); 897 if (_mem_config_set(name_str, val_str) < 0) { 898 return SOC_E_MEMORY; 899 } 900 break; 901 case SOC_MEM_INTERFACE_TCAM: 902 SOC_IF_ERROR_RETURN(READ_ETU_DDR72_CONFIG_REG1_ISr(mt_ctrl->unit, 903 &rval)); 904 use_midl = 905 soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr, rval, 906 MIDL_TX_ENf) && 907 soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr, rval, 908 SEL_TX_CLKDLY_BLKf) ? 1 : 0; 909 sal_sprintf(val_str, "0x%08x", 910 SOC_TR_MEMTUNE_CONFIG_VALID_MASK | 911 ((mt_ctrl->fcd_dpeo_cur & SOC_TR_MEMTUNE_FCD_DPEO_MASK) << 912 SOC_TR_MEMTUNE_FCD_DPEO_SHIFT) | 913 ((mt_ctrl->dpeo_sync_dly_cur & 914 SOC_TR_MEMTUNE_DPEO_SYNC_DLY_MASK) << 915 SOC_TR_MEMTUNE_DPEO_SYNC_DLY_SHIFT) | 916 ((mt_ctrl->fcd_rbus_cur & SOC_TR_MEMTUNE_FCD_RBUS_MASK) << 917 SOC_TR_MEMTUNE_FCD_RBUS_SHIFT) | 918 ((mt_ctrl->rbus_sync_dly_cur & 919 SOC_TR_MEMTUNE_RBUS_SYNC_DLY_MASK) << 920 SOC_TR_MEMTUNE_RBUS_SYNC_DLY_SHIFT)); 921 sal_sprintf(name_str, "%s0.%d", spn_EXT_TCAM_TUNING, mt_ctrl->unit); 922 if (_mem_config_set(name_str, val_str) < 0) { 923 return SOC_E_MEMORY; 924 } 925 val = 0; 926 if (mt_ctrl->invert_txclk_cur != -1) { 927 val |= (mt_ctrl->invert_txclk_cur & 928 SOC_TR_MEMTUNE_INVERT_TXCLK_MASK) << 929 SOC_TR_MEMTUNE_INVERT_TXCLK_SHIFT; 930 } 931 if (mt_ctrl->invert_rxclk_cur != -1) { 932 val |= (mt_ctrl->invert_rxclk_cur & 933 SOC_TR_MEMTUNE_INVERT_RXCLK_MASK) << 934 SOC_TR_MEMTUNE_INVERT_RXCLK_SHIFT; 935 } 936 sal_sprintf(val_str, "0x%08x", 937 SOC_TR_MEMTUNE_CONFIG_VALID_MASK | 938 val | 939 ((mt_ctrl->tx_offset_cur & 940 SOC_TR_MEMTUNE_TCAM_TX_OFFSET_MASK) << 941 SOC_TR_MEMTUNE_TCAM_TX_OFFSET_SHIFT) | 942 ((mt_ctrl->rx_offset_cur & 943 SOC_TR_MEMTUNE_TCAM_RX_OFFSET_MASK) << 944 SOC_TR_MEMTUNE_TCAM_RX_OFFSET_SHIFT) | 945 ((mt_data->freq & 946 SOC_TR_MEMTUNE_TCAM_FREQ_MASK) << 947 SOC_TR_MEMTUNE_TCAM_FREQ_SHIFT) | 948 ((use_midl & SOC_TR_MEMTUNE_USE_MIDL_MASK) << 949 SOC_TR_MEMTUNE_USE_MIDL_SHIFT)); 950 sal_sprintf(name_str, "%s1.%d", spn_EXT_TCAM_TUNING, mt_ctrl->unit); 951 if (_mem_config_set(name_str, val_str) < 0) { 952 return SOC_E_MEMORY; 953 } 954 if (pvt_val) { 955 sal_sprintf(val_str, "0x%08x", 956 SOC_TR_MEMTUNE_CONFIG_VALID_MASK | pvt_val); 957 sal_sprintf(name_str, "%s.%d", spn_EXT_TCAM_PVT, mt_ctrl->unit); 958 if (_mem_config_set(name_str, val_str) < 0) { 959 return SOC_E_MEMORY; 960 } 961 } 962 if (mt_ctrl->tx_offset_min == mt_ctrl->tx_offset_max || 963 mt_ctrl->rx_offset_min == mt_ctrl->rx_offset_max) { 964 break; 965 } 966 if (mt_ctrl->invert_txclk_cur != -1 && 967 mt_ctrl->invert_rxclk_cur != -1) { 968 result = &mt_ctrl->result[mt_ctrl->invert_txclk_cur * 2 + 969 mt_ctrl->invert_rxclk_cur]; 970 } else { 971 result = &mt_ctrl->result[0]; 972 } 973 sal_sprintf(val_str, "0x%08x", 974 SOC_TR_MEMTUNE_CONFIG_VALID_MASK | 975 ((result->width & SOC_TR_MEMTUNE_STATS_WIDTH_MASK) << 976 SOC_TR_MEMTUNE_STATS_WIDTH_SHIFT) | 977 ((result->height & SOC_TR_MEMTUNE_STATS_HEIGHT_MASK) << 978 SOC_TR_MEMTUNE_STATS_HEIGHT_SHIFT) | 979 ((result->fail_count & SOC_TR_MEMTUNE_STATS_FAIL_MASK) << 980 SOC_TR_MEMTUNE_STATS_FAIL_SHIFT)); 981 sal_sprintf(name_str, "%s.%d", spn_EXT_TCAM_TUNING_STATS, 982 mt_ctrl->unit); 983 if (_mem_config_set(name_str, val_str) < 0) { 984 return SOC_E_MEMORY; 985 } 986 break; 987 default: 988 break; 989 } 990 #endif /* NO_MEMTUNE */ 991 992 return SOC_E_NONE; 993 } 994 #endif /* BCM_TRIUMPH_SUPPORT */ 995 996 #define ABS(n) (((n) < 0) ? -(n) : (n)) 997 998 STATIC void 999 _soc_memtune_get_txrx_area(soc_memtune_data_t *mt_data, 1000 int tx_offset, int rx_offset, 1001 int *width, int *height) 1002 { 1003 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 1004 int best_area, best_shape, area, shape; 1005 int dt, dr, max_dt, max_dr, index, num_rx; 1006 1007 num_rx = mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1; 1008 index = (tx_offset - mt_ctrl->tx_offset_min) * num_rx + 1009 rx_offset - mt_ctrl->rx_offset_min; 1010 if (mt_ctrl->fail_array[index] > 0) { 1011 *width = *height = 0; 1012 return; 1013 } 1014 1015 max_dt = (mt_ctrl->tx_offset_max - mt_ctrl->tx_offset_min) / 2 + 1; 1016 for (dt = 1; dt < max_dt; dt++) { 1017 if (tx_offset - dt < mt_ctrl->tx_offset_min || 1018 tx_offset + dt > mt_ctrl->tx_offset_max || 1019 mt_ctrl->fail_array[index - dt * num_rx] > 0 || 1020 mt_ctrl->fail_array[index + dt * num_rx] > 0) { 1021 max_dt = dt; 1022 break; 1023 } 1024 } 1025 1026 max_dr = (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min) / 2 + 1; 1027 for (dr = 1; dr < max_dr; dr++) { 1028 if (rx_offset - dr < mt_ctrl->rx_offset_min || 1029 rx_offset + dr > mt_ctrl->rx_offset_max || 1030 mt_ctrl->fail_array[index - dr] > 0 || 1031 mt_ctrl->fail_array[index + dr] > 0) { 1032 max_dr = dr; 1033 break; 1034 } 1035 } 1036 1037 area = max_dr * 2 - 1; 1038 shape = area - 1; 1039 best_area = area; 1040 best_shape = shape; 1041 *width = area; 1042 *height = 1; 1043 1044 for (dt = 1; dt < max_dt; dt++) { 1045 for (dr = 1; dr < max_dr; dr++) { 1046 if (mt_ctrl->fail_array[index - dt * num_rx - dr] > 0 || 1047 mt_ctrl->fail_array[index - dt * num_rx + dr] > 0 || 1048 mt_ctrl->fail_array[index + dt * num_rx - dr] > 0 || 1049 mt_ctrl->fail_array[index + dt * num_rx + dr] > 0) { 1050 max_dr = dr; 1051 break; 1052 } 1053 } 1054 1055 dr--; 1056 area = (dt * 2 + 1) * (dr * 2 + 1); 1057 shape = ABS(dt - dr) * 2; 1058 if (area > best_area || 1059 (area == best_area && shape < best_shape)) { 1060 best_area = area; 1061 best_shape = shape; 1062 *width = dr * 2 + 1; 1063 *height = dt * 2 + 1; 1064 } 1065 } 1066 } 1067 1068 STATIC int 1069 _soc_memtune_txrx_analyze(soc_memtune_data_t *mt_data) 1070 { 1071 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 1072 soc_memtune_result_t *result; 1073 int offset_count, fail_count; 1074 int index, tx_offset, rx_offset; 1075 int area, shape, width, height; 1076 int best_area, best_shape, best_width, best_height; 1077 char buf[128]; 1078 int buf_index; 1079 1080 offset_count = (mt_ctrl->tx_offset_max - mt_ctrl->tx_offset_min + 1) * 1081 (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1); 1082 fail_count = 0; 1083 index = 0; 1084 for (tx_offset = mt_ctrl->tx_offset_min; 1085 tx_offset <= mt_ctrl->tx_offset_max; tx_offset++) { 1086 for (rx_offset = mt_ctrl->rx_offset_min; 1087 rx_offset <= mt_ctrl->rx_offset_max; rx_offset++) { 1088 if (mt_ctrl->fail_array[index] > 0) { 1089 fail_count++; 1090 } 1091 index++; 1092 } 1093 } 1094 1095 if (mt_ctrl->flags & (SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX | 1096 SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS)) { 1097 buf_index = sal_sprintf(buf, "unit %d %s interface", 1098 mt_ctrl->unit, mt_ctrl->intf_name); 1099 switch (mt_data->interface) { 1100 case SOC_MEM_INTERFACE_SRAM: 1101 if (mt_ctrl->em_latency_cur != -1) { 1102 buf_index += sal_sprintf(&buf[buf_index], " em_latency=%d", 1103 mt_ctrl->em_latency_cur); 1104 } 1105 if (mt_ctrl->ddr_latency_cur != -1) { 1106 buf_index += sal_sprintf(&buf[buf_index], " ddr_latency=%d", 1107 mt_ctrl->ddr_latency_cur); 1108 } 1109 break; 1110 case SOC_MEM_INTERFACE_TCAM: 1111 if (mt_ctrl->invert_txclk_cur != -1) { 1112 buf_index += sal_sprintf(&buf[buf_index], " invert_txclk=%d", 1113 mt_ctrl->invert_txclk_cur); 1114 } 1115 if (mt_ctrl->invert_rxclk_cur != -1) { 1116 buf_index += sal_sprintf(&buf[buf_index], " invert_rxclk=%d", 1117 mt_ctrl->invert_rxclk_cur); 1118 } 1119 break; 1120 default: 1121 break; 1122 } 1123 } 1124 1125 if (fail_count == offset_count) { 1126 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX) { 1127 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1128 "Memory tuning %s failure count: all fail\n"), buf)); 1129 } 1130 result = &mt_ctrl->result[mt_ctrl->result_count]; 1131 result->fail_count = fail_count; 1132 mt_ctrl->result_count++; 1133 return SOC_E_NONE; 1134 } 1135 1136 /* Print failure matrix */ 1137 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX) { 1138 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1139 "Memory tuning %s failure count:\n"), buf)); 1140 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1141 "TX (vertical axis) range: %d - %d, " 1142 "RX (horizontal axis) range: %d - %d\n"), 1143 mt_ctrl->tx_offset_min, mt_ctrl->tx_offset_max, 1144 mt_ctrl->rx_offset_min, mt_ctrl->rx_offset_max)); 1145 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1146 " |"))); 1147 for (index = mt_ctrl->rx_offset_min; index <= mt_ctrl->rx_offset_max; 1148 index++) { 1149 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1150 "%4d\t"), index)); 1151 } 1152 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1153 "\n--------+"))); 1154 for (rx_offset = mt_ctrl->rx_offset_min; 1155 rx_offset <= mt_ctrl->rx_offset_max; rx_offset++) { 1156 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1157 "--------"))); 1158 } 1159 index = 0; 1160 for (tx_offset = mt_ctrl->tx_offset_min; 1161 tx_offset <= mt_ctrl->tx_offset_max; tx_offset++) { 1162 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1163 "\n %2d |"), tx_offset)); 1164 for (rx_offset = mt_ctrl->rx_offset_min; 1165 rx_offset <= mt_ctrl->rx_offset_max; rx_offset++) { 1166 if (mt_ctrl->fail_array[index] >= 0) { 1167 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1168 "%4d\t"), mt_ctrl->fail_array[index])); 1169 } else { 1170 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1171 " (%d)\t"), -mt_ctrl->fail_array[index])); 1172 } 1173 index++; 1174 } 1175 } 1176 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1177 "\n"))); 1178 } 1179 1180 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS) { 1181 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1182 "Memory tuning %s analysis " 1183 "[box area, abs(width - height)]:\n"), buf)); 1184 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1185 " |"))); 1186 for (index = mt_ctrl->rx_offset_min; index <= mt_ctrl->rx_offset_max; 1187 index++) { 1188 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1189 "%4d\t"), index)); 1190 } 1191 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1192 "\n--------+"))); 1193 for (rx_offset = mt_ctrl->rx_offset_min; 1194 rx_offset <= mt_ctrl->rx_offset_max; rx_offset++) { 1195 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1196 "--------"))); 1197 } 1198 } 1199 1200 best_area = 0; 1201 best_shape = mt_ctrl->tx_offset_max + mt_ctrl->rx_offset_max; 1202 best_width = 0; 1203 best_height = 0; 1204 1205 for (tx_offset = mt_ctrl->tx_offset_min; 1206 tx_offset <= mt_ctrl->tx_offset_max; tx_offset++) { 1207 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS) { 1208 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1209 "\n %2d |"), tx_offset)); 1210 } 1211 for (rx_offset = mt_ctrl->rx_offset_min; 1212 rx_offset <= mt_ctrl->rx_offset_max; rx_offset++) { 1213 _soc_memtune_get_txrx_area(mt_data, tx_offset, rx_offset, 1214 &width, &height); 1215 area = width * height; 1216 shape = ABS(width - height); 1217 if (area != 0) { 1218 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS) { 1219 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1220 "%3d,%1d\t"), area, shape)); 1221 } 1222 if (area > best_area || 1223 (area == best_area && shape < best_shape)) { 1224 best_area = area; 1225 best_shape = shape; 1226 best_width = width; 1227 best_height = height; 1228 mt_ctrl->tx_offset_cur = tx_offset; 1229 mt_ctrl->rx_offset_cur = rx_offset; 1230 } 1231 } else { 1232 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS) { 1233 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1234 " *,*\t"))); 1235 } 1236 } 1237 } 1238 } 1239 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS) { 1240 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1241 "\n"))); 1242 } 1243 1244 result = &mt_ctrl->result[mt_ctrl->result_count]; 1245 1246 result->fail_count = fail_count; 1247 if (best_area != 0) { 1248 /* save the stats and TX/RX settings for this result */ 1249 result->width = best_width; 1250 result->height = best_height; 1251 result->tx_offset = mt_ctrl->tx_offset_cur; 1252 result->rx_offset = mt_ctrl->rx_offset_cur; 1253 } 1254 1255 mt_ctrl->result_count++; 1256 1257 return SOC_E_NONE; 1258 } 1259 1260 #define BACKSPACE "\010" 1261 STATIC int 1262 _soc_memtune_phase_sel_compare(soc_memtune_data_t *mt_data) 1263 { 1264 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 1265 soc_memtune_result_t *ps_data; 1266 int area[4], adj_area[4], shape, side; 1267 int best_area, best_shape, best_side, best_adj_area; 1268 int i, index; 1269 1270 for (i = mt_ctrl->phase_sel_min; i <= mt_ctrl->phase_sel_max; i++) { 1271 area[i] = mt_ctrl->ps_data[i]->width * mt_ctrl->ps_data[i]->height; 1272 } 1273 for (i = mt_ctrl->phase_sel_min; i <= mt_ctrl->phase_sel_max; i++) { 1274 /* For each of the phase_sel values, get a sum of the 1275 * areas of the 2 neighboring phase_sel values. Later, 1276 * if 2 phase_sel values are found to have the same area/shape, 1277 * preference is given to the one with better neighbors. 1278 */ 1279 adj_area[i] = area[i]; 1280 index = i == mt_ctrl->phase_sel_min ? mt_ctrl->phase_sel_max : i - 1; 1281 if (mt_ctrl->ps_data[index]->ddr_latency == 1282 mt_ctrl->ps_data[i]->ddr_latency && 1283 mt_ctrl->ps_data[index]->em_latency == 1284 mt_ctrl->ps_data[i]->em_latency) { 1285 adj_area[i] += area[index]; 1286 } 1287 index = i == mt_ctrl->phase_sel_max ? mt_ctrl->phase_sel_min : i + 1; 1288 if (mt_ctrl->ps_data[index]->ddr_latency == 1289 mt_ctrl->ps_data[i]->ddr_latency && 1290 mt_ctrl->ps_data[index]->em_latency == 1291 mt_ctrl->ps_data[i]->em_latency) { 1292 adj_area[i] += area[index]; 1293 } 1294 } 1295 1296 best_side = 0; 1297 best_adj_area = 0; 1298 best_area = 0; 1299 best_shape = 0; 1300 mt_ctrl->phase_sel_cur = 0; 1301 for (i = mt_ctrl->phase_sel_min; i <= mt_ctrl->phase_sel_max; i++) { 1302 ps_data = mt_ctrl->ps_data[i]; 1303 if (ps_data->width > ps_data->height) { 1304 side = ps_data->height; 1305 shape = ps_data->width - ps_data->height; 1306 } else { 1307 side = ps_data->width; 1308 shape = ps_data->height - ps_data->width; 1309 } 1310 if (!area[i]) { 1311 continue; 1312 } 1313 if (side < best_side) { 1314 continue; 1315 } else if (side == best_side) { 1316 if (adj_area[i] < best_adj_area) { 1317 continue; 1318 } else if (adj_area[i] == best_adj_area) { 1319 if (area[i] < best_area) { 1320 continue; 1321 } else if (area[i] == best_area) { 1322 if (shape >= best_shape) { 1323 continue; 1324 } 1325 } 1326 } 1327 } 1328 1329 best_side = side; 1330 /* coverity[uninit_use : FALSE] */ 1331 best_adj_area = adj_area[i]; 1332 best_area = area[i]; 1333 best_shape = shape; 1334 mt_ctrl->phase_sel_cur = i; 1335 } 1336 1337 return SOC_E_NONE; 1338 } 1339 1340 STATIC int 1341 _soc_memtune_ddr_single_test(soc_memtune_data_t *mt_data) 1342 { 1343 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 1344 int rv; 1345 1346 mt_ctrl->cur_fail_count = 0; 1347 1348 rv = (*mt_ctrl->test_fn)(mt_data); 1349 1350 if (rv < 0) { 1351 LOG_ERROR(BSL_LS_SOC_MEMTUNE, 1352 (BSL_META_U(mt_ctrl->unit, 1353 "unit %d %s test failure: %s\n"), 1354 mt_ctrl->unit, mt_ctrl->intf_name, soc_errmsg(rv))); 1355 return rv; 1356 } 1357 1358 if ((!(mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_PASS) && 1359 mt_ctrl->cur_fail_count != mt_data->test_count) || 1360 (!(mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL) && 1361 mt_ctrl->cur_fail_count == mt_data->test_count)) { 1362 return SOC_E_NONE; 1363 } 1364 1365 if (mt_ctrl->phase_sel_cur != -1) { 1366 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1367 "Phase select=%d "), mt_ctrl->phase_sel_cur)); 1368 } 1369 if (mt_ctrl->em_latency_cur != -1) { 1370 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1371 "EM lat=%d "), mt_ctrl->em_latency_cur)); 1372 } 1373 if (mt_ctrl->ddr_latency_cur != -1) { 1374 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1375 "DDR lat=%d "), mt_ctrl->ddr_latency_cur)); 1376 } 1377 if (mt_ctrl->tx_offset_cur != -1) { 1378 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1379 "TX offset=%d "), mt_ctrl->tx_offset_cur)); 1380 } 1381 if (mt_ctrl->rx_offset_cur != -1) { 1382 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1383 "RX offset=%d "), mt_ctrl->rx_offset_cur)); 1384 } 1385 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_NOPS) { 1386 if (mt_ctrl->r2w_nops_cur != -1) { 1387 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1388 "R2W nops=%d "), mt_ctrl->r2w_nops_cur)); 1389 } 1390 if (mt_ctrl->w2r_nops_cur != -1) { 1391 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1392 "W2R nops=%d "), mt_ctrl->w2r_nops_cur)); 1393 } 1394 } 1395 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1396 ": Fail count=%d\n"), mt_ctrl->cur_fail_count)); 1397 1398 return SOC_E_NONE; 1399 } 1400 1401 STATIC int 1402 _soc_memtune_ddr_main(soc_memtune_data_t *mt_data) 1403 { 1404 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 1405 soc_memtune_result_t *result; 1406 int rv, success, offset_count, old_result_count, index, i; 1407 char progress_symbol; 1408 1409 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_TEST_NAME) { 1410 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1411 "Memory tuning test: %s interface:\n"), 1412 mt_ctrl->intf_name)); 1413 } 1414 1415 if (mt_data->manual_settings) { 1416 mt_ctrl->phase_sel_cur = mt_data->man_phase_sel; 1417 mt_ctrl->em_latency_cur = mt_data->man_em_latency; 1418 mt_ctrl->ddr_latency_cur = mt_data->man_ddr_latency; 1419 mt_ctrl->tx_offset_cur = mt_data->man_tx_offset; 1420 mt_ctrl->rx_offset_cur = mt_data->man_rx_offset; 1421 mt_ctrl->w2r_nops_cur = mt_data->man_w2r_nops; 1422 mt_ctrl->r2w_nops_cur = mt_data->man_r2w_nops; 1423 mt_ctrl->cur_fail_count = 0; 1424 1425 (*mt_ctrl->prog_hw3_fn)(mt_data); /* phase */ 1426 (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */ 1427 (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */ 1428 if (*mt_ctrl->per_tx_fn != NULL) { 1429 (*mt_ctrl->per_tx_fn)(mt_data); 1430 } 1431 if (*mt_ctrl->per_rx_fn != NULL) { 1432 (*mt_ctrl->per_rx_fn)(mt_data); 1433 } 1434 1435 SOC_IF_ERROR_RETURN(_soc_memtune_ddr_single_test(mt_data)); 1436 if (mt_ctrl->cur_fail_count == 0 && mt_data->config) { 1437 #ifdef BCM_TRIUMPH_SUPPORT 1438 if (soc_feature(mt_ctrl->unit, soc_feature_esm_support)) { 1439 SOC_IF_ERROR_RETURN(_soc_tr_tune_generate_config(mt_data)); 1440 } 1441 #endif /* BCM_TRIUMPH_SUPPORT */ 1442 } 1443 return SOC_E_NONE; 1444 } 1445 1446 offset_count = (mt_ctrl->tx_offset_max - mt_ctrl->tx_offset_min + 1) * 1447 (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1); 1448 mt_ctrl->fail_array = sal_alloc(offset_count * sizeof(int), 1449 "memtune working data"); 1450 if (mt_ctrl->fail_array == NULL) { 1451 return SOC_E_MEMORY; 1452 } 1453 sal_memset(mt_ctrl->fail_array, 0, offset_count * sizeof(int)); 1454 1455 mt_ctrl->w2r_nops_cur = mt_ctrl->w2r_nops_max; 1456 mt_ctrl->r2w_nops_cur = mt_ctrl->r2w_nops_max; 1457 mt_ctrl->result_count = 0; 1458 1459 for (mt_ctrl->phase_sel_cur = mt_ctrl->phase_sel_min; 1460 mt_ctrl->phase_sel_cur <= mt_ctrl->phase_sel_max; 1461 mt_ctrl->phase_sel_cur++) { 1462 if (mt_ctrl->phase_sel_cur != -1) { 1463 (*mt_ctrl->prog_hw3_fn)(mt_data); /* phase */ 1464 } 1465 1466 old_result_count = mt_ctrl->result_count; 1467 progress_symbol = '-'; 1468 if (mt_data->do_txrx_first) { 1469 for (mt_ctrl->tx_offset_cur = mt_ctrl->tx_offset_min; 1470 mt_ctrl->tx_offset_cur <= mt_ctrl->tx_offset_max; 1471 mt_ctrl->tx_offset_cur++) { 1472 for (mt_ctrl->rx_offset_cur = mt_ctrl->rx_offset_min; 1473 mt_ctrl->rx_offset_cur <= mt_ctrl->rx_offset_max; 1474 mt_ctrl->rx_offset_cur++) { 1475 (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */ 1476 if (mt_ctrl->rx_offset_cur == mt_ctrl->rx_offset_min) { 1477 if (*mt_ctrl->per_tx_fn != NULL) { 1478 (*mt_ctrl->per_tx_fn)(mt_data); 1479 } 1480 } 1481 if (*mt_ctrl->per_rx_fn != NULL) { 1482 (*mt_ctrl->per_rx_fn)(mt_data); 1483 } 1484 for (mt_ctrl->em_latency_cur = mt_ctrl->em_latency_min; 1485 mt_ctrl->em_latency_cur <= mt_ctrl->em_latency_max; 1486 mt_ctrl->em_latency_cur++) { 1487 for (mt_ctrl->ddr_latency_cur = 1488 mt_ctrl->ddr_latency_min; 1489 mt_ctrl->ddr_latency_cur <= 1490 mt_ctrl->ddr_latency_max; 1491 mt_ctrl->ddr_latency_cur++) { 1492 if (mt_ctrl->flags & 1493 SOC_MEMTUNE_CTRL_FLAGS_SHOW_PROGRESS) { 1494 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1495 "%c" BACKSPACE), progress_symbol)); 1496 progress_symbol ^= '-' ^ '|'; 1497 } 1498 (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */ 1499 rv = _soc_memtune_ddr_single_test(mt_data); 1500 if (SOC_FAILURE(rv)) { /* fail unexpected */ 1501 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1502 " " BACKSPACE))); 1503 sal_free(mt_ctrl->fail_array); 1504 return rv; 1505 } 1506 if (mt_ctrl->cur_fail_count == 0) { 1507 break; 1508 } 1509 } /* mt_ctrl->ddr_latency_cur loop */ 1510 if (mt_ctrl->cur_fail_count == 0) { 1511 break; 1512 } 1513 } /* mt_ctrl->em_latency_cur loop */ 1514 index = (mt_ctrl->tx_offset_cur - mt_ctrl->tx_offset_min) * 1515 (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1) + 1516 mt_ctrl->rx_offset_cur - mt_ctrl->rx_offset_min; 1517 if (mt_ctrl->cur_fail_count > 0) { 1518 mt_ctrl->fail_array[index] = mt_ctrl->cur_fail_count; 1519 } else { 1520 mt_ctrl->fail_array[index] = -mt_ctrl->em_latency_cur; 1521 } 1522 } /* mt_ctrl->rx_offset_cur loop */ 1523 } /* mt_ctrl->tx_offset_cur loop */ 1524 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_PROGRESS) { 1525 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1526 " " BACKSPACE))); 1527 } 1528 1529 /* Analyze and print result matrix */ 1530 result = &mt_ctrl->result[mt_ctrl->result_count]; 1531 mt_ctrl->em_latency_cur = -1; 1532 mt_ctrl->ddr_latency_cur = -1; 1533 _soc_memtune_txrx_analyze(mt_data); 1534 result->phase_sel = mt_ctrl->phase_sel_cur; 1535 result->em_latency = -1; 1536 result->ddr_latency = -1; 1537 } else { 1538 for (mt_ctrl->em_latency_cur = mt_ctrl->em_latency_min; 1539 mt_ctrl->em_latency_cur <= mt_ctrl->em_latency_max; 1540 mt_ctrl->em_latency_cur++) { 1541 for (mt_ctrl->ddr_latency_cur = mt_ctrl->ddr_latency_min; 1542 mt_ctrl->ddr_latency_cur <= mt_ctrl->ddr_latency_max; 1543 mt_ctrl->ddr_latency_cur++) { 1544 success = FALSE; 1545 for (mt_ctrl->tx_offset_cur = mt_ctrl->tx_offset_min; 1546 mt_ctrl->tx_offset_cur <= mt_ctrl->tx_offset_max; 1547 mt_ctrl->tx_offset_cur++) { 1548 for (mt_ctrl->rx_offset_cur = mt_ctrl->rx_offset_min; 1549 mt_ctrl->rx_offset_cur <= mt_ctrl->rx_offset_max; 1550 mt_ctrl->rx_offset_cur++) { 1551 if (mt_ctrl->flags & 1552 SOC_MEMTUNE_CTRL_FLAGS_SHOW_PROGRESS) { 1553 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1554 "%c" BACKSPACE), progress_symbol)); 1555 progress_symbol ^= '-' ^ '|'; 1556 } 1557 (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */ 1558 (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */ 1559 if (mt_ctrl->rx_offset_cur == 1560 mt_ctrl->rx_offset_min) { 1561 if (*mt_ctrl->per_tx_fn != NULL) { 1562 (*mt_ctrl->per_tx_fn)(mt_data); 1563 } 1564 } 1565 if (*mt_ctrl->per_rx_fn != NULL) { 1566 (*mt_ctrl->per_rx_fn)(mt_data); 1567 } 1568 rv = _soc_memtune_ddr_single_test(mt_data); 1569 if (SOC_FAILURE(rv)) { /* fail unexpected */ 1570 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1571 " " BACKSPACE))); 1572 sal_free(mt_ctrl->fail_array); 1573 return rv; 1574 } 1575 index = (mt_ctrl->tx_offset_cur - 1576 mt_ctrl->tx_offset_min) * 1577 (mt_ctrl->rx_offset_max - 1578 mt_ctrl->rx_offset_min + 1) + 1579 mt_ctrl->rx_offset_cur - 1580 mt_ctrl->rx_offset_min; 1581 mt_ctrl->fail_array[index] = 1582 mt_ctrl->cur_fail_count; 1583 if (mt_ctrl->cur_fail_count == 0) { 1584 success = TRUE; 1585 } 1586 } /* mt_ctrl->rx_offset_cur loop */ 1587 } /* mt_ctrl->tx_offset_cur loop */ 1588 if (success) { 1589 if (mt_ctrl->flags & 1590 SOC_MEMTUNE_CTRL_FLAGS_SHOW_PROGRESS) { 1591 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1592 " " BACKSPACE))); 1593 } 1594 1595 /* Analyze and print result matrix */ 1596 result = &mt_ctrl->result[mt_ctrl->result_count]; 1597 _soc_memtune_txrx_analyze(mt_data); 1598 result->phase_sel = mt_ctrl->phase_sel_cur; 1599 result->em_latency = mt_ctrl->em_latency_cur; 1600 result->ddr_latency = mt_ctrl->ddr_latency_cur; 1601 if (!mt_data->test_all_latency) { 1602 goto loop_done; 1603 } 1604 } 1605 } /* mt_ctrl->ddr_latency_cur loop */ 1606 } /* mt_ctrl->em_latency_cur loop */ 1607 1608 /* If nothing is passed for any EM_LATENCY, DDR_LATENCY setting */ 1609 if (mt_ctrl->result_count == old_result_count) { 1610 result = &mt_ctrl->result[mt_ctrl->result_count]; 1611 _soc_memtune_txrx_analyze(mt_data); 1612 result->phase_sel = mt_ctrl->phase_sel_cur; 1613 } 1614 } 1615 1616 loop_done: 1617 index = mt_ctrl->phase_sel_cur == -1 ? 0 : mt_ctrl->phase_sel_cur; 1618 mt_ctrl->ps_data[index] = &mt_ctrl->result[old_result_count]; 1619 for (i = old_result_count + 1; i < mt_ctrl->result_count; i++) { 1620 if (mt_ctrl->ps_data[index]->width * 1621 mt_ctrl->ps_data[index]->height < 1622 mt_ctrl->result[i].width * mt_ctrl->result[i].height) { 1623 mt_ctrl->ps_data[index] = &mt_ctrl->result[i]; 1624 } 1625 } 1626 } 1627 1628 if (mt_ctrl->phase_sel_min != -1) { 1629 /* Select the best result from 4 different phase */ 1630 _soc_memtune_phase_sel_compare(mt_data); 1631 result = mt_ctrl->ps_data[mt_ctrl->phase_sel_cur]; 1632 1633 /* Program phase setting from the best result */ 1634 (*mt_ctrl->prog_hw3_fn)(mt_data); /* phase */ 1635 } else { 1636 mt_ctrl->phase_sel_cur = mt_ctrl->phase_sel_min; 1637 result = mt_ctrl->ps_data[0]; 1638 } 1639 1640 if (result->fail_count != offset_count) { 1641 /* Program latency setting if do_txrx_first is FALSE */ 1642 if (result->em_latency != -1 || result->ddr_latency != -1) { 1643 mt_ctrl->em_latency_cur = result->em_latency; 1644 mt_ctrl->ddr_latency_cur = result->ddr_latency; 1645 (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */ 1646 } 1647 /* Program TX/RX setting from the best result */ 1648 mt_ctrl->tx_offset_cur = result->tx_offset; 1649 mt_ctrl->rx_offset_cur = result->rx_offset; 1650 (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */ 1651 if (*mt_ctrl->per_tx_fn != NULL) { 1652 (*mt_ctrl->per_tx_fn)(mt_data); 1653 } 1654 if (*mt_ctrl->per_rx_fn != NULL) { 1655 (*mt_ctrl->per_rx_fn)(mt_data); 1656 } 1657 /* Find latency setting if do_txrx_first is TRUE */ 1658 if (result->em_latency == -1 && result->ddr_latency == -1) { 1659 for (mt_ctrl->em_latency_cur = mt_ctrl->em_latency_min; 1660 mt_ctrl->em_latency_cur <= mt_ctrl->em_latency_max; 1661 mt_ctrl->em_latency_cur++) { 1662 for (mt_ctrl->ddr_latency_cur = mt_ctrl->ddr_latency_min; 1663 mt_ctrl->ddr_latency_cur <= mt_ctrl->ddr_latency_max; 1664 mt_ctrl->ddr_latency_cur++) { 1665 (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */ 1666 rv = _soc_memtune_ddr_single_test(mt_data); 1667 if (SOC_FAILURE(rv)) { /* fail unexpected */ 1668 sal_free(mt_ctrl->fail_array); 1669 return rv; 1670 } 1671 if (mt_ctrl->cur_fail_count == 0) { 1672 result->ddr_latency = mt_ctrl->ddr_latency_cur; 1673 break; 1674 } 1675 } /* mt_ctrl->ddr_latency_cur loop */ 1676 if (mt_ctrl->cur_fail_count == 0) { 1677 result->em_latency = mt_ctrl->em_latency_cur; 1678 break; 1679 } 1680 } /* mt_ctrl->em_latency_cur loop */ 1681 } 1682 1683 /* Tune number of nop between write-to-read and read-to-write */ 1684 if (mt_ctrl->w2r_nops_min != mt_ctrl->w2r_nops_max && 1685 mt_ctrl->r2w_nops_min != mt_ctrl->r2w_nops_max) { 1686 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_NOPS; 1687 success = FALSE; 1688 for (mt_ctrl->w2r_nops_cur = mt_ctrl->w2r_nops_min; 1689 mt_ctrl->w2r_nops_cur <= mt_ctrl->w2r_nops_max; 1690 mt_ctrl->w2r_nops_cur++) { 1691 for (mt_ctrl->r2w_nops_cur = mt_ctrl->r2w_nops_max; 1692 mt_ctrl->r2w_nops_cur >= mt_ctrl->r2w_nops_min; 1693 mt_ctrl->r2w_nops_cur--) { 1694 if (*mt_ctrl->prog_hw4_fn != NULL) { 1695 (*mt_ctrl->prog_hw4_fn)(mt_data); /* nops */ 1696 } 1697 rv = _soc_memtune_ddr_single_test(mt_data); 1698 if (SOC_FAILURE(rv)) { /* fail unexpected */ 1699 sal_free(mt_ctrl->fail_array); 1700 return rv; 1701 } 1702 if (mt_ctrl->cur_fail_count == 0) { 1703 success = TRUE; 1704 continue; 1705 } 1706 if (mt_ctrl->r2w_nops_cur < mt_ctrl->r2w_nops_max) { 1707 mt_ctrl->r2w_nops_cur++; 1708 } 1709 break; 1710 } 1711 if (mt_ctrl->r2w_nops_cur < mt_ctrl->r2w_nops_min) { 1712 mt_ctrl->r2w_nops_cur++; 1713 } 1714 if (success) { 1715 break; 1716 } 1717 } 1718 if (success) { 1719 if (mt_ctrl->r2w_nops_cur < 1) { 1720 mt_ctrl->r2w_nops_cur = 1; /* hardware interprets 0 as 4 */ 1721 } 1722 if (*mt_ctrl->prog_hw4_fn != NULL) { 1723 (*mt_ctrl->prog_hw4_fn)(mt_data); /* nops */ 1724 } 1725 } else { /* should not be here */ 1726 mt_ctrl->r2w_nops_cur = mt_ctrl->r2w_nops_max; 1727 mt_ctrl->w2r_nops_cur = mt_ctrl->w2r_nops_max; 1728 } 1729 mt_ctrl->flags &= ~SOC_MEMTUNE_CTRL_FLAGS_SHOW_NOPS; 1730 } 1731 1732 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SELECTION) { 1733 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1734 "Memory tuning selection: "))); 1735 if (mt_ctrl->phase_sel_cur != -1) { 1736 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1737 "Phase sel=%d "), mt_ctrl->phase_sel_cur)); 1738 } 1739 if (mt_ctrl->em_latency_cur != -1) { 1740 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1741 "EM lat=%d "), mt_ctrl->em_latency_cur)); 1742 } 1743 if (mt_ctrl->ddr_latency_cur != -1) { 1744 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1745 "DDR lat=%d "), mt_ctrl->ddr_latency_cur)); 1746 } 1747 if (mt_ctrl->tx_offset_cur != -1) { 1748 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1749 "TX offset=%d "), mt_ctrl->tx_offset_cur)); 1750 } 1751 if (mt_ctrl->rx_offset_cur != -1) { 1752 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1753 "RX offset=%d "), mt_ctrl->rx_offset_cur)); 1754 } 1755 if (mt_ctrl->w2r_nops_cur != -1) { 1756 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1757 "W2R nops=%d "), mt_ctrl->w2r_nops_cur)); 1758 } 1759 if (mt_ctrl->r2w_nops_cur != -1) { 1760 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1761 "R2W nops=%d "), mt_ctrl->r2w_nops_cur)); 1762 } 1763 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1764 "\n"))); 1765 } 1766 } 1767 1768 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY) { 1769 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY_HEADER) { 1770 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1771 "\n Interface , Area , Width , Height , PS ," 1772 " TX , RX , Lat , Em , Pass , Fail"))); 1773 if (soc_feature(mt_ctrl->unit, soc_feature_esm_support)) { 1774 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1775 " , Freq , Tb , Sb , Dac"))); 1776 } 1777 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1778 "\n"))); 1779 } 1780 1781 for (i = 0; i < mt_ctrl->result_count; i++) { 1782 result = &mt_ctrl->result[i]; 1783 1784 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1785 " %10s , %4d , %3d , %3d ,"), 1786 mt_ctrl->intf_name, result->width * result->height, 1787 result->width, result->height)); 1788 if (result->phase_sel != -1) { 1789 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1790 " %1d ,"), result->phase_sel)); 1791 } else { 1792 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1793 " ** ,"))); 1794 } 1795 if (result->fail_count != offset_count) { 1796 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1797 " %2d , %2d ,"), 1798 result->tx_offset, result->rx_offset)); 1799 if (result->ddr_latency != -1) { 1800 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1801 " %2d ,"), result->ddr_latency)); 1802 } else { 1803 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1804 " ** ,"))); 1805 } 1806 if (result->em_latency != -1) { 1807 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1808 " %2d ,"), 1809 result->em_latency)); 1810 } else { 1811 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1812 " ** ,"))); 1813 } 1814 } else { 1815 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1816 " ** , ** , ** , ** ,"))); 1817 } 1818 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1819 " %4d , %4d"), 1820 offset_count - result->fail_count, 1821 result->fail_count)); 1822 if (soc_feature(mt_ctrl->unit, soc_feature_esm_support)) { 1823 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1824 " , %3d , %c , %c ,"), 1825 mt_data->freq, 1826 mt_data->bg_tcam_bist ? 'Y' : 'N', 1827 mt_data->bg_sram_bist ? 'Y' : 'N')); 1828 if (mt_ctrl->dac_value != -1) { 1829 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1830 " %2d"), mt_ctrl->dac_value)); 1831 } else { 1832 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1833 " **"))); 1834 } 1835 } 1836 index = result->phase_sel == -1 ? 0 : result->phase_sel; 1837 if (result != mt_ctrl->ps_data[index]) { 1838 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1839 " (ignored)\n"))); 1840 } else if (result->fail_count != offset_count && 1841 mt_ctrl->phase_sel_cur != -1 && 1842 result == mt_ctrl->ps_data[mt_ctrl->phase_sel_cur]) { 1843 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1844 " <\n"))); 1845 } else { 1846 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1847 "\n"))); 1848 } 1849 } 1850 } 1851 1852 if ((mt_ctrl->phase_sel_min != -1) && 1853 (mt_ctrl->phase_sel_cur != -1)) { 1854 result = mt_ctrl->ps_data[mt_ctrl->phase_sel_cur]; 1855 } else { 1856 result = mt_ctrl->ps_data[0]; 1857 } 1858 if (result->fail_count == offset_count) { 1859 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1860 "ERROR - no passing \"eye\" was found, \n" 1861 "please contact your Field Applications Engineer or " 1862 "Sales Manager\n" 1863 "for additional assistance.\n"))); 1864 rv = SOC_E_FAIL; 1865 } else { 1866 if (result->height < mt_ctrl->tx_pass_threshold || 1867 result->width < mt_ctrl->rx_pass_threshold) { 1868 LOG_CLI((BSL_META_U(mt_ctrl->unit, 1869 "!!! SRAM tuning result does not pass qualified " 1870 "threshold !!!\n"))); 1871 } 1872 rv = SOC_E_NONE; 1873 if (mt_data->config) { 1874 #ifdef BCM_TRIUMPH_SUPPORT 1875 if (soc_feature(mt_ctrl->unit, soc_feature_esm_support)) { 1876 rv = _soc_tr_tune_generate_config(mt_data); 1877 } 1878 #endif 1879 if (rv < 0) { 1880 LOG_ERROR(BSL_LS_SOC_MEMTUNE, 1881 (BSL_META_U(mt_ctrl->unit, 1882 "unit %d %s fail to generate config: %s\n"), 1883 mt_ctrl->unit, mt_ctrl->intf_name, 1884 soc_errmsg(rv))); 1885 } 1886 } 1887 } 1888 1889 sal_free(mt_ctrl->fail_array); 1890 return rv; 1891 } 1892 1893 #ifdef BCM_TRIUMPH_SUPPORT 1894 STATIC int 1895 _soc_memtune_tcam_single_test(soc_memtune_data_t *mt_data) 1896 { 1897 soc_tcam_info_t *tcam_info; 1898 soc_tcam_partition_t *partitions; 1899 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 1900 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 1901 char *fail_name, fail_reason[80]; 1902 int rv, index; 1903 uint32 addr, rval, mask[8], data[8]; 1904 int do_init; 1905 1906 tcam_info = SOC_CONTROL(mt_ctrl->unit)->tcam_info; 1907 partitions = tcam_info->partitions; 1908 do_init = tcam_info->num_tcams <= 0 ? TRUE : FALSE; 1909 1910 mt_ctrl->dpeo_sync_dly_cur = -1; 1911 mt_ctrl->fcd_dpeo_cur = -1; 1912 mt_ctrl->rbus_sync_dly_cur = -1; 1913 mt_ctrl->fcd_rbus_cur = -1; 1914 fail_name = NULL; 1915 fail_reason[0] = '\0'; 1916 1917 /* DBUS */ 1918 mt_data->sub_interface = 0; 1919 rv = (*mt_ctrl->prog_hw1_fn)(mt_data); /* dpeo/rbus */ 1920 if (rv < 0) { 1921 LOG_ERROR(BSL_LS_SOC_MEMTUNE, 1922 (BSL_META_U(mt_ctrl->unit, 1923 "%s prog hardware failure: %s\n"), 1924 mt_ctrl->intf_name, 1925 soc_errmsg(rv))); 1926 return rv; 1927 } 1928 1929 if (do_init) { 1930 for (index = 0; index < TCAM_PARTITION_COUNT; index++) { 1931 tcam_info->partitions[index].num_entries = 0; 1932 } 1933 partitions[TCAM_PARTITION_DEV0_TBL72].num_entries = 16384; 1934 partitions[TCAM_PARTITION_DEV0_TBL144].num_entries = 8192; 1935 partitions[TCAM_PARTITION_DEV1_TBL72].num_entries = 16384; 1936 partitions[TCAM_PARTITION_DEV1_TBL144].num_entries = 8192; 1937 soc_tcam_init(mt_ctrl->unit); 1938 mt_ctrl->do_setup_for_rbus_test = TRUE; 1939 } 1940 1941 mt_ctrl->cur_fail_count = 0; 1942 rv = (*mt_ctrl->test_fn)(mt_data); 1943 if (rv < 0) { 1944 LOG_ERROR(BSL_LS_SOC_MEMTUNE, 1945 (BSL_META_U(mt_ctrl->unit, 1946 "%s dbus test failure: %s\n"), 1947 mt_ctrl->intf_name, soc_errmsg(rv))); 1948 return rv; 1949 } 1950 if (mt_ctrl->cur_fail_count) { 1951 fail_name = "DBUS"; 1952 switch (mt_ctrl->cur_fail_reason & 0xffff0000) { 1953 case 0x10000: 1954 sal_sprintf(fail_reason, "bank %d error bit assert (0x%08x)", 1955 mt_ctrl->cur_fail_reason & 0xf, 1956 mt_ctrl->cur_fail_detail0); 1957 break; 1958 case 0x20000: 1959 sal_sprintf(fail_reason, "bank %d entry %d mismatch", 1960 mt_ctrl->cur_fail_reason & 0xf, 1961 mt_ctrl->cur_fail_detail0); 1962 break; 1963 default: 1964 return SOC_E_INTERNAL; 1965 } 1966 goto done; 1967 } 1968 1969 /* DBUS_out (DPEO) */ 1970 addr = soc_reg_addr(mt_ctrl->unit, tr_mt_data->etc_ctl, REG_PORT_ANY, 0); 1971 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 1972 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval, 1973 OUT_DPR_ODD_FALLf, 3); 1974 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval, 1975 OUT_DPR_ODD_RISEf, 3); 1976 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 1977 1978 mt_data->sub_interface = 1; 1979 for (mt_ctrl->dpeo_sync_dly_cur = mt_ctrl->dpeo_sync_dly_min; 1980 mt_ctrl->dpeo_sync_dly_cur <= mt_ctrl->dpeo_sync_dly_max; 1981 mt_ctrl->dpeo_sync_dly_cur++) { 1982 for (mt_ctrl->fcd_dpeo_cur = mt_ctrl->fcd_dpeo_min; 1983 mt_ctrl->fcd_dpeo_cur <= mt_ctrl->fcd_dpeo_max; 1984 mt_ctrl->fcd_dpeo_cur++) { 1985 rv = (*mt_ctrl->prog_hw1_fn)(mt_data); /* dpeo/rbus */ 1986 if (rv < 0) { 1987 LOG_ERROR(BSL_LS_SOC_MEMTUNE, 1988 (BSL_META_U(mt_ctrl->unit, 1989 "%s prog hardware failure: " 1990 "%s\n"), 1991 mt_ctrl->intf_name, 1992 soc_errmsg(rv))); 1993 return rv; 1994 } 1995 mt_ctrl->cur_fail_count = 0; 1996 rv = (*mt_ctrl->test_fn)(mt_data); 1997 if (rv < 0) { 1998 LOG_ERROR(BSL_LS_SOC_MEMTUNE, 1999 (BSL_META_U(mt_ctrl->unit, 2000 "%s dpeo test failure: %s\n"), 2001 mt_ctrl->intf_name, 2002 soc_errmsg(rv))); 2003 return rv; 2004 } 2005 if (mt_ctrl->cur_fail_count == 0) { 2006 break; 2007 } 2008 } /* mt_ctrl->fcd_dpeo_cur loop */ 2009 if (mt_ctrl->cur_fail_count == 0) { 2010 break; 2011 } 2012 } /* mt_ctrl->dpeo_sync_dly_cur loop */ 2013 addr = soc_reg_addr(mt_ctrl->unit, tr_mt_data->etc_ctl, REG_PORT_ANY, 0); 2014 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 2015 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval, 2016 OUT_DPR_ODD_FALLf, 0); 2017 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval, 2018 OUT_DPR_ODD_RISEf, 0); 2019 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 2020 if (mt_ctrl->cur_fail_count) { 2021 fail_name = "DPEO"; 2022 sal_sprintf(fail_reason, "error bit assert (0x%08x)", 2023 mt_ctrl->cur_fail_detail0); 2024 goto done; 2025 } 2026 2027 /* setup for RBUS test */ 2028 if (mt_ctrl->do_setup_for_rbus_test) { 2029 if (!do_init) { 2030 soc_tcam_init(mt_ctrl->unit); 2031 } 2032 mt_ctrl->do_setup_for_rbus_test = FALSE; 2033 sal_memset(mask, 0, sizeof(mask)); 2034 sal_memset(data, 0, sizeof(data)); 2035 2036 /* No reset on simulation, put test entry at index 0 to avoid hitting 2037 * leftover entries */ 2038 index = SAL_BOOT_SIMULATION ? 0 : 0x1555; 2039 if (mt_data->mask[0] == 0xffffffff) { 2040 /* all '1's for lower 72-bit, all '0's for upper 72-bit */ 2041 data[5] = 0xff; 2042 data[6] = data[7] = 0xffffffff; 2043 } else { 2044 sal_memcpy(mask, mt_data->mask, sizeof(mask)); 2045 sal_memcpy(data, mt_data->data, sizeof(data)); 2046 } 2047 soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL72, index, 2048 &mask[4], &data[4]); 2049 soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL144, index, 2050 mask, data); 2051 if (partitions[TCAM_PARTITION_DEV1_TBL72].num_entries) { 2052 soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL72, 2053 index, &mask[4], &data[4]); 2054 } 2055 if (partitions[TCAM_PARTITION_DEV1_TBL144].num_entries) { 2056 soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL144, 2057 index, mask, data); 2058 } 2059 } 2060 2061 addr = soc_reg_addr(mt_ctrl->unit, tr_mt_data->etc_ctl, REG_PORT_ANY, 0); 2062 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 2063 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval, IN_SMFL00f, 2064 0); 2065 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 2066 2067 mt_data->sub_interface = 2; 2068 for (mt_ctrl->rbus_sync_dly_cur = mt_ctrl->rbus_sync_dly_min; 2069 mt_ctrl->rbus_sync_dly_cur <= mt_ctrl->rbus_sync_dly_max; 2070 mt_ctrl->rbus_sync_dly_cur++) { 2071 for (mt_ctrl->fcd_rbus_cur = mt_ctrl->fcd_rbus_min; 2072 mt_ctrl->fcd_rbus_cur <= mt_ctrl->fcd_rbus_max; 2073 mt_ctrl->fcd_rbus_cur++) { 2074 rv = (*mt_ctrl->prog_hw1_fn)(mt_data); /* dpeo/rbus */ 2075 if (rv < 0) { 2076 LOG_ERROR(BSL_LS_SOC_MEMTUNE, 2077 (BSL_META_U(mt_ctrl->unit, 2078 "%s prog hardware failure: " 2079 "%s\n"), 2080 mt_ctrl->intf_name, 2081 soc_errmsg(rv))); 2082 return rv; 2083 } 2084 mt_ctrl->cur_fail_count = 0; 2085 rv = (*mt_ctrl->test_fn)(mt_data); 2086 if (rv < 0) { 2087 LOG_ERROR(BSL_LS_SOC_MEMTUNE, 2088 (BSL_META_U(mt_ctrl->unit, 2089 "%s rbus test failure: %s\n"), 2090 mt_ctrl->intf_name, 2091 soc_errmsg(rv))); 2092 return rv; 2093 } 2094 if (mt_ctrl->cur_fail_count == 0) { 2095 break; 2096 } 2097 } 2098 if (mt_ctrl->cur_fail_count == 0) { 2099 break; 2100 } 2101 } 2102 addr = soc_reg_addr(mt_ctrl->unit, tr_mt_data->etc_ctl, REG_PORT_ANY, 0); 2103 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 2104 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval, IN_SMFL00f, 2105 1); 2106 SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval)); 2107 if (mt_ctrl->cur_fail_count) { 2108 fail_name = "RBUS"; 2109 switch (mt_ctrl->cur_fail_reason & 0xffff0000) { 2110 case 0x10000: 2111 sal_sprintf(fail_reason, "bank %d error bit assert (0x%08x)", 2112 mt_ctrl->cur_fail_reason & 0xf, 2113 mt_ctrl->cur_fail_detail0); 2114 break; 2115 case 0x20000: 2116 sal_sprintf(fail_reason, "bank %d valid bit not assert (0x%08x)", 2117 mt_ctrl->cur_fail_reason & 0xf, 2118 mt_ctrl->cur_fail_detail0); 2119 break; 2120 default: 2121 return SOC_E_INTERNAL; 2122 } 2123 goto done; 2124 } 2125 2126 /* search test */ 2127 mt_data->sub_interface = 3; 2128 mt_ctrl->cur_fail_count = 0; 2129 rv = (*mt_ctrl->test_fn)(mt_data); 2130 if (rv < 0) { 2131 LOG_ERROR(BSL_LS_SOC_MEMTUNE, 2132 (BSL_META_U(mt_ctrl->unit, 2133 "%s search test failure: %s\n"), 2134 mt_ctrl->intf_name, soc_errmsg(rv))); 2135 return rv; 2136 } 2137 2138 if (mt_ctrl->cur_fail_count) { 2139 fail_name = "search"; 2140 switch (mt_ctrl->cur_fail_reason & 0xffff0000) { 2141 case 0x10000: 2142 sal_sprintf(fail_reason, "bank %d status=0x%08x, fail count=%d", 2143 mt_ctrl->cur_fail_reason & 0xf, 2144 mt_ctrl->cur_fail_detail0, 2145 mt_ctrl->cur_fail_count); 2146 break; 2147 case 0x20000: 2148 sal_sprintf(fail_reason, "bank %d index mismatch (0x%x/0x%x), " 2149 "fail count=%d", 2150 mt_ctrl->cur_fail_reason & 0xf, 2151 mt_ctrl->cur_fail_detail0, 2152 mt_ctrl->cur_fail_detail1, 2153 mt_ctrl->cur_fail_count); 2154 break; 2155 case 0x30000: 2156 sal_sprintf(fail_reason, "bank %d BIST search fail, fail count=%d", 2157 mt_ctrl->cur_fail_reason & 0xf, 2158 mt_ctrl->cur_fail_count); 2159 break; 2160 default: 2161 return SOC_E_INTERNAL; 2162 } 2163 goto done; 2164 } 2165 2166 done: 2167 if ((!(mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_PASS) && 2168 mt_ctrl->cur_fail_count < mt_data->test_count) || 2169 (!(mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL) && 2170 mt_ctrl->cur_fail_count >= mt_data->test_count)) { 2171 return SOC_E_NONE; 2172 } 2173 2174 if (mt_ctrl->tx_offset_cur != -1) { 2175 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2176 "TX offset=%d "), mt_ctrl->tx_offset_cur)); 2177 } 2178 if (mt_ctrl->rx_offset_cur != -1) { 2179 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2180 "RX offset=%d "), mt_ctrl->rx_offset_cur)); 2181 } 2182 if (mt_ctrl->dpeo_sync_dly_cur != -1) { 2183 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2184 "DPEO_SYNC_DLY=%d "), mt_ctrl->dpeo_sync_dly_cur)); 2185 } 2186 if (mt_ctrl->fcd_dpeo_cur != -1) { 2187 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2188 "FCD_DPEO=%d "), mt_ctrl->fcd_dpeo_cur)); 2189 } 2190 if (mt_ctrl->rbus_sync_dly_cur != -1) { 2191 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2192 "RBUS_SYNC_DLY=%d "), mt_ctrl->rbus_sync_dly_cur)); 2193 } 2194 if (mt_ctrl->fcd_rbus_cur != -1) { 2195 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2196 "FCD_RBUS=%d "), mt_ctrl->fcd_rbus_cur)); 2197 } 2198 if (fail_name) { 2199 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2200 ": %s test FAIL %s\n"), fail_name, fail_reason)); 2201 } else { 2202 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2203 ": Fail count=%d\n"), mt_ctrl->cur_fail_count)); 2204 } 2205 2206 return SOC_E_NONE; 2207 } 2208 2209 STATIC int 2210 _soc_memtune_tcam_main(soc_memtune_data_t *mt_data) 2211 { 2212 soc_tcam_info_t *tcam_info; 2213 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 2214 soc_memtune_result_t *result; 2215 int rv, offset_count, index, i; 2216 2217 tcam_info = SOC_CONTROL(mt_ctrl->unit)->tcam_info; 2218 2219 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_TEST_NAME) { 2220 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2221 "TCAM tuning test:%s interface:\n"), 2222 mt_ctrl->intf_name)); 2223 } 2224 2225 /* No TCAM reset on simulation, only need to re-init TCAM to setup 2226 * partitions used by test */ 2227 if (SAL_BOOT_SIMULATION) { 2228 tcam_info->num_tcams = -1; 2229 } 2230 2231 offset_count = (mt_ctrl->tx_offset_max - mt_ctrl->tx_offset_min + 1) * 2232 (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1); 2233 mt_ctrl->fail_array = sal_alloc(offset_count * sizeof(int), 2234 "memtune working data"); 2235 if (mt_ctrl->fail_array == NULL) { 2236 return SOC_E_MEMORY; 2237 } 2238 sal_memset(mt_ctrl->fail_array, 0, offset_count * sizeof(int)); 2239 2240 mt_ctrl->do_setup_for_rbus_test = FALSE; 2241 mt_ctrl->result_count = 0; 2242 2243 for (mt_ctrl->invert_txclk_cur = mt_ctrl->invert_txclk_min; 2244 mt_ctrl->invert_txclk_cur <= mt_ctrl->invert_txclk_max; 2245 mt_ctrl->invert_txclk_cur++) { 2246 for (mt_ctrl->invert_rxclk_cur = mt_ctrl->invert_rxclk_min; 2247 mt_ctrl->invert_rxclk_cur <= mt_ctrl->invert_rxclk_max; 2248 mt_ctrl->invert_rxclk_cur++) { 2249 if (mt_ctrl->invert_txclk_cur != -1 && 2250 mt_ctrl->invert_rxclk_cur != -1) { 2251 (*mt_ctrl->prog_hw3_fn)(mt_data); /* clock invert */ 2252 } 2253 for (mt_ctrl->tx_offset_cur = mt_ctrl->tx_offset_min; 2254 mt_ctrl->tx_offset_cur <= mt_ctrl->tx_offset_max; 2255 mt_ctrl->tx_offset_cur++) { 2256 for (mt_ctrl->rx_offset_cur = mt_ctrl->rx_offset_min; 2257 mt_ctrl->rx_offset_cur <= mt_ctrl->rx_offset_max; 2258 mt_ctrl->rx_offset_cur++) { 2259 (*mt_ctrl->prog_hw2_fn)(mt_data); /* TX/RX */ 2260 if (mt_ctrl->rx_offset_cur == mt_ctrl->rx_offset_min) { 2261 if (*mt_ctrl->per_tx_fn != NULL) { 2262 (*mt_ctrl->per_tx_fn)(mt_data); 2263 } 2264 } 2265 if (*mt_ctrl->per_rx_fn != NULL) { 2266 (*mt_ctrl->per_rx_fn)(mt_data); 2267 } 2268 rv = _soc_memtune_tcam_single_test(mt_data); 2269 if (SOC_FAILURE(rv)) { /* fail unexpected */ 2270 sal_free(mt_ctrl->fail_array); 2271 return rv; 2272 } 2273 index = (mt_ctrl->tx_offset_cur - mt_ctrl->tx_offset_min) * 2274 (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1) + 2275 mt_ctrl->rx_offset_cur - mt_ctrl->rx_offset_min; 2276 mt_ctrl->fail_array[index] = mt_ctrl->cur_fail_count; 2277 } /* mt_ctrl->rx_offset_cur loop */ 2278 } /* mt_ctrl->tx_offset_cur loop */ 2279 result = &mt_ctrl->result[mt_ctrl->result_count]; 2280 result->invert_txclk = mt_ctrl->invert_txclk_cur; 2281 result->invert_rxclk = mt_ctrl->invert_rxclk_cur; 2282 /* Analyze and print result matrix */ 2283 _soc_memtune_txrx_analyze(mt_data); 2284 result->dpeo_sync_dly = mt_ctrl->dpeo_sync_dly_cur; 2285 result->fcd_dpeo = mt_ctrl->fcd_dpeo_cur; 2286 result->rbus_sync_dly = mt_ctrl->rbus_sync_dly_cur; 2287 result->fcd_rbus = mt_ctrl->fcd_rbus_cur; 2288 } /* mt_ctrl->invert_rxclk_cur loop */ 2289 } /* mt_ctrl->invert_txclk_cur loop */ 2290 2291 if (mt_ctrl->invert_txclk_min != -1 && mt_ctrl->invert_rxclk_min != -1) { 2292 result = &mt_ctrl->result[0]; 2293 for (i = 1; i < 4; i++) { 2294 if (result->width * result->height < 2295 mt_ctrl->result[i].width * mt_ctrl->result[i].height) { 2296 result = &mt_ctrl->result[i]; 2297 } 2298 } 2299 mt_ctrl->invert_txclk_cur = result->invert_txclk; 2300 mt_ctrl->invert_rxclk_cur = result->invert_rxclk; 2301 2302 /* Program clock invert setting from the best result */ 2303 (*mt_ctrl->prog_hw3_fn)(mt_data); /* clock invert */ 2304 } else { 2305 mt_ctrl->invert_txclk_cur = mt_ctrl->invert_txclk_min; 2306 mt_ctrl->invert_rxclk_cur = mt_ctrl->invert_rxclk_min; 2307 result = &mt_ctrl->result[0]; 2308 } 2309 2310 if (result->fail_count != offset_count) { 2311 /* Program TX/RX setting from the best result */ 2312 mt_ctrl->tx_offset_cur = result->tx_offset; 2313 mt_ctrl->rx_offset_cur = result->rx_offset; 2314 (*mt_ctrl->prog_hw2_fn)(mt_data); /* TX/RX */ 2315 if (*mt_ctrl->per_tx_fn != NULL) { 2316 (*mt_ctrl->per_tx_fn)(mt_data); 2317 } 2318 if (*mt_ctrl->per_rx_fn != NULL) { 2319 (*mt_ctrl->per_rx_fn)(mt_data); 2320 } 2321 rv = _soc_memtune_tcam_single_test(mt_data); 2322 if (SOC_FAILURE(rv) || mt_ctrl->cur_fail_count) { 2323 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2324 "!!! TCAM tuning FAIL --- unstable result !!!\n"))); 2325 result->fail_count = offset_count; 2326 } else { 2327 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SELECTION) { 2328 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2329 "TCAM tuning selection: "))); 2330 if (mt_ctrl->invert_txclk_cur != -1) { 2331 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2332 "invert_txclk=%d "), 2333 mt_ctrl->invert_txclk_cur)); 2334 } 2335 if (mt_ctrl->invert_rxclk_cur != -1) { 2336 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2337 "invert_rxclk=%d "), 2338 mt_ctrl->invert_rxclk_cur)); 2339 } 2340 if (mt_ctrl->tx_offset_cur != -1) { 2341 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2342 "TX offset=%d "), mt_ctrl->tx_offset_cur)); 2343 } 2344 if (mt_ctrl->rx_offset_cur != -1) { 2345 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2346 "RX offset=%d "), mt_ctrl->rx_offset_cur)); 2347 } 2348 if (mt_ctrl->dpeo_sync_dly_cur != -1) { 2349 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2350 "dpeo_sync_dly=%d "), 2351 mt_ctrl->dpeo_sync_dly_cur)); 2352 } 2353 if (mt_ctrl->fcd_dpeo_cur != -1) { 2354 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2355 "fcd_dpeo=%d "), mt_ctrl->fcd_dpeo_cur)); 2356 } 2357 if (mt_ctrl->rbus_sync_dly_cur != -1) { 2358 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2359 "rbus_sync_dly=%d "), 2360 mt_ctrl->rbus_sync_dly_cur)); 2361 } 2362 if (mt_ctrl->fcd_rbus_cur != -1) { 2363 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2364 "fcd_rbus=%d "), mt_ctrl->fcd_rbus_cur)); 2365 } 2366 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2367 "\n"))); 2368 } 2369 } 2370 } 2371 2372 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY) { 2373 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY_HEADER) { 2374 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2375 "\n Interface , Area , Width , Height ," 2376 " Tc , Rc , TX , RX , Pass , Fail ," 2377 " Freq , Sb , Dac , Dist\n"))); 2378 } 2379 for (i = 0; i < mt_ctrl->result_count; i++) { 2380 result = &mt_ctrl->result[i]; 2381 2382 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2383 " %10s , %4d , %3d , %3d ,"), 2384 mt_ctrl->intf_name, result->width * result->height, 2385 result->width, result->height)); 2386 if (result->invert_txclk != -1) { 2387 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2388 " %c ,"), result->invert_txclk ? 'I' : ' ')); 2389 } else { 2390 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2391 " ** ,"))); 2392 } 2393 if (result->invert_rxclk != -1) { 2394 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2395 " %c ,"), result->invert_rxclk ? 'I' : ' ')); 2396 } else { 2397 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2398 " ** ,"))); 2399 } 2400 if (result->fail_count != offset_count) { 2401 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2402 " %2d , %2d ,"), 2403 result->tx_offset, result->rx_offset)); 2404 } else { 2405 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2406 " ** , ** ,"))); 2407 } 2408 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2409 " %4d , %4d , %3d , %c ,"), 2410 offset_count - result->fail_count, result->fail_count, 2411 mt_data->freq, 2412 mt_data->bg_sram_bist ? 'Y' : 'N')); 2413 if (mt_ctrl->dac_value != -1) { 2414 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2415 " %2d ,"), mt_ctrl->dac_value)); 2416 } else { 2417 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2418 " ** ,"))); 2419 } 2420 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2421 " %2d"), mt_ctrl->ptr_dist)); 2422 if (result->fail_count != offset_count && 2423 mt_ctrl->invert_txclk_cur != -1 && 2424 result->invert_txclk == mt_ctrl->invert_txclk_cur && 2425 mt_ctrl->invert_rxclk_cur != -1 && 2426 result->invert_rxclk == mt_ctrl->invert_rxclk_cur) { 2427 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2428 " <\n"))); 2429 } else { 2430 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2431 "\n"))); 2432 } 2433 } 2434 } 2435 2436 if (result->fail_count == offset_count) { 2437 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2438 "ERROR - no passing \"eye\" was found, \n" 2439 "please contact your Field Applications Engineer or " 2440 "Sales Manager\n" 2441 "for additional assistance.\n"))); 2442 rv = SOC_E_FAIL; 2443 } else { 2444 if (result->height < mt_ctrl->tx_pass_threshold || 2445 result->width < mt_ctrl->rx_pass_threshold) { 2446 LOG_CLI((BSL_META_U(mt_ctrl->unit, 2447 "!!! TCAM tuning result does not pass qualified " 2448 "threshold !!!\n"))); 2449 } 2450 rv = SOC_E_NONE; 2451 if (mt_data->config) { 2452 rv = _soc_tr_tune_generate_config(mt_data); 2453 if (rv < 0) { 2454 LOG_ERROR(BSL_LS_SOC_MEMTUNE, 2455 (BSL_META_U(mt_ctrl->unit, 2456 "%s fail to generate config: %s\n"), 2457 mt_ctrl->intf_name, 2458 soc_errmsg(rv))); 2459 } 2460 } 2461 } 2462 2463 sal_free(mt_ctrl->fail_array); 2464 return rv; 2465 } 2466 #endif /* BCM_TRIUMPH_SUPPORT */ 2467 2468 #ifdef BCM_TRIUMPH_SUPPORT 2469 STATIC int 2470 _soc_tr_mem_interface_tune_setup(soc_memtune_data_t *mt_data) 2471 { 2472 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 2473 soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data; 2474 uint32 rval; 2475 uint16 dev_id; 2476 uint8 rev_id; 2477 2478 soc_cm_get_id(mt_ctrl->unit, &dev_id, &rev_id); 2479 2480 switch (mt_data->interface) { 2481 case SOC_MEM_INTERFACE_SRAM: 2482 switch (mt_data->sub_interface) { 2483 case 0: 2484 mt_ctrl->intf_name = "SRAM0"; 2485 tr_mt_data->config_reg1 = ES0_DDR36_CONFIG_REG1_ISr; 2486 tr_mt_data->config_reg2 = ES0_DDR36_CONFIG_REG2_ISr; 2487 tr_mt_data->config_reg3 = ES0_DDR36_CONFIG_REG3_ISr; 2488 tr_mt_data->status_reg2 = ES0_DDR36_STATUS_REG2_ISr; 2489 tr_mt_data->mode = ES0_DTU_MODEr; 2490 tr_mt_data->tmode0 = ES0_DTU_LTE_TMODE0r; 2491 tr_mt_data->tmode0_other_sram = ES1_DTU_LTE_TMODE0r; 2492 tr_mt_data->sram_ctl = ES0_SRAM_CTLr; 2493 break; 2494 case 1: 2495 mt_ctrl->intf_name = "SRAM1"; 2496 tr_mt_data->config_reg1 = ES1_DDR36_CONFIG_REG1_ISr; 2497 tr_mt_data->config_reg2 = ES1_DDR36_CONFIG_REG2_ISr; 2498 tr_mt_data->config_reg3 = ES1_DDR36_CONFIG_REG3_ISr; 2499 tr_mt_data->status_reg2 = ES1_DDR36_STATUS_REG2_ISr; 2500 tr_mt_data->mode = ES1_DTU_MODEr; 2501 tr_mt_data->tmode0 = ES1_DTU_LTE_TMODE0r; 2502 tr_mt_data->tmode0_other_sram = ES0_DTU_LTE_TMODE0r; 2503 tr_mt_data->sram_ctl = ES1_SRAM_CTLr; 2504 break; 2505 default: 2506 return SOC_E_PARAM; 2507 } 2508 2509 if ((SOC_IS_TRIUMPH(mt_ctrl->unit) && rev_id >= BCM56624_B2_REV_ID) || 2510 SOC_IS_TRIUMPH2(mt_ctrl->unit)) { 2511 mt_ctrl->tx_pass_threshold = 9; 2512 mt_ctrl->rx_pass_threshold = 11; 2513 } 2514 2515 if (soc_feature(mt_ctrl->unit, soc_feature_esm_rxfifo_resync)) { 2516 mt_data->phase_sel_ovrd = FALSE; 2517 } 2518 2519 mt_ctrl->prog_hw1_fn = _soc_tr_ddr_txrx_prog_hw_cb; 2520 mt_ctrl->prog_hw2_fn = _soc_tr_ddr_latency_prog_hw_cb; 2521 mt_ctrl->prog_hw3_fn = _soc_tr_ddr_phase_sel_prog_hw_cb; 2522 mt_ctrl->prog_hw4_fn = _soc_tr_ddr_nops_prog_hw_cb; 2523 if (soc_feature(mt_ctrl->unit, soc_feature_esm_rxfifo_resync)) { 2524 mt_ctrl->per_rx_fn = _soc_tr_ddr_per_rx_cb; 2525 } 2526 mt_ctrl->test_fn = _soc_tr_sram_tune_test_cb; 2527 2528 mt_ctrl->phase_sel_min = 2529 mt_data->phase_sel_ovrd ? SOC_TR_PHASE_SEL_MIN : -1; 2530 mt_ctrl->phase_sel_max = 2531 mt_data->phase_sel_ovrd ? SOC_TR_PHASE_SEL_MAX : -1; 2532 mt_ctrl->em_latency_min = SOC_TR_EM_LATENCY_MIN; 2533 if (soc_reg_field_valid(mt_ctrl->unit, tr_mt_data->tmode0, 2534 EM_LATENCY8f)) { 2535 mt_ctrl->em_latency_max = SOC_TR_EM_LATENCY_MAX;; 2536 } else { 2537 mt_ctrl->em_latency_max = 7; 2538 } 2539 if (mt_data->man_em_latency != -1) { 2540 mt_ctrl->em_latency_min = mt_data->man_em_latency; 2541 mt_ctrl->em_latency_max = mt_data->man_em_latency; 2542 } 2543 if (soc_reg_field_valid(mt_ctrl->unit, tr_mt_data->config_reg2, 2544 SEL_EARLY1_0f)) { 2545 mt_ctrl->ddr_latency_min = SOC_TR_DDR_LATENCY_MIN; 2546 mt_ctrl->ddr_latency_max = SOC_TR_DDR_LATENCY_MAX; 2547 if (mt_data->man_ddr_latency != -1) { 2548 mt_ctrl->ddr_latency_min = mt_data->man_ddr_latency; 2549 mt_ctrl->ddr_latency_max = mt_data->man_ddr_latency; 2550 } 2551 } else { 2552 mt_ctrl->ddr_latency_min = -1; 2553 mt_ctrl->ddr_latency_max = -1; 2554 mt_data->man_ddr_latency = -1; 2555 } 2556 mt_ctrl->tx_offset_min = SOC_TR_SRAM_TX_OFFSET_MIN; 2557 mt_ctrl->tx_offset_max = SOC_TR_SRAM_TX_OFFSET_MAX; 2558 if (mt_data->man_tx_offset != -1) { 2559 mt_ctrl->tx_offset_min = mt_data->man_tx_offset; 2560 mt_ctrl->tx_offset_max = mt_data->man_tx_offset; 2561 } 2562 mt_ctrl->rx_offset_min = SOC_TR_SRAM_RX_OFFSET_MIN; 2563 mt_ctrl->rx_offset_max = SOC_TR_SRAM_RX_OFFSET_MAX; 2564 if (mt_data->man_rx_offset != -1) { 2565 mt_ctrl->rx_offset_min = mt_data->man_rx_offset; 2566 mt_ctrl->rx_offset_max = mt_data->man_rx_offset; 2567 } 2568 mt_ctrl->w2r_nops_min = SOC_TR_SRAM_W2R_NOPS_MIN; 2569 mt_ctrl->w2r_nops_max = SOC_TR_SRAM_W2R_NOPS_MAX; 2570 mt_ctrl->r2w_nops_min = SOC_TR_SRAM_R2W_NOPS_MIN; 2571 mt_ctrl->r2w_nops_max = SOC_TR_SRAM_R2W_NOPS_MAX; 2572 break; 2573 2574 case SOC_MEM_INTERFACE_TCAM: 2575 mt_ctrl->intf_name = "TCAM"; 2576 tr_mt_data->config_reg1 = ETU_DDR72_CONFIG_REG1_ISr; 2577 tr_mt_data->config_reg3 = ETU_DDR72_CONFIG_REG3_ISr; 2578 tr_mt_data->etc_ctl = ETC_CTLr; 2579 tr_mt_data->inst_status = ETU_ET_INST_STATUSr; 2580 tr_mt_data->dbus_fail_mask = 0; 2581 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2582 &tr_mt_data->dbus_fail_mask, SEQ_DPEO_ERRf, 1); 2583 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2584 &tr_mt_data->dbus_fail_mask, DPEO_RISEf, 1); 2585 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2586 &tr_mt_data->dbus_fail_mask, DPEO_FALLf, 1); 2587 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2588 &tr_mt_data->dbus_fail_mask, DPRERR0f, 1); 2589 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2590 &tr_mt_data->dbus_fail_mask, DPRERR1f, 1); 2591 tr_mt_data->rbus_fail_mask = 0; 2592 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2593 &tr_mt_data->rbus_fail_mask, SEQ_DPEO_ERRf, 1); 2594 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2595 &tr_mt_data->rbus_fail_mask, RDACKf, 1); 2596 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2597 &tr_mt_data->rbus_fail_mask, DPEO_RISEf, 1); 2598 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2599 &tr_mt_data->rbus_fail_mask, DPEO_FALLf, 1); 2600 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2601 &tr_mt_data->rbus_fail_mask, DPRERR0f, 1); 2602 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2603 &tr_mt_data->rbus_fail_mask, DPRERR1f, 1); 2604 tr_mt_data->rbus_valid_mask = 0; 2605 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2606 &tr_mt_data->rbus_valid_mask, RBUS0_VALIDf, 1); 2607 soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status, 2608 &tr_mt_data->rbus_valid_mask, RBUS1_VALIDf, 1); 2609 2610 if ((SOC_IS_TRIUMPH(mt_ctrl->unit) && rev_id >= BCM56624_B2_REV_ID) || 2611 SOC_IS_TRIUMPH2(mt_ctrl->unit)) { 2612 mt_ctrl->tx_pass_threshold = 11; 2613 mt_ctrl->rx_pass_threshold = 11; 2614 } 2615 2616 mt_ctrl->prog_hw1_fn = _soc_tr_tcam_dpeo_rbus_prog_hw_cb; 2617 mt_ctrl->prog_hw2_fn = _soc_tr_tcam_txrx_prog_hw_cb; 2618 mt_ctrl->prog_hw3_fn = _soc_tr_tcam_invert_clk_prog_hw_cb; 2619 mt_ctrl->per_tx_fn = _soc_tr_tcam_per_tx_cb; 2620 mt_ctrl->per_rx_fn = _soc_tr_tcam_per_rx_cb; 2621 mt_ctrl->test_fn = _soc_tr_tcam_tune_test_cb; 2622 2623 SOC_IF_ERROR_RETURN 2624 (READ_ETU_DDR72_CONFIG_REG3_ISr(mt_ctrl->unit, &rval)); 2625 if (soc_reg_field_valid(mt_ctrl->unit, ETU_DDR72_CONFIG_REG3_ISr, 2626 INVERT_TXCLKf)) { 2627 if (mt_data->phase_sel_ovrd) { 2628 mt_ctrl->invert_txclk_min = SOC_TR_TCAM_INVERT_TXCLK_MIN; 2629 mt_ctrl->invert_txclk_max = SOC_TR_TCAM_INVERT_TXCLK_MAX; 2630 } else { 2631 mt_ctrl->invert_txclk_min = 2632 mt_ctrl->invert_txclk_max = 2633 soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG3_ISr, 2634 rval, INVERT_TXCLKf); 2635 } 2636 } else { 2637 mt_ctrl->invert_txclk_min = -1; 2638 mt_ctrl->invert_txclk_max = -1; 2639 } 2640 if (soc_reg_field_valid(mt_ctrl->unit, ETU_DDR72_CONFIG_REG3_ISr, 2641 INVERT_RXCLKf)) { 2642 if (mt_data->phase_sel_ovrd) { 2643 mt_ctrl->invert_rxclk_min = SOC_TR_TCAM_INVERT_RXCLK_MIN; 2644 mt_ctrl->invert_rxclk_max = SOC_TR_TCAM_INVERT_RXCLK_MAX; 2645 } else { 2646 mt_ctrl->invert_rxclk_min = 2647 mt_ctrl->invert_rxclk_max = 2648 soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG3_ISr, 2649 rval, INVERT_RXCLKf); 2650 } 2651 } else { 2652 mt_ctrl->invert_rxclk_min = -1; 2653 mt_ctrl->invert_rxclk_max = -1; 2654 } 2655 SOC_IF_ERROR_RETURN 2656 (READ_ETU_DDR72_CONFIG_REG1_ISr(mt_ctrl->unit, &rval)); 2657 mt_ctrl->tx_offset_min = SOC_TR_TCAM_TX_OFFSET_MIN; 2658 if (soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr, 2659 rval, MIDL_TX_ENf) && 2660 soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr, 2661 rval, SEL_TX_CLKDLY_BLKf)) { 2662 mt_ctrl->tx_offset_max = SOC_TR_TCAM_MIDL_TX_OFFSET_MAX; 2663 } else { 2664 mt_ctrl->tx_offset_max = SOC_TR_TCAM_VCDL_TX_OFFSET_MAX; 2665 } 2666 if (mt_data->man_tx_offset != -1) { 2667 mt_ctrl->tx_offset_min = mt_data->man_tx_offset; 2668 mt_ctrl->tx_offset_max = mt_data->man_tx_offset; 2669 } 2670 mt_ctrl->rx_offset_min = SOC_TR_TCAM_RX_OFFSET_MIN; 2671 if (soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr, 2672 rval, MIDL_RX_ENf) && 2673 soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr, 2674 rval, SEL_RX_CLKDLY_BLKf)) { 2675 mt_ctrl->rx_offset_max = SOC_TR_TCAM_MIDL_RX_OFFSET_MAX; 2676 } else { 2677 mt_ctrl->rx_offset_max = SOC_TR_TCAM_VCDL_RX_OFFSET_MAX; 2678 } 2679 if (mt_data->man_rx_offset != -1) { 2680 mt_ctrl->rx_offset_min = mt_data->man_rx_offset; 2681 mt_ctrl->rx_offset_max = mt_data->man_rx_offset; 2682 } 2683 2684 mt_ctrl->dpeo_sel_cur = 0; /* do DPEO_0 only */ 2685 mt_ctrl->dpeo_sync_dly_min = SOC_TR_DPEO_SYNC_DLY_MIN; 2686 mt_ctrl->dpeo_sync_dly_max = SOC_TR_DPEO_SYNC_DLY_MAX; 2687 mt_ctrl->fcd_dpeo_min = SOC_TR_FCD_DPEO_MIN; 2688 mt_ctrl->fcd_dpeo_max = SOC_TR_FCD_DPEO_MAX; 2689 2690 mt_ctrl->rbus_sync_dly_min = SOC_TR_RBUS_SYNC_DLY_MIN; 2691 mt_ctrl->rbus_sync_dly_max = SOC_TR_RBUS_SYNC_DLY_MAX; 2692 mt_ctrl->fcd_rbus_min = SOC_TR_FCD_RBUS_MIN; 2693 mt_ctrl->fcd_rbus_max = SOC_TR_FCD_RBUS_MAX; 2694 break; 2695 2696 default: 2697 return SOC_E_PARAM; 2698 } 2699 2700 if (mt_ctrl->tx_pass_threshold > 2701 mt_ctrl->tx_offset_max - mt_ctrl->tx_offset_min + 1) { 2702 mt_ctrl->tx_pass_threshold = 0; 2703 } 2704 if (mt_ctrl->rx_pass_threshold > 2705 mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1) { 2706 mt_ctrl->rx_pass_threshold = 0; 2707 } 2708 2709 return SOC_E_NONE; 2710 } 2711 2712 STATIC int 2713 _soc_tr_mem_interface_tune(int unit, soc_memtune_data_t *mt_data) 2714 { 2715 soc_tcam_info_t *tcam_info; 2716 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 2717 soc_tr_memtune_data_t *tr_mt_data; 2718 tr_ext_sram_bist_t *sram_bist, bg_sram_bist; 2719 soc_reg_t reg; 2720 uint32 addr, rval, sub_interface_mask; 2721 int rv, i; 2722 2723 tcam_info = SOC_CONTROL(unit)->tcam_info; 2724 if (tcam_info == NULL) { 2725 return SOC_E_INIT; 2726 } 2727 2728 tr_mt_data = sal_alloc(sizeof(soc_tr_memtune_data_t), 2729 "memtune working data"); 2730 if (!tr_mt_data) { 2731 return SOC_E_MEMORY; 2732 } 2733 sal_memset(tr_mt_data, 0, sizeof(soc_tr_memtune_data_t)); 2734 mt_ctrl->data = tr_mt_data; 2735 2736 sram_bist = sal_alloc(sizeof(tr_ext_sram_bist_t), "memtune working data"); 2737 if (!sram_bist) { 2738 return SOC_E_MEMORY; 2739 } 2740 sal_memset(sram_bist, 0, sizeof(tr_ext_sram_bist_t)); 2741 mt_ctrl->sram_bist = sram_bist; 2742 2743 if (mt_data->bg_sram_bist) { 2744 sal_memset(&bg_sram_bist, 0, sizeof(bg_sram_bist)); 2745 if (mt_data->bg_d0r_0 == 0xffffffff) { 2746 bg_sram_bist.d0r_0 = bg_sram_bist.d0r_1 = 0x3ffff; 2747 bg_sram_bist.d0f_0 = bg_sram_bist.d0f_1 = 0; 2748 bg_sram_bist.d1r_0 = bg_sram_bist.d1r_1 = 0x3ffff; 2749 bg_sram_bist.d1f_0 = bg_sram_bist.d1f_1 = 0; 2750 } else { 2751 bg_sram_bist.d0r_0 = mt_data->bg_d0r_0 & 0x3ffff; 2752 bg_sram_bist.d0r_1 = mt_data->bg_d0r_1 & 0x3ffff; 2753 bg_sram_bist.d0f_0 = mt_data->bg_d0f_0 & 0x3ffff; 2754 bg_sram_bist.d0f_1 = mt_data->bg_d0f_1 & 0x3ffff; 2755 bg_sram_bist.d1r_0 = mt_data->bg_d1r_0 & 0x3ffff; 2756 bg_sram_bist.d1r_1 = mt_data->bg_d1r_1 & 0x3ffff; 2757 bg_sram_bist.d1f_0 = mt_data->bg_d1f_0 & 0x3ffff; 2758 bg_sram_bist.d1f_1 = mt_data->bg_d1f_1 & 0x3ffff; 2759 } 2760 if (mt_data->bg_adr0 == -1) { 2761 bg_sram_bist.adr0 = 0x0; /* starting address */ 2762 } else { 2763 bg_sram_bist.adr0 = mt_data->bg_adr0 & 0x3ffffe; 2764 } 2765 if (mt_data->bg_adr1 == -1 || mt_data->bg_adr_mode == 3) { 2766 bg_sram_bist.adr1 = 0x10; /* end address */ 2767 } else { 2768 bg_sram_bist.adr1 = mt_data->bg_adr1 & 0x3ffffe; 2769 } 2770 if (mt_data->bg_loop_mode == -1) { 2771 bg_sram_bist.loop_mode = 3; /* WW_RR */ 2772 } else { 2773 bg_sram_bist.loop_mode = mt_data->bg_loop_mode & 3; 2774 } 2775 if (mt_data->bg_adr_mode == -1) { 2776 bg_sram_bist.adr_mode = 2; /* from ADR0 to ADR1 w/ step of 2 */ 2777 } else { 2778 bg_sram_bist.adr_mode = mt_data->bg_adr_mode & 3; 2779 } 2780 bg_sram_bist.em_latency = -1; 2781 bg_sram_bist.w2r_nops = -1; 2782 bg_sram_bist.r2w_nops = -1; 2783 } 2784 2785 switch (mt_data->interface) { 2786 case SOC_MEM_INTERFACE_SRAM: 2787 if (mt_data->sub_interface > 1) { 2788 return SOC_E_PARAM; 2789 } else if (mt_data->sub_interface < 0) { 2790 sub_interface_mask = 0x3; 2791 } else { 2792 sub_interface_mask = 1 << mt_data->sub_interface; 2793 } 2794 2795 /* (Optionally) program frequency */ 2796 if (mt_data->freq != -1) { 2797 (void)soc_triumph_esm_init_set_sram_freq(unit, mt_data->freq); 2798 } else { 2799 mt_data->freq = tcam_info->sram_freq; 2800 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) { 2801 LOG_CLI((BSL_META_U(unit, 2802 "Using SRAM frequency %d\n"), 2803 tcam_info->sram_freq)); 2804 } 2805 } 2806 2807 rv = SOC_E_NONE; 2808 for (i = 0; i < 2; i++) { 2809 if (!(sub_interface_mask & (1 << i))) { 2810 continue; 2811 } 2812 mt_data->sub_interface = i; 2813 SOC_IF_ERROR_RETURN 2814 (_soc_tr_mem_interface_tune_setup(mt_data)); 2815 2816 /* Setup sram_bist control structure 2817 * -- --------- --------- --------- --------- -- 2818 * \ / \ / \ / \ / \ / 2819 * DQ[35:18] X D0R_1 X D0F_1 X D1R_1 X D1F_1 X 2820 * / \ / \ / \ / \ / \ 2821 * -- --------- --------- --------- --------- -- 2822 * 2823 * -- --------- --------- --------- --------- -- 2824 * \ / \ / \ / \ / \ / 2825 * DQ[17:0] X D0R_0 X D0F_0 X D1R_0 X D1F_0 X 2826 * / \ / \ / \ / \ / \ 2827 * -- --------- --------- --------- --------- -- 2828 */ 2829 if (mt_data->d0r_0 == 0xffffffff) { 2830 sram_bist->d1r_0 = sram_bist->d0r_0 = 0xffffffff & 0x3ffff; 2831 sram_bist->d1r_1 = sram_bist->d0r_1 = 0x55555555 & 0x3ffff; 2832 sram_bist->d1f_0 = sram_bist->d0f_0 = 0x00000000 & 0x3ffff; 2833 sram_bist->d1f_1 = sram_bist->d0f_1 = 0xaaaaaaaa & 0x3ffff; 2834 } else { 2835 sram_bist->d0r_0 = mt_data->d0r_0 & 0x3ffff; 2836 sram_bist->d0r_1 = mt_data->d0r_1 & 0x3ffff; 2837 sram_bist->d0f_0 = mt_data->d0f_0 & 0x3ffff; 2838 sram_bist->d0f_1 = mt_data->d0f_1 & 0x3ffff; 2839 sram_bist->d1r_0 = mt_data->d1r_0 & 0x3ffff; 2840 sram_bist->d1r_1 = mt_data->d1r_1 & 0x3ffff; 2841 sram_bist->d1f_0 = mt_data->d1f_0 & 0x3ffff; 2842 sram_bist->d1f_1 = mt_data->d1f_1 & 0x3ffff; 2843 } 2844 if (mt_data->adr0 == -1) { 2845 sram_bist->adr0 = 0x0; /* starting address */ 2846 } else { 2847 sram_bist->adr0 = mt_data->adr0 & 0x3ffffe; 2848 } 2849 if (mt_data->adr1 == -1 || mt_data->adr_mode == 3) { 2850 sram_bist->adr1 = 0x10; /* end address */ 2851 } else { 2852 sram_bist->adr1 = mt_data->adr1 & 0x3ffffe; 2853 } 2854 if (mt_data->adr_mode == -1) { 2855 sram_bist->adr_mode = 2; /* from ADR0 to ADR1 w/ step of 2 */ 2856 } else { 2857 sram_bist->adr_mode = mt_data->adr_mode & 3; 2858 } 2859 sram_bist->wdoebr = -1; 2860 sram_bist->em_latency = -1; 2861 sram_bist->w2r_nops = -1; 2862 sram_bist->r2w_nops = -1; 2863 SOC_IF_ERROR_RETURN 2864 (soc_triumph_ext_sram_bist_setup(unit, mt_data->sub_interface, 2865 sram_bist)); 2866 2867 /* 2868 * Following sram bist registers has been set properly, 2869 * don't touch them during test to save time: 2870 * D0R_0, D0R_1, D0F_0, D0F_1, D1R_0, D1R_1, D1F_0, D1F_1, 2871 * ADR0, ADR1, TMODE1 2872 */ 2873 sram_bist->d0r_0 = 0xffffffff; 2874 sram_bist->d1r_0 = 0xffffffff; 2875 sram_bist->adr0 = -1; 2876 sram_bist->adr1 = -1; 2877 sram_bist->wdoebr = -1; 2878 2879 /* Get BIASGEN DAC_VALUE */ 2880 reg = tr_mt_data->config_reg3; 2881 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 2882 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &rval)); 2883 mt_ctrl->dac_value = -1; 2884 if (soc_reg_field_get(unit, reg, rval, BIASGEN_DAC_ENf)) { 2885 mt_ctrl->dac_value = soc_reg_field_get(unit, reg, rval, 2886 BIASGEN_DAC_CTRLf); 2887 } 2888 2889 /* Optionally do PVT compensation */ 2890 mt_ctrl->odtres_val = -1; 2891 mt_ctrl->pdrive_val = -1; 2892 mt_ctrl->ndrive_val = -1; 2893 mt_ctrl->slew_val = -1; 2894 if (mt_data->do_pvt_comp) { 2895 reg = tr_mt_data->config_reg2; 2896 SOC_IF_ERROR_RETURN(soc_triumph_esm_init_pvt_comp(unit, i)); 2897 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 2898 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &rval)); 2899 if (soc_reg_field_get(unit, reg, rval, OVRD_EN_ODTRES_PVTf)) { 2900 mt_ctrl->odtres_val = soc_reg_field_get(unit, reg, rval, 2901 PVT_ODTRES_VALf); 2902 } 2903 if (soc_reg_field_get(unit, reg, rval, OVRD_EN_DRIVER_PVTf)) { 2904 mt_ctrl->pdrive_val = soc_reg_field_get(unit, reg, rval, 2905 PVT_PDRIVE_VALf); 2906 mt_ctrl->ndrive_val = soc_reg_field_get(unit, reg, rval, 2907 PVT_NDRIVE_VALf); 2908 } 2909 if (soc_reg_field_get(unit, reg, rval, OVRD_EN_SLEW_PVTf)) { 2910 mt_ctrl->slew_val = soc_reg_field_get(unit, reg, rval, 2911 PVT_SLEW_VALf); 2912 } 2913 } 2914 2915 /* Optionally setup background TCAM BIST */ 2916 if (mt_data->bg_tcam_bist) { 2917 LOG_CLI((BSL_META_U(unit, 2918 "Do TCAM BIST loop count %d\n"), 2919 mt_data->bg_tcam_loop_count)); 2920 SOC_IF_ERROR_RETURN 2921 (soc_tr_tcam_type1_memtest_dpeo(unit, 8, 2922 mt_data->bg_tcam_oemap, 2923 mt_data->bg_tcam_data)); 2924 rval = 0; 2925 soc_reg_field_set(unit, ETU_LTE_BIST_CTLr, &rval, 2926 RD_EN_BIST_RSLTSf, 1); 2927 soc_reg_field_set(unit, ETU_LTE_BIST_CTLr, &rval, LOOP_COUNTf, 2928 mt_data->bg_tcam_loop_count); 2929 SOC_IF_ERROR_RETURN(WRITE_ETU_LTE_BIST_CTLr(unit, rval)); 2930 } 2931 2932 /* Optionally do background BIST on the other SRAM interface */ 2933 if (mt_data->bg_sram_bist) { 2934 LOG_CLI((BSL_META_U(unit, 2935 "Do SRAM BIST on SRAM%d with loop mode %d\n"), 2936 mt_data->sub_interface ^ 1, 2937 bg_sram_bist.loop_mode)); 2938 soc_triumph_ext_sram_enable_set(unit, 2939 mt_data->sub_interface ^ 1, 2940 TRUE, TRUE); 2941 soc_triumph_ext_sram_bist_setup(unit, 2942 mt_data->sub_interface ^ 1, 2943 &bg_sram_bist); 2944 2945 reg = tr_mt_data->tmode0_other_sram; 2946 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 2947 rv = soc_reg32_read(unit, addr, &rval); 2948 if (SOC_SUCCESS(rv)) { 2949 soc_reg_field_set(unit, reg, &rval, START_LAB_TESTf, 1); 2950 soc_reg_field_set(unit, reg, &rval, FOREVERf, 1); 2951 (void)soc_reg32_write(unit, addr, rval); 2952 } 2953 } 2954 2955 rv = _soc_memtune_ddr_main(mt_data); 2956 2957 if (mt_data->bg_sram_bist) { 2958 soc_reg_field_set(unit, reg, &rval, FOREVERf, 0); 2959 (void)soc_reg32_write(unit, addr, rval); 2960 soc_triumph_ext_sram_enable_set(unit, 2961 mt_data->sub_interface ^ 1, 2962 FALSE, TRUE); 2963 } 2964 2965 if (mt_data->bg_tcam_bist) { 2966 rval = 0; 2967 soc_reg_field_set(unit, ETU_LTE_BIST_CTLr, &rval, LOOP_COUNTf, 2968 1); 2969 SOC_IF_ERROR_RETURN(WRITE_ETU_LTE_BIST_CTLr(unit, rval)); 2970 } 2971 2972 if (SOC_FAILURE(rv)) { 2973 break; 2974 } 2975 } 2976 break; 2977 2978 case SOC_MEM_INTERFACE_TCAM: 2979 if (mt_data->sub_interface > 3) { 2980 return SOC_E_PARAM; 2981 } 2982 mt_data->sub_interface = 0; 2983 SOC_IF_ERROR_RETURN(_soc_tr_mem_interface_tune_setup(mt_data)); 2984 2985 if (mt_data->freq != -1) { 2986 (void)soc_triumph_esm_init_set_tcam_freq(mt_ctrl->unit, 2987 mt_data->freq); 2988 } else { 2989 mt_data->freq = tcam_info->tcam_freq; 2990 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) { 2991 LOG_CLI((BSL_META_U(unit, 2992 "Using TCAM frequency %d\n"), 2993 tcam_info->tcam_freq)); 2994 } 2995 } 2996 2997 SOC_IF_ERROR_RETURN(READ_ETU_DDR72_CONFIG_REG2_ISr(unit, &rval)); 2998 mt_ctrl->dac_value = -1; 2999 if (soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, rval, 3000 BIASGEN_DAC_ENf)) { 3001 mt_ctrl->dac_value = 3002 soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, rval, 3003 BIASGEN_DAC_CTRLf); 3004 } 3005 3006 SOC_IF_ERROR_RETURN(READ_ETU_DDR72_CONFIG_REG1_ISr(unit, &rval)); 3007 mt_ctrl->ptr_dist = 3008 soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG1_ISr, rval, 3009 SEL_WRFIFO_PTR_CLKf); 3010 3011 mt_ctrl->odtres_val = -1; 3012 mt_ctrl->pdrive_val = -1; 3013 mt_ctrl->ndrive_val = -1; 3014 mt_ctrl->slew_val = -1; 3015 if (mt_data->do_pvt_comp) { 3016 SOC_IF_ERROR_RETURN(soc_triumph_esm_init_pvt_comp(unit, 2)); 3017 SOC_IF_ERROR_RETURN 3018 (READ_ETU_DDR72_CONFIG_REG2_ISr(unit, &rval)); 3019 if (soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, rval, 3020 OVRD_EN_ODTRES_PVTf)) { 3021 mt_ctrl->odtres_val = 3022 soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, 3023 rval, PVT_ODTRES_VALf); 3024 } 3025 if (soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, rval, 3026 OVRD_EN_DRIVER_PVTf)) { 3027 mt_ctrl->pdrive_val = 3028 soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, 3029 rval, PVT_PDRIVE_VALf); 3030 mt_ctrl->ndrive_val = 3031 soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, 3032 rval, PVT_NDRIVE_VALf); 3033 } 3034 if (soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, rval, 3035 OVRD_EN_SLEW_PVTf)) { 3036 mt_ctrl->slew_val = 3037 soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, 3038 rval, PVT_SLEW_VALf); 3039 } 3040 } 3041 3042 if (mt_data->bg_sram_bist) { 3043 LOG_CLI((BSL_META_U(unit, 3044 "Do SRAM BIST on both SRAM with loop mode %d\n"), 3045 bg_sram_bist.loop_mode)); 3046 soc_triumph_ext_sram_enable_set(unit, 0, TRUE, TRUE); 3047 soc_triumph_ext_sram_bist_setup(unit, 0, &bg_sram_bist); 3048 SOC_IF_ERROR_RETURN(READ_ES0_DTU_LTE_TMODE0r(unit, &rval)); 3049 soc_reg_field_set(unit, ES0_DTU_LTE_TMODE0r, &rval, 3050 START_LAB_TESTf, 1); 3051 soc_reg_field_set(unit, ES0_DTU_LTE_TMODE0r, &rval, FOREVERf, 1); 3052 SOC_IF_ERROR_RETURN(WRITE_ES0_DTU_LTE_TMODE0r(unit, rval)); 3053 3054 soc_triumph_ext_sram_enable_set(unit, 1, TRUE, TRUE); 3055 soc_triumph_ext_sram_bist_setup(unit, 1, &bg_sram_bist); 3056 SOC_IF_ERROR_RETURN(READ_ES1_DTU_LTE_TMODE0r(unit, &rval)); 3057 soc_reg_field_set(unit, ES1_DTU_LTE_TMODE0r, &rval, 3058 START_LAB_TESTf, 1); 3059 soc_reg_field_set(unit, ES1_DTU_LTE_TMODE0r, &rval, FOREVERf, 1); 3060 SOC_IF_ERROR_RETURN(WRITE_ES1_DTU_LTE_TMODE0r(unit, rval)); 3061 } 3062 3063 rv = _soc_memtune_tcam_main(mt_data); 3064 3065 if (mt_data->bg_sram_bist) { 3066 SOC_IF_ERROR_RETURN(READ_ES0_DTU_LTE_TMODE0r(unit, &rval)); 3067 soc_reg_field_set(unit, ES0_DTU_LTE_TMODE0r, &rval, FOREVERf, 0); 3068 SOC_IF_ERROR_RETURN(WRITE_ES0_DTU_LTE_TMODE0r(unit, rval)); 3069 soc_triumph_ext_sram_enable_set(unit, 0, FALSE, TRUE); 3070 3071 SOC_IF_ERROR_RETURN(READ_ES1_DTU_LTE_TMODE0r(unit, &rval)); 3072 soc_reg_field_set(unit, ES1_DTU_LTE_TMODE0r, &rval, FOREVERf, 0); 3073 SOC_IF_ERROR_RETURN(WRITE_ES1_DTU_LTE_TMODE0r(unit, rval)); 3074 soc_triumph_ext_sram_enable_set(unit, 1, FALSE, TRUE); 3075 } 3076 3077 break; 3078 default: 3079 return SOC_E_UNAVAIL; 3080 } 3081 3082 return rv; 3083 } 3084 #endif /* BCM_TRIUMPH_SUPPORT */ 3085 3086 int 3087 soc_mem_interface_tune(int unit, soc_memtune_data_t *mt_data) 3088 { 3089 soc_memtune_ctrl_t *mt_ctrl; 3090 int rv = SOC_E_NONE; 3091 3092 mt_ctrl = sal_alloc(sizeof(soc_memtune_ctrl_t), "memtune working data"); 3093 if (!mt_ctrl) { 3094 return SOC_E_MEMORY; 3095 } 3096 sal_memset(mt_ctrl, 0, sizeof(soc_memtune_ctrl_t)); 3097 mt_ctrl->unit = unit; 3098 mt_data->mt_ctrl = mt_ctrl; 3099 3100 if (mt_data->verbose) { 3101 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_TEST_NAME | 3102 SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY | 3103 SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY_HEADER | 3104 SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX | 3105 SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS | 3106 SOC_MEMTUNE_CTRL_FLAGS_SHOW_SELECTION | 3107 SOC_MEMTUNE_CTRL_FLAGS_SHOW_PASS | 3108 SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING; 3109 if (!mt_data->suppress_fail) { 3110 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL; 3111 } 3112 } 3113 if (mt_data->summary) { 3114 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY; 3115 } 3116 if (mt_data->summary_header) { 3117 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY_HEADER; 3118 } 3119 if (mt_data->show_matrix) { 3120 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX | 3121 SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS | 3122 SOC_MEMTUNE_CTRL_FLAGS_SHOW_SELECTION; 3123 } 3124 if (mt_data->show_progress) { 3125 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_PROGRESS; 3126 } 3127 3128 #ifdef BCM_TRIUMPH_SUPPORT 3129 if (soc_feature(unit, soc_feature_esm_support)) { 3130 rv = _soc_tr_mem_interface_tune(unit, mt_data); 3131 } 3132 #endif /* BCM_TRIUMPH_SUPPORT */ 3133 3134 if (mt_ctrl->data) { 3135 sal_free(mt_ctrl->data); 3136 } 3137 if (mt_ctrl->sram_bist) { 3138 sal_free(mt_ctrl->sram_bist); 3139 } 3140 sal_free(mt_ctrl); 3141 3142 return rv; 3143 } 3144 3145 #ifdef BCM_TRIUMPH_SUPPORT 3146 STATIC int 3147 _soc_tr_memtune_lvl2_tcam_bist_setup(soc_memtune_data_t *mt_data) 3148 { 3149 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 3150 uint32 oe_map, data[32], rval; 3151 int i; 3152 3153 sal_memset(data, 0, sizeof(data)); 3154 3155 #define SETUP_72BIT_DATA(name,index,d0_msb,d1,d2_lsb) \ 3156 name[index * 4] = d2_lsb; \ 3157 name[index * 4 + 1] = d1; \ 3158 name[index * 4 + 2] = d0_msb; 3159 switch (mt_data->tcam_data_choice) { 3160 case 0: 3161 oe_map = 0xff; 3162 SETUP_72BIT_DATA(data, 0, 0xa5, 0xa5a5a5a5, 0xa5a5a5a5); 3163 SETUP_72BIT_DATA(data, 1, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a); 3164 SETUP_72BIT_DATA(data, 2, 0x00, 0x00000000, 0x00000000); 3165 SETUP_72BIT_DATA(data, 3, 0x22, 0x22222222, 0x22222222); 3166 SETUP_72BIT_DATA(data, 4, 0xff, 0xffffffff, 0xffffffff); 3167 SETUP_72BIT_DATA(data, 5, 0x44, 0x44444444, 0x44444444); 3168 SETUP_72BIT_DATA(data, 6, 0x01, 0x23456789, 0x01234567); 3169 SETUP_72BIT_DATA(data, 7, 0x76, 0x54321098, 0x76543210); 3170 break; 3171 case 1: 3172 oe_map = 0xff; 3173 SETUP_72BIT_DATA(data, 0, 0x00, 0x00000000, 0x00000000); 3174 SETUP_72BIT_DATA(data, 1, 0xff, 0xffffffff, 0xffffffff); 3175 SETUP_72BIT_DATA(data, 2, 0x00, 0x00000000, 0x00000000); 3176 SETUP_72BIT_DATA(data, 3, 0xff, 0xffffffff, 0xffffffff); 3177 SETUP_72BIT_DATA(data, 4, 0x00, 0x00000000, 0x00000000); 3178 SETUP_72BIT_DATA(data, 5, 0xff, 0xffffffff, 0xffffffff); 3179 SETUP_72BIT_DATA(data, 6, 0x00, 0x00000000, 0x00000000); 3180 SETUP_72BIT_DATA(data, 7, 0xff, 0xffffffff, 0xffffffff); 3181 break; 3182 case 2: 3183 oe_map = 0xff; 3184 SETUP_72BIT_DATA(data, 0, 0xa5, 0xa5a5a5a5, 0xa5a5a5a5); 3185 SETUP_72BIT_DATA(data, 1, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a); 3186 SETUP_72BIT_DATA(data, 2, 0xa5, 0xa5a5a5a5, 0xa5a5a5a5); 3187 SETUP_72BIT_DATA(data, 3, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a); 3188 SETUP_72BIT_DATA(data, 4, 0xa5, 0xa5a5a5a5, 0xa5a5a5a5); 3189 SETUP_72BIT_DATA(data, 5, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a); 3190 SETUP_72BIT_DATA(data, 6, 0xa5, 0xa5a5a5a5, 0xa5a5a5a5); 3191 SETUP_72BIT_DATA(data, 7, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a); 3192 break; 3193 case 3: 3194 oe_map = 0xff; 3195 SETUP_72BIT_DATA(data, 0, 0x00, 0x00000000, 0x00000000); 3196 SETUP_72BIT_DATA(data, 1, 0x00, 0x00000000, 0x00000000); 3197 SETUP_72BIT_DATA(data, 2, 0x00, 0x00000000, 0x00000000); 3198 SETUP_72BIT_DATA(data, 3, 0x00, 0x00000000, 0x00000000); 3199 SETUP_72BIT_DATA(data, 4, 0x00, 0x00000000, 0x00000000); 3200 SETUP_72BIT_DATA(data, 5, 0x00, 0x00000000, 0x00000000); 3201 SETUP_72BIT_DATA(data, 6, 0x00, 0x00000000, 0x00000000); 3202 SETUP_72BIT_DATA(data, 7, 0x00, 0x00000000, 0x00000000); 3203 break; 3204 case 4: 3205 oe_map = 0xff; 3206 SETUP_72BIT_DATA(data, 0, 0xaa, 0xaaaaaaaa, 0xaaaaaaaa); 3207 SETUP_72BIT_DATA(data, 1, 0x55, 0x55555555, 0x55555555); 3208 SETUP_72BIT_DATA(data, 2, 0xaa, 0xaaaaaaaa, 0xaaaaaaaa); 3209 SETUP_72BIT_DATA(data, 3, 0x55, 0x55555555, 0x55555555); 3210 SETUP_72BIT_DATA(data, 4, 0xaa, 0xaaaaaaaa, 0xaaaaaaaa); 3211 SETUP_72BIT_DATA(data, 5, 0x55, 0x55555555, 0x55555555); 3212 SETUP_72BIT_DATA(data, 6, 0xaa, 0xaaaaaaaa, 0xaaaaaaaa); 3213 SETUP_72BIT_DATA(data, 7, 0x55, 0x55555555, 0x55555555); 3214 break; 3215 case 5: 3216 oe_map = 0xff; 3217 SETUP_72BIT_DATA(data, 0, 0xff, 0xffffffff, 0xffffffff); 3218 SETUP_72BIT_DATA(data, 1, 0xff, 0xffffffff, 0xffffffff); 3219 SETUP_72BIT_DATA(data, 2, 0xff, 0xffffffff, 0xffffffff); 3220 SETUP_72BIT_DATA(data, 3, 0xff, 0xffffffff, 0xffffffff); 3221 SETUP_72BIT_DATA(data, 4, 0xff, 0xffffffff, 0xffffffff); 3222 SETUP_72BIT_DATA(data, 5, 0xff, 0xffffffff, 0xffffffff); 3223 SETUP_72BIT_DATA(data, 6, 0xff, 0xffffffff, 0xffffffff); 3224 SETUP_72BIT_DATA(data, 7, 0xff, 0xffffffff, 0xffffffff); 3225 break; 3226 case 6: 3227 oe_map = 0x55; 3228 SETUP_72BIT_DATA(data, 0, 0xff, 0xffffffff, 0xffffffff); 3229 SETUP_72BIT_DATA(data, 2, 0xff, 0xffffffff, 0xffffffff); 3230 SETUP_72BIT_DATA(data, 4, 0xff, 0xffffffff, 0xffffffff); 3231 SETUP_72BIT_DATA(data, 6, 0xff, 0xffffffff, 0xffffffff); 3232 break; 3233 case 7: 3234 oe_map = 0x55; 3235 SETUP_72BIT_DATA(data, 0, 0x00, 0x00000000, 0x00000000); 3236 SETUP_72BIT_DATA(data, 2, 0x00, 0x00000000, 0x00000000); 3237 SETUP_72BIT_DATA(data, 4, 0x00, 0x00000000, 0x00000000); 3238 SETUP_72BIT_DATA(data, 6, 0x00, 0x00000000, 0x00000000); 3239 break; 3240 case 8: 3241 oe_map = 0xff; 3242 SETUP_72BIT_DATA(data, 0, 0x00, 0x0000000f, 0xffffffff); 3243 SETUP_72BIT_DATA(data, 1, 0x00, 0x00000000, 0x00000000); 3244 SETUP_72BIT_DATA(data, 2, 0x00, 0x0000000f, 0xffffffff); 3245 SETUP_72BIT_DATA(data, 3, 0x00, 0x00000000, 0x00000000); 3246 SETUP_72BIT_DATA(data, 4, 0x00, 0x0000000f, 0xffffffff); 3247 SETUP_72BIT_DATA(data, 5, 0x00, 0x00000000, 0x00000000); 3248 SETUP_72BIT_DATA(data, 6, 0x00, 0x0000000f, 0xffffffff); 3249 SETUP_72BIT_DATA(data, 7, 0x00, 0x00000000, 0x00000000); 3250 break; 3251 case 81: 3252 oe_map = 0xff; 3253 SETUP_72BIT_DATA(data, 0, 0xff, 0xfffffff0, 0x00000000); 3254 SETUP_72BIT_DATA(data, 1, 0x00, 0x00000000, 0x00000000); 3255 SETUP_72BIT_DATA(data, 2, 0xff, 0xfffffff0, 0x00000000); 3256 SETUP_72BIT_DATA(data, 3, 0x00, 0x00000000, 0x00000000); 3257 SETUP_72BIT_DATA(data, 4, 0xff, 0xfffffff0, 0x00000000); 3258 SETUP_72BIT_DATA(data, 5, 0x00, 0x00000000, 0x00000000); 3259 SETUP_72BIT_DATA(data, 6, 0xff, 0xfffffff0, 0x00000000); 3260 SETUP_72BIT_DATA(data, 7, 0x00, 0x00000000, 0x00000000); 3261 break; 3262 case 200: 3263 oe_map = 0xff; 3264 SETUP_72BIT_DATA(data, 0, 0x00, 0x00000000, 0x00000000); 3265 SETUP_72BIT_DATA(data, 1, 0x6d, 0xb6df6db6, 0xdb6fd6db); 3266 SETUP_72BIT_DATA(data, 2, 0x00, 0x00000000, 0x00000000); 3267 SETUP_72BIT_DATA(data, 3, 0x6d, 0xb6df6db6, 0xdb6fd6db); 3268 SETUP_72BIT_DATA(data, 4, 0x00, 0x00000000, 0x00000000); 3269 SETUP_72BIT_DATA(data, 5, 0x6d, 0xb6df6db6, 0xdb6fd6db); 3270 SETUP_72BIT_DATA(data, 6, 0x00, 0x00000000, 0x00000000); 3271 SETUP_72BIT_DATA(data, 7, 0x6d, 0xb6df6db6, 0xdb6fd6db); 3272 break; 3273 case 2000: 3274 oe_map = 0; 3275 break; 3276 default: 3277 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3278 "Unknown TcamDataChoice %d\n"), mt_data->tcam_data_choice)); 3279 return SOC_E_PARAM; 3280 } 3281 #undef SETUP_72BIT_DATA 3282 3283 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) { 3284 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3285 "TCAM setting:\n"))); 3286 for (i = 0; i < 8; i++) { 3287 if (oe_map & (1 << i)) { 3288 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3289 " K%d: %02x-%08x-%08x OE: ENABLE\n"), 3290 i, data[i * 4 + 2], data[i * 4 + 1], data[i * 4])); 3291 } else { 3292 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3293 " K%d: zz-zzzzzzzz-zzzzzzzz OE: DISABLE\n"), i)); 3294 } 3295 } 3296 } 3297 SOC_IF_ERROR_RETURN 3298 (soc_tr_tcam_type1_memtest_dpeo(mt_ctrl->unit, 8, oe_map, data)); 3299 3300 rval = 0; 3301 soc_reg_field_set(mt_ctrl->unit, ETU_LTE_BIST_CTLr, &rval, 3302 RD_EN_BIST_RSLTSf, 1); 3303 soc_reg_field_set(mt_ctrl->unit, ETU_LTE_BIST_CTLr, &rval, LOOP_COUNTf, 3304 mt_data->tcam_loop_count); 3305 SOC_IF_ERROR_RETURN(WRITE_ETU_LTE_BIST_CTLr(mt_ctrl->unit, rval)); 3306 3307 return SOC_E_NONE; 3308 } 3309 3310 STATIC int 3311 _soc_tr_memtune_lvl2_sram_bist_setup(soc_memtune_data_t *mt_data) 3312 { 3313 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 3314 tr_ext_sram_bist_t sram_bist; 3315 soc_reg_t reg; 3316 int addr; 3317 uint32 rval; 3318 3319 sal_memset(&sram_bist, 0, sizeof(sram_bist)); 3320 3321 #define SPLIT_36BIT_DATA(name,d0_msb,d1_lsb) \ 3322 name## _0 = (d1_lsb) & 0x3ffff; \ 3323 name## _1 = ((d0_msb & 0xf) << 14) | ((d1_lsb & 0xfffc0000) >> 18); 3324 switch (mt_data->sram_data_choice) { 3325 case -1: 3326 SPLIT_36BIT_DATA(sram_bist.d0r, 0x1, 0x23456789); 3327 SPLIT_36BIT_DATA(sram_bist.d0f, 0xa, 0xbcdef012); 3328 SPLIT_36BIT_DATA(sram_bist.d1r, 0x3, 0x456789ab); 3329 SPLIT_36BIT_DATA(sram_bist.d1f, 0xc, 0xdef01234); 3330 break; 3331 case 0: 3332 SPLIT_36BIT_DATA(sram_bist.d0r, 0x5, 0x55555555); 3333 SPLIT_36BIT_DATA(sram_bist.d0f, 0xa, 0xaaaaaaaa); 3334 SPLIT_36BIT_DATA(sram_bist.d1r, 0x5, 0x55555555); 3335 SPLIT_36BIT_DATA(sram_bist.d1f, 0xa, 0xaaaaaaaa); 3336 break; 3337 case 1: 3338 SPLIT_36BIT_DATA(sram_bist.d0r, 0xf, 0xffffffff); 3339 SPLIT_36BIT_DATA(sram_bist.d0f, 0x0, 0x00000000); 3340 SPLIT_36BIT_DATA(sram_bist.d1r, 0xf, 0xffffffff); 3341 SPLIT_36BIT_DATA(sram_bist.d1f, 0x0, 0x00000000); 3342 break; 3343 case 2: 3344 SPLIT_36BIT_DATA(sram_bist.d0r, 0xf, 0xffffffff); 3345 SPLIT_36BIT_DATA(sram_bist.d0f, 0xf, 0xffffffff); 3346 SPLIT_36BIT_DATA(sram_bist.d1r, 0x0, 0x00000000); 3347 SPLIT_36BIT_DATA(sram_bist.d1f, 0x0, 0x00000000); 3348 break; 3349 case 3: 3350 SPLIT_36BIT_DATA(sram_bist.d0r, 0x0, 0x00000000); 3351 SPLIT_36BIT_DATA(sram_bist.d0f, 0x0, 0x00000000); 3352 SPLIT_36BIT_DATA(sram_bist.d1r, 0xf, 0xffffffff); 3353 SPLIT_36BIT_DATA(sram_bist.d1f, 0xf, 0xffffffff); 3354 break; 3355 case 4: 3356 SPLIT_36BIT_DATA(sram_bist.d0r, 0x0, 0x00000000); 3357 SPLIT_36BIT_DATA(sram_bist.d0f, 0x0, 0x00000000); 3358 SPLIT_36BIT_DATA(sram_bist.d1r, 0x0, 0x00000000); 3359 SPLIT_36BIT_DATA(sram_bist.d1f, 0x0, 0x00000000); 3360 break; 3361 case 5: 3362 SPLIT_36BIT_DATA(sram_bist.d0r, 0xf, 0xffffffff); 3363 SPLIT_36BIT_DATA(sram_bist.d0f, 0xf, 0xffffffff); 3364 SPLIT_36BIT_DATA(sram_bist.d1r, 0xf, 0xffffffff); 3365 SPLIT_36BIT_DATA(sram_bist.d1f, 0xf, 0xffffffff); 3366 break; 3367 case 6: 3368 SPLIT_36BIT_DATA(sram_bist.d0r, 0xf, 0xfffc1020); 3369 SPLIT_36BIT_DATA(sram_bist.d0f, 0x0, 0x00000000); 3370 SPLIT_36BIT_DATA(sram_bist.d1r, 0xf, 0xfffc1020); 3371 SPLIT_36BIT_DATA(sram_bist.d1f, 0x0, 0x00000000); 3372 break; 3373 case 7: 3374 SPLIT_36BIT_DATA(sram_bist.d0r, 0x0, 0x00000000); 3375 SPLIT_36BIT_DATA(sram_bist.d0f, 0x0, 0x00000000); 3376 SPLIT_36BIT_DATA(sram_bist.d1r, 0x0, 0x00000000); 3377 SPLIT_36BIT_DATA(sram_bist.d1f, 0xf, 0xffffffff); 3378 break; 3379 case 8: 3380 SPLIT_36BIT_DATA(sram_bist.d0r, 0xf, 0xffffffff); 3381 SPLIT_36BIT_DATA(sram_bist.d0f, 0xf, 0xffffffff); 3382 SPLIT_36BIT_DATA(sram_bist.d1r, 0xf, 0xffffffff); 3383 SPLIT_36BIT_DATA(sram_bist.d1f, 0x0, 0x00000000); 3384 break; 3385 default: 3386 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3387 "Unknown SramDataChoice %d\n"), mt_data->sram_data_choice)); 3388 return SOC_E_PARAM; 3389 } 3390 #undef SPLIT_36BIT_DATA 3391 3392 switch (mt_data->alt_adr) { 3393 case 0: /* ADR0:0 ADR1:78, INC2 */ 3394 sram_bist.adr1 = 78; 3395 sram_bist.adr_mode = 2; 3396 break; 3397 case 1: /* ADR0:0 ADR1:0x3ffffe, ALT_A0A1 */ 3398 sram_bist.adr1 = 0x3ffffe; 3399 break; 3400 case 2: /* ADR0:0 ADR1:2, ALT_A0A1 */ 3401 sram_bist.adr1 = 2; 3402 break; 3403 case 3: /* ADR0:0x3ffffe ADR1:0, ALT_A0A1 */ 3404 sram_bist.adr0 = 0x3ffffe; 3405 break; 3406 default: 3407 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3408 "Unknown AltAdr %d\n"), mt_data->alt_adr)); 3409 return SOC_E_PARAM; 3410 } 3411 3412 sram_bist.wdoebr = -1; 3413 sram_bist.em_latency = -1; 3414 3415 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) { 3416 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3417 "SRAM setting:\n"))); 3418 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3419 " D0R:%05x-%05x D0F:%05x-%05x D1R:%05x-%05x " 3420 "D1F:%05x-%05x\n"), 3421 sram_bist.d0r_1, sram_bist.d0r_0, 3422 sram_bist.d0f_1, sram_bist.d0f_0, 3423 sram_bist.d1r_1, sram_bist.d1r_0, 3424 sram_bist.d1f_1, sram_bist.d1f_0)); 3425 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3426 " ADR0:%05x ADR1:%05x ADR_MODE:%d\n"), 3427 sram_bist.adr0, sram_bist.adr1, sram_bist.adr_mode)); 3428 } 3429 3430 if (mt_data->loop_mode[0] != 4) { 3431 reg = ES0_SRAM_CTLr; 3432 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 3433 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 3434 sram_bist.w2r_nops = 3435 soc_reg_field_get(mt_ctrl->unit, reg, rval, NUM_W2R_NOPSf); 3436 sram_bist.r2w_nops = 3437 soc_reg_field_get(mt_ctrl->unit, reg, rval, NUM_R2W_NOPSf); 3438 3439 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) { 3440 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3441 " (SRAM0) W2R_NOPS:%d R2W_NOPS:%d LOOP_MODE: %d\n"), 3442 sram_bist.w2r_nops, sram_bist.r2w_nops, 3443 mt_data->loop_mode[0])); 3444 } 3445 SOC_IF_ERROR_RETURN 3446 (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, 0, &sram_bist)); 3447 } 3448 3449 if (mt_data->loop_mode[1] != 4) { 3450 reg = ES1_SRAM_CTLr; 3451 addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0); 3452 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 3453 sram_bist.w2r_nops = 3454 soc_reg_field_get(mt_ctrl->unit, reg, rval, NUM_W2R_NOPSf); 3455 sram_bist.r2w_nops = 3456 soc_reg_field_get(mt_ctrl->unit, reg, rval, NUM_R2W_NOPSf); 3457 3458 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) { 3459 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3460 " (SRAM1) W2R_NOPS:%d R2W_NOPS:%d LOOP_MODE: %d\n"), 3461 sram_bist.w2r_nops, sram_bist.r2w_nops, 3462 mt_data->loop_mode[1])); 3463 } 3464 SOC_IF_ERROR_RETURN 3465 (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, 1, &sram_bist)); 3466 } 3467 3468 return SOC_E_NONE; 3469 } 3470 3471 STATIC int 3472 _soc_tr_memtune_lvl2_test(soc_memtune_data_t *mt_data, int *fail_count) 3473 { 3474 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 3475 tr_ext_sram_bist_t sram_bist[2], *sram_bist_ptr, *opt_sram_bist_ptr; 3476 int i, count, start, end, done; 3477 3478 if (mt_data->loop_mode[0] == 4) { 3479 start = end = 1; 3480 sram_bist_ptr = &sram_bist[1]; 3481 opt_sram_bist_ptr = NULL; 3482 } else if (mt_data->loop_mode[1] == 4) { 3483 start = end = 0; 3484 sram_bist_ptr = &sram_bist[0]; 3485 opt_sram_bist_ptr = NULL; 3486 } else { 3487 start = 0; 3488 end = 1; 3489 sram_bist_ptr = &sram_bist[0]; 3490 opt_sram_bist_ptr = &sram_bist[1]; 3491 } 3492 3493 for (i = start; i <= end; i++) { 3494 sal_memset(&sram_bist[i], 0, sizeof(tr_ext_sram_bist_t)); 3495 3496 /* 3497 * Following sram bist registers has been set properly, 3498 * don't touch them during test to save time: 3499 * D0R_0, D0R_1, D0F_0, D0F_1, D1R_0, D1R_1, D1F_0, D1F_1, 3500 * ADR0, ADR1, TMODE1 3501 */ 3502 sram_bist[i].d0r_0 = 0xffffffff; 3503 sram_bist[i].d1r_0 = 0xffffffff; 3504 sram_bist[i].adr0 = -1; 3505 sram_bist[i].adr1 = -1; 3506 sram_bist[i].wdoebr = -1; 3507 sram_bist[i].em_latency = -1; 3508 sram_bist[i].r2w_nops = -1; 3509 sram_bist[i].w2r_nops = -1; 3510 3511 sram_bist[i].bg_tcam_loop_count = mt_data->tcam_loop_count; 3512 } 3513 3514 for (count = 0; count < mt_data->test_count; count++) { 3515 for (i = start; i <= end; i++) { 3516 if (mt_data->loop_mode[i] == 1) /* RR */ { 3517 sram_bist[i].loop_mode = 0; /* WW */ 3518 SOC_IF_ERROR_RETURN 3519 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, i, TRUE, 3520 TRUE)); 3521 SOC_IF_ERROR_RETURN 3522 (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, i, 3523 &sram_bist[i])); 3524 SOC_IF_ERROR_RETURN 3525 (soc_triumph_ext_sram_op(mt_ctrl->unit, i, &sram_bist[i], 3526 NULL)); 3527 } 3528 sram_bist[i].loop_mode = mt_data->loop_mode[i]; 3529 SOC_IF_ERROR_RETURN 3530 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, i, TRUE, 3531 TRUE)); 3532 SOC_IF_ERROR_RETURN 3533 (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, i, 3534 &sram_bist[i])); 3535 } 3536 3537 SOC_IF_ERROR_RETURN 3538 (soc_triumph_ext_sram_op(mt_ctrl->unit, start, sram_bist_ptr, 3539 opt_sram_bist_ptr)); 3540 if (mt_data->ok_on_both_pass && start != end) { 3541 sram_bist[0].err_cnt += sram_bist[1].err_cnt; 3542 sram_bist[1].err_cnt = sram_bist[0].err_cnt; 3543 } 3544 3545 done = FALSE; 3546 for (i = start; i <= end; i++) { 3547 SOC_IF_ERROR_RETURN 3548 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, i, FALSE, 3549 FALSE)); 3550 if (sram_bist[i].err_cnt) { 3551 fail_count[i]++; 3552 if (fail_count[i] >= mt_data->max_fail_count) { 3553 done = TRUE; 3554 } 3555 } 3556 } 3557 if (done) { 3558 break; 3559 } 3560 } 3561 3562 return SOC_E_NONE; 3563 } 3564 3565 STATIC int 3566 _soc_tr_mem_interface_tune_lvl2(soc_memtune_data_t *mt_data) 3567 { 3568 soc_tcam_info_t *tcam_info; 3569 soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl; 3570 soc_tr_memtune_data_t *tr_mt_data; 3571 soc_memtune_result_t *result; 3572 int offset_count[2], index[2]; 3573 int tx_offset[2], tx_offset_cur[2], tx_offset_min[2], tx_offset_max[2]; 3574 int rx_offset[2], rx_offset_cur[2], rx_offset_min[2], rx_offset_max[2]; 3575 int em_latency[2], em_latency_cur[2], em_latency_min[2], em_latency_max[2]; 3576 int last_tx_offset[2], last_rx_offset[2]; 3577 int tx_pass_threshold[2], rx_pass_threshold[2]; 3578 int fail_count[2]; 3579 int has_fail[2]; 3580 int delta_max; 3581 static const struct { 3582 soc_reg_t tmode0; 3583 soc_reg_t config_reg1; 3584 } ddr_reg[2] = { 3585 { 3586 ES0_DTU_LTE_TMODE0r, 3587 ES0_DDR36_CONFIG_REG1_ISr 3588 }, 3589 { 3590 ES1_DTU_LTE_TMODE0r, 3591 ES1_DDR36_CONFIG_REG1_ISr 3592 }, 3593 }; 3594 int addr, dt, dr, i, start, end; 3595 uint32 rval; 3596 int sram_data_choice, alt_adr, loop_mode[2], tcam_loop_count, test_count; 3597 3598 if (mt_data->loop_mode[0] < 0 || mt_data->loop_mode[0] > 4) { 3599 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3600 "Unknown LoopMode %d\n"), mt_data->loop_mode[0])); 3601 return SOC_E_PARAM; 3602 } 3603 3604 if (mt_data->loop_mode[1] < 0 || mt_data->loop_mode[1] > 4) { 3605 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3606 "Unknown LoopMode %d\n"), mt_data->loop_mode[1])); 3607 return SOC_E_PARAM; 3608 } 3609 3610 start = 0; 3611 end = 1; 3612 if (mt_data->loop_mode[0] == 4) { 3613 if (mt_data->loop_mode[1] == 4) { 3614 return SOC_E_NONE; /* do nothing */ 3615 } else { 3616 start++; 3617 } 3618 } else if (mt_data->loop_mode[1] == 4) { 3619 end--; 3620 } 3621 3622 tcam_info = SOC_CONTROL(mt_ctrl->unit)->tcam_info; 3623 if (tcam_info == NULL) { 3624 return SOC_E_INIT; 3625 } 3626 3627 tr_mt_data = sal_alloc(sizeof(soc_tr_memtune_data_t), 3628 "memtune working data"); 3629 if (!tr_mt_data) { 3630 return SOC_E_MEMORY; 3631 } 3632 sal_memset(tr_mt_data, 0, sizeof(soc_tr_memtune_data_t)); 3633 mt_ctrl->data = tr_mt_data; 3634 3635 mt_data->interface = SOC_MEM_INTERFACE_SRAM; 3636 mt_data->sub_interface = 0; /* any legal value to allow setup to pass */ 3637 mt_data->man_em_latency = -1; 3638 mt_data->man_ddr_latency = -1; 3639 mt_data->man_tx_offset = -1; 3640 mt_data->man_rx_offset = -1; 3641 _soc_tr_mem_interface_tune_setup(mt_data); 3642 mt_ctrl->em_latency_cur = -1; 3643 mt_ctrl->ddr_latency_cur = -1; 3644 mt_ctrl->phase_sel_cur = -1; 3645 3646 em_latency_min[0] = em_latency_max[0] = -1; 3647 em_latency_min[1] = em_latency_max[1] = -1; 3648 has_fail[0] = has_fail[1] = FALSE; 3649 3650 for (i = start; i <= end; i++) { 3651 if (mt_data->tx_offset[i] != -1 || mt_data->rx_offset[i] != -1) { 3652 if (mt_data->tx_offset[i] < mt_ctrl->tx_offset_min || 3653 mt_data->tx_offset[i] > mt_ctrl->tx_offset_max || 3654 mt_data->rx_offset[i] < mt_ctrl->rx_offset_min || 3655 mt_data->rx_offset[i] > mt_ctrl->rx_offset_max) { 3656 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3657 "Invalid TX/RX value %d/%d\n"), 3658 mt_data->tx_offset[i], mt_data->rx_offset[i])); 3659 return SOC_E_PARAM; 3660 } 3661 tx_offset[i] = mt_data->tx_offset[i]; 3662 rx_offset[i] = mt_data->rx_offset[i]; 3663 } else { 3664 /* Get current TX/RX offset setting as center of sweep test */ 3665 addr = soc_reg_addr(mt_ctrl->unit, ddr_reg[i].config_reg1, 3666 REG_PORT_ANY, 0); 3667 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 3668 tx_offset[i] = 3669 soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].config_reg1, rval, 3670 DLL90_OFFSET_TXf) | 3671 (soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].config_reg1, rval, 3672 DLL90_OFFSET_TX4f) << 4); 3673 rx_offset[i] = 3674 soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].config_reg1, rval, 3675 DLL90_OFFSET_QKf) | 3676 (soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].config_reg1, rval, 3677 DLL90_OFFSET_QK4f) << 4); 3678 } 3679 3680 addr = soc_reg_addr(mt_ctrl->unit, ddr_reg[i].tmode0, REG_PORT_ANY, 0); 3681 SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval)); 3682 em_latency[i] = 3683 soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].tmode0, rval, 3684 EM_LATENCYf); 3685 if (soc_reg_field_valid(mt_ctrl->unit, ddr_reg[i].tmode0, 3686 EM_LATENCY8f) && 3687 soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].tmode0, rval, 3688 EM_LATENCY8f)) { 3689 em_latency[i] |= 8; 3690 } 3691 3692 /* Find out the min/max range of the sweeping window, the specified 3693 * delta may include TX/RX points beyond the physical range supported 3694 * by hardware */ 3695 tx_offset_min[i] = mt_ctrl->tx_offset_min; 3696 if (tx_offset[i] - mt_data->delta[i] >= tx_offset_min[i]) { 3697 tx_offset_min[i] = tx_offset[i] - mt_data->delta[i]; 3698 } 3699 tx_offset_max[i] = mt_ctrl->tx_offset_max; 3700 if (tx_offset[i] + mt_data->delta[i] <= tx_offset_max[i]) { 3701 tx_offset_max[i] = tx_offset[i] + mt_data->delta[i]; 3702 } 3703 rx_offset_min[i] = mt_ctrl->rx_offset_min; 3704 if (rx_offset[i] - mt_data->delta[i] >= rx_offset_min[i]) { 3705 rx_offset_min[i] = rx_offset[i] - mt_data->delta[i]; 3706 } 3707 rx_offset_max[i] = mt_ctrl->rx_offset_max; 3708 if (rx_offset[i] + mt_data->delta[i] <= rx_offset_max[i]) { 3709 rx_offset_max[i] = rx_offset[i] + mt_data->delta[i]; 3710 } 3711 offset_count[i] = (tx_offset_max[i] - tx_offset_min[i] + 1) * 3712 (rx_offset_max[i] - rx_offset_min[i] + 1); 3713 3714 if (mt_data->test_all_latency) { 3715 em_latency_min[i] = mt_ctrl->em_latency_min; 3716 em_latency_max[i] = mt_ctrl->em_latency_max; 3717 } 3718 3719 /* Set passing threshold if the sweeping window is larger than the 3720 * size of qualified window */ 3721 tx_pass_threshold[i] = mt_ctrl->tx_pass_threshold; 3722 if (tx_pass_threshold[i] > tx_offset_max[i] - tx_offset_min[i] + 1) { 3723 tx_pass_threshold[i] = 0; 3724 } 3725 rx_pass_threshold[i] = mt_ctrl->rx_pass_threshold; 3726 if (rx_pass_threshold[i] > rx_offset_max[i] - rx_offset_min[i] + 1) { 3727 rx_pass_threshold[i] = 0; 3728 } 3729 } 3730 3731 /* Setup TCAM BIST */ 3732 SOC_IF_ERROR_RETURN(_soc_tr_memtune_lvl2_tcam_bist_setup(mt_data)); 3733 3734 sram_data_choice = mt_data->sram_data_choice; 3735 alt_adr = mt_data->alt_adr; 3736 loop_mode[0] = mt_data->loop_mode[0]; 3737 loop_mode[1] = mt_data->loop_mode[1]; 3738 tcam_loop_count = mt_data->tcam_loop_count; 3739 test_count = mt_data->test_count; 3740 3741 last_tx_offset[0] = last_tx_offset[1] = -1; 3742 last_rx_offset[0] = last_rx_offset[1] = -1; 3743 delta_max = mt_data->delta[0] > mt_data->delta[1] ? 3744 mt_data->delta[0] : mt_data->delta[1]; 3745 for (dt = -delta_max; dt <= delta_max; dt++) { 3746 for (dr = -delta_max; dr <= delta_max; dr++) { 3747 for (i = start; i <= end; i++) { 3748 /* Find out the actual TX/RX setting for testing, this can be 3749 * different from the "intended" sweeping point 3750 * (center +/- delta). For example, if the point after moving 3751 * delta steps from center is out of supported min/max range, 3752 * the actual tx (or rx) setting for testing will be at the 3753 * valid window edge of that direction */ 3754 if (tx_offset[i] + dt < tx_offset_min[i]) { 3755 tx_offset_cur[i] = tx_offset_min[i]; 3756 } else if (tx_offset[i] + dt > tx_offset_max[i]) { 3757 tx_offset_cur[i] = tx_offset_max[i]; 3758 } else { 3759 tx_offset_cur[i] = tx_offset[i] + dt; 3760 } 3761 if (rx_offset[i] + dr < rx_offset_min[i]) { 3762 rx_offset_cur[i] = rx_offset_min[i]; 3763 } else if (rx_offset[i] + dr > rx_offset_max[i]) { 3764 rx_offset_cur[i] = rx_offset_max[i]; 3765 } else { 3766 rx_offset_cur[i] = rx_offset[i] + dr; 3767 } 3768 if (tx_offset[i] + dt != tx_offset_cur[i] || 3769 rx_offset[i] + dr != rx_offset_cur[i]) { 3770 /* Do not record result if the "intended" sweeping point 3771 * is not the actual TX/RX setting for testing */ 3772 index[i] = -1; 3773 } else { 3774 index[i] = (tx_offset_cur[i] - tx_offset_min[i]) * 3775 (rx_offset_max[i] - rx_offset_min[i] + 1) + 3776 rx_offset_cur[i] - rx_offset_min[i]; 3777 if (mt_data->fail_array[i][index[i]] > 0) { 3778 has_fail[i] = TRUE; 3779 if (mt_data->fail_array[i][index[i]] >= 3780 mt_data->max_fail_count) { 3781 /* Do not record result if the currently 3782 * accumulated error count has already exceeded 3783 * the specified max fail count */ 3784 index[i] = -1; 3785 } 3786 } 3787 } 3788 } 3789 3790 if (index[start] == -1 && index[end] == -1) { 3791 /* If none of the interface needs to record the result 3792 * go to next TX/RX */ 3793 continue; 3794 } 3795 3796 for (i = start; i <= end; i++) { 3797 em_latency_cur[i] = -1; 3798 /* If the TX/RX setting is the same as last test, no need to 3799 * reporgram TX/RX in hardware */ 3800 if (tx_offset_cur[i] == last_tx_offset[i] && 3801 rx_offset_cur[i] == last_rx_offset[i]) { 3802 continue; 3803 } 3804 mt_ctrl->tx_offset_cur = tx_offset_cur[i]; 3805 mt_ctrl->rx_offset_cur = rx_offset_cur[i]; 3806 tr_mt_data->config_reg1 = ddr_reg[i].config_reg1; 3807 (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */ 3808 if (tx_offset_cur[i] != last_tx_offset[i]) { 3809 if (*mt_ctrl->per_tx_fn != NULL) { 3810 (*mt_ctrl->per_tx_fn)(mt_data); 3811 } 3812 } 3813 if (rx_offset_cur[i] != last_rx_offset[i]) { 3814 if (*mt_ctrl->per_rx_fn != NULL) { 3815 (*mt_ctrl->per_rx_fn)(mt_data); 3816 } 3817 } 3818 last_tx_offset[i] = tx_offset_cur[i]; 3819 last_rx_offset[i] = rx_offset_cur[i]; 3820 3821 if (em_latency_min[i] == -1) { 3822 continue; 3823 } 3824 3825 /* Find EM_LATENCY for the TX/RX setting */ 3826 for (mt_ctrl->em_latency_cur = em_latency_min[i]; 3827 mt_ctrl->em_latency_cur <= em_latency_max[i]; 3828 mt_ctrl->em_latency_cur++) { 3829 tr_mt_data->tmode0 = ddr_reg[i].tmode0; 3830 (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */ 3831 mt_data->sram_data_choice = -1; 3832 mt_data->alt_adr = 2; 3833 mt_data->loop_mode[i] = 1; 3834 mt_data->loop_mode[i ^ 1] = 4; 3835 mt_data->tcam_loop_count = 1; 3836 mt_data->test_count = 1; 3837 SOC_IF_ERROR_RETURN 3838 (_soc_tr_memtune_lvl2_sram_bist_setup(mt_data)); 3839 3840 fail_count[i] = 0; 3841 _soc_tr_memtune_lvl2_test(mt_data, fail_count); 3842 3843 if (fail_count[i] == 0) { 3844 em_latency_cur[i] = mt_ctrl->em_latency_cur; 3845 break; 3846 } 3847 } 3848 } 3849 3850 /* Setup user-specified test parameters in hardware */ 3851 mt_data->sram_data_choice = sram_data_choice; 3852 mt_data->alt_adr = alt_adr; 3853 mt_data->loop_mode[0] = loop_mode[0]; 3854 mt_data->loop_mode[1] = loop_mode[1]; 3855 mt_data->tcam_loop_count = tcam_loop_count; 3856 mt_data->test_count = test_count; 3857 SOC_IF_ERROR_RETURN(_soc_tr_memtune_lvl2_sram_bist_setup(mt_data)); 3858 3859 /* Do user-specified test */ 3860 for (i = start; i <= end; i++) { 3861 fail_count[i] = 0; 3862 } 3863 _soc_tr_memtune_lvl2_test(mt_data, fail_count); 3864 3865 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL || 3866 mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_PASS) { 3867 for (i = start; i <= end; i++) { 3868 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3869 "SRAM%d TX=%d RX=%d "), i, 3870 tx_offset_cur[i], rx_offset_cur[i])); 3871 if (em_latency_cur[i] != -1) { 3872 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3873 "EM lat=%d "), em_latency_cur[i])); 3874 } 3875 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3876 ": Fail count=%d "), fail_count[i])); 3877 } 3878 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3879 "\n"))); 3880 } 3881 3882 for (i = start; i <= end; i++) { 3883 if (index[i] == -1) { 3884 continue; 3885 } 3886 if (mt_data->fail_array[i][index[i]] <= 0) { 3887 if (fail_count[i] == 0 && em_latency_cur[i] != -1) { 3888 mt_data->fail_array[i][index[i]] = -em_latency_cur[i]; 3889 } else { 3890 mt_data->fail_array[i][index[i]] = fail_count[i]; 3891 } 3892 } else { 3893 mt_data->fail_array[i][index[i]] += fail_count[i]; 3894 } 3895 if (fail_count[i] > 0) { 3896 has_fail[i] = TRUE; 3897 if (mt_data->fail_array[i][index[i]] > 3898 mt_data->max_fail_count) { 3899 mt_data->fail_array[i][index[i]] = 3900 mt_data->max_fail_count; 3901 } 3902 } 3903 } 3904 } 3905 } 3906 3907 /* Clear TCAM BIST setting */ 3908 rval = 0; 3909 soc_reg_field_set(mt_ctrl->unit, ETU_LTE_BIST_CTLr, &rval, LOOP_COUNTf, 1); 3910 (void)WRITE_ETU_LTE_BIST_CTLr(mt_ctrl->unit, rval); 3911 3912 for (i = start; i <= end; i++) { 3913 /* When sweeping only one SRAM, no analysis on the non-sweeping SRAM */ 3914 if (mt_data->delta[i] == 0 && mt_data->delta[i ^ 1] != 0) { 3915 continue; 3916 } 3917 mt_ctrl->tx_offset_cur = tx_offset[i]; 3918 mt_ctrl->rx_offset_cur = rx_offset[i]; 3919 mt_ctrl->intf_name = i == 0 ? "SRAM0" : "SRAM1"; 3920 mt_ctrl->result_count = 0; 3921 result = &mt_ctrl->result[mt_ctrl->result_count]; 3922 if (!has_fail[i]) { 3923 /* All tested TX/RX passes, no need to analyze */ 3924 mt_ctrl->tx_offset_cur = (tx_offset_min[i] + tx_offset_max[i]) / 2; 3925 mt_ctrl->rx_offset_cur = (rx_offset_min[i] + rx_offset_max[i]) / 2; 3926 result->fail_count = 0; 3927 result->width = rx_offset_max[i] - rx_offset_min[i] + 1; 3928 result->height = tx_offset_max[i] - tx_offset_min[i] + 1; 3929 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX) { 3930 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3931 "Memory tuning %s interface"), 3932 mt_ctrl->intf_name)); 3933 if (mt_ctrl->em_latency_cur != -1) { 3934 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3935 " em_latency=%d"), mt_ctrl->em_latency_cur)); 3936 } 3937 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3938 " failure count: all pass\n"))); 3939 } 3940 } else { 3941 /* Analyze and print result matrix */ 3942 mt_ctrl->tx_offset_min = tx_offset_min[i]; 3943 mt_ctrl->tx_offset_max = tx_offset_max[i]; 3944 mt_ctrl->rx_offset_min = rx_offset_min[i]; 3945 mt_ctrl->rx_offset_max = rx_offset_max[i]; 3946 mt_ctrl->fail_array = mt_data->fail_array[i]; 3947 _soc_memtune_txrx_analyze(mt_data); 3948 } 3949 3950 if (result->fail_count == offset_count[i] || 3951 mt_data->restore_txrx_after_test) { 3952 /* Test fail, or restore TX/RX flag is set */ 3953 mt_ctrl->tx_offset_cur = tx_offset[i]; 3954 mt_ctrl->rx_offset_cur = rx_offset[i]; 3955 } 3956 3957 /* Restore TX/RX in hardware */ 3958 tr_mt_data->config_reg1 = ddr_reg[i].config_reg1; 3959 (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */ 3960 if (*mt_ctrl->per_tx_fn != NULL) { 3961 (*mt_ctrl->per_tx_fn)(mt_data); 3962 } 3963 if (*mt_ctrl->per_rx_fn != NULL) { 3964 (*mt_ctrl->per_rx_fn)(mt_data); 3965 } 3966 3967 /* Find EM_LATENCY for the TX/RX setting */ 3968 if (em_latency_min[i] != -1) { 3969 for (em_latency_cur[i] = em_latency_min[i]; 3970 em_latency_cur[i] <= em_latency_max[i]; em_latency_cur[i]++) { 3971 mt_ctrl->em_latency_cur = em_latency_cur[i]; 3972 tr_mt_data->tmode0 = ddr_reg[i].tmode0; 3973 (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */ 3974 3975 mt_data->sram_data_choice = -1; 3976 mt_data->alt_adr = 2; 3977 mt_data->loop_mode[i] = 1; 3978 mt_data->loop_mode[i ^ 1] = 4; 3979 mt_data->tcam_loop_count = 1; 3980 mt_data->test_count = 1; 3981 SOC_IF_ERROR_RETURN 3982 (_soc_tr_memtune_lvl2_sram_bist_setup(mt_data)); 3983 3984 fail_count[i] = 0; 3985 _soc_tr_memtune_lvl2_test(mt_data, fail_count); 3986 if (fail_count[i] == 0) { 3987 break; 3988 } 3989 } 3990 } 3991 3992 if (result->fail_count == offset_count[i]) { 3993 LOG_CLI((BSL_META_U(mt_ctrl->unit, 3994 "ERROR - no passing \"eye\" was found, \n" 3995 "please contact your Field Applications " 3996 "Engineer or Sales Manager\n" 3997 "for additional assistance.\n"))); 3998 } else { 3999 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY) { 4000 LOG_CLI((BSL_META_U(mt_ctrl->unit, 4001 "%s OldTX=%d OldRX=%d "), 4002 mt_ctrl->intf_name, tx_offset[i], rx_offset[i])); 4003 if (em_latency_min[i] != -1) { 4004 LOG_CLI((BSL_META_U(mt_ctrl->unit, 4005 "OldEmLat=%d "), em_latency[i])); 4006 } 4007 LOG_CLI((BSL_META_U(mt_ctrl->unit, 4008 "NewTX=%d NewRX=%d "), 4009 mt_ctrl->tx_offset_cur, mt_ctrl->rx_offset_cur)); 4010 if (em_latency_min[i] != -1) { 4011 LOG_CLI((BSL_META_U(mt_ctrl->unit, 4012 "NewEmLat=%d "), mt_ctrl->em_latency_cur)); 4013 } 4014 LOG_CLI((BSL_META_U(mt_ctrl->unit, 4015 "Delta=%d "), mt_data->delta[i])); 4016 if (result->fail_count == 0) { 4017 LOG_CLI((BSL_META_U(mt_ctrl->unit, 4018 "no failure seen in tested points\n"))); 4019 } else { 4020 LOG_CLI((BSL_META_U(mt_ctrl->unit, 4021 "Area=%d Width=%d Height=%d\n"), 4022 result->width * result->height, 4023 result->width, result->height)); 4024 } 4025 } 4026 4027 if (result->fail_count > 0 && 4028 (result->height < tx_pass_threshold[i] || 4029 result->width < rx_pass_threshold[i])) { 4030 LOG_CLI((BSL_META_U(mt_ctrl->unit, 4031 "ERROR - \"eye\" of size %d * %d is smaller " 4032 "than minimum size of %d * %d,\n" 4033 "please contact your Field Applications " 4034 "Engineer or Sales Manager\n" 4035 "for additional assistance.\n"), 4036 result->height, result->width, 4037 mt_ctrl->tx_pass_threshold, 4038 mt_ctrl->rx_pass_threshold)); 4039 } 4040 4041 #ifndef NO_MEMTUNE 4042 if (mt_data->config) { 4043 char name_str[24], val_str[11]; 4044 sal_sprintf(name_str, "%s%d.%d", spn_EXT_SRAM_TUNING, i, 4045 mt_ctrl->unit); 4046 rval = soc_property_get(mt_ctrl->unit, name_str, 0); 4047 /* use 0 in the 3-bit field to represent EM_LATENCY is 8 */ 4048 if (em_latency_min[i] != -1) { 4049 rval &= ~(SOC_TR_MEMTUNE_EM_LATENCY_MASK << 4050 SOC_TR_MEMTUNE_EM_LATENCY_SHIFT); 4051 rval |= ((mt_ctrl->em_latency_cur & 4052 SOC_TR_MEMTUNE_EM_LATENCY_MASK) << 4053 SOC_TR_MEMTUNE_EM_LATENCY_SHIFT); 4054 } 4055 rval &= ~(SOC_TR_MEMTUNE_DDR_TX_OFFSET_MASK << 4056 SOC_TR_MEMTUNE_DDR_TX_OFFSET_SHIFT); 4057 rval |= ((mt_ctrl->tx_offset_cur & 4058 SOC_TR_MEMTUNE_DDR_TX_OFFSET_MASK) << 4059 SOC_TR_MEMTUNE_DDR_TX_OFFSET_SHIFT); 4060 rval &= ~(SOC_TR_MEMTUNE_DDR_RX_OFFSET_MASK << 4061 SOC_TR_MEMTUNE_DDR_RX_OFFSET_SHIFT); 4062 rval |= ((mt_ctrl->rx_offset_cur & 4063 SOC_TR_MEMTUNE_DDR_RX_OFFSET_MASK) << 4064 SOC_TR_MEMTUNE_DDR_RX_OFFSET_SHIFT); 4065 sal_sprintf(val_str, "0x%08x", rval); 4066 if (_mem_config_set(name_str, val_str) < 0) { 4067 return SOC_E_MEMORY; 4068 } 4069 sal_sprintf(name_str, "%s%d.%d", spn_EXT_SRAM_TUNING2_STATS, i, 4070 mt_ctrl->unit); 4071 rval = SOC_TR_MEMTUNE_CONFIG_VALID_MASK | 4072 ((result->width & SOC_TR_MEMTUNE_STATS_WIDTH_MASK) << 4073 SOC_TR_MEMTUNE_STATS_WIDTH_SHIFT) | 4074 ((result->height & SOC_TR_MEMTUNE_STATS_HEIGHT_MASK) << 4075 SOC_TR_MEMTUNE_STATS_HEIGHT_SHIFT) | 4076 ((result->fail_count & 4077 SOC_TR_MEMTUNE_STATS_FAIL_MASK) << 4078 SOC_TR_MEMTUNE_STATS_FAIL_SHIFT); 4079 sal_sprintf(val_str, "0x%08x", rval); 4080 if (_mem_config_set(name_str, val_str) < 0) { 4081 return SOC_E_MEMORY; 4082 } 4083 } 4084 #endif /* NO_MEMTUNE */ 4085 } 4086 } 4087 4088 mt_data->sram_data_choice = sram_data_choice; 4089 mt_data->alt_adr = alt_adr; 4090 mt_data->loop_mode[0] = loop_mode[0]; 4091 mt_data->loop_mode[1] = loop_mode[1]; 4092 mt_data->tcam_loop_count = tcam_loop_count; 4093 mt_data->test_count = test_count; 4094 4095 return SOC_E_NONE; 4096 } 4097 #endif /* BCM_TRIUMPH_SUPPORT */ 4098 4099 int 4100 soc_mem_interface_tune_lvl2(int unit, soc_memtune_data_t *mt_data) 4101 { 4102 soc_memtune_ctrl_t *mt_ctrl; 4103 int rv = SOC_E_NONE; 4104 4105 mt_ctrl = sal_alloc(sizeof(soc_memtune_ctrl_t), "memtune working data"); 4106 if (!mt_ctrl) { 4107 return SOC_E_MEMORY; 4108 } 4109 sal_memset(mt_ctrl, 0, sizeof(soc_memtune_ctrl_t)); 4110 mt_ctrl->unit = unit; 4111 mt_data->mt_ctrl = mt_ctrl; 4112 4113 if (mt_data->verbose) { 4114 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_TEST_NAME | 4115 SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY | 4116 SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX | 4117 SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS | 4118 SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL | 4119 SOC_MEMTUNE_CTRL_FLAGS_SHOW_PASS | 4120 SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING; 4121 } 4122 if (mt_data->summary) { 4123 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY; 4124 } 4125 if (mt_data->show_setting) { 4126 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING; 4127 } 4128 if (mt_data->show_matrix) { 4129 mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX | 4130 SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS; 4131 } 4132 4133 #ifdef BCM_TRIUMPH_SUPPORT 4134 if (soc_feature(unit, soc_feature_esm_support)) { 4135 rv = _soc_tr_mem_interface_tune_lvl2(mt_data); 4136 } 4137 #endif /* BCM_TRIUMPH_SUPPORT */ 4138 4139 if (mt_ctrl->data) { 4140 sal_free(mt_ctrl->data); 4141 } 4142 sal_free(mt_ctrl); 4143 4144 return rv; 4145 } 4146 #endif /* BCM_TRIUMPH_SUPPORT */