falcon_diagnostics.c (32544B)
1 2 /* 3 * 4 * 5 * 6 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 7 * 8 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 9 */ 10 11 #include <phymod/phymod.h> 12 #include <phymod/phymod_system.h> 13 #include <phymod/phymod_util.h> 14 #include <phymod/phymod_config.h> 15 #include <phymod/phymod_diagnostics.h> 16 #include <phymod/phymod_diagnostics_dispatch.h> 17 18 #include "../../tscf/tier1/tefmod_enum_defines.h" 19 #include "../../falcon/tier1/falcon_cfg_seq.h" 20 #include "../../falcon/tier1/falcon_tsc_enum.h" 21 #include "../../falcon/tier1/falcon_tsc_common.h" 22 #include "../../falcon/tier1/falcon_tsc_interface.h" 23 #include "../../falcon/tier1/falcon_tsc_dependencies.h" 24 #include "../../falcon/tier1/falcon_tsc_debug_functions.h" 25 26 27 #define PATTERN_MAX_LENGTH 240 28 #ifdef PHYMOD_FALCON_SUPPORT 29 30 31 /*phymod, internal enum mappings*/ 32 STATIC 33 int _falcon_prbs_poly_phymod_to_falcon(phymod_prbs_poly_t phymod_poly, enum srds_prbs_polynomial_enum *falcon_poly) 34 { 35 switch(phymod_poly){ 36 case phymodPrbsPoly7: 37 *falcon_poly = PRBS_7; 38 break; 39 case phymodPrbsPoly9: 40 *falcon_poly = PRBS_9; 41 break; 42 case phymodPrbsPoly11: 43 *falcon_poly = PRBS_11; 44 break; 45 case phymodPrbsPoly15: 46 *falcon_poly = PRBS_15; 47 break; 48 case phymodPrbsPoly23: 49 *falcon_poly = PRBS_23; 50 break; 51 case phymodPrbsPoly31: 52 *falcon_poly = PRBS_31; 53 break; 54 case phymodPrbsPoly58: 55 *falcon_poly = PRBS_58; 56 break; 57 default: 58 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, (_PHYMOD_MSG("unsupported poly for tscf %u"), phymod_poly)); 59 } 60 return PHYMOD_E_NONE; 61 } 62 63 STATIC 64 int _falcon_prbs_poly_tscf_to_phymod(falcon_prbs_polynomial_type_t tscf_poly, phymod_prbs_poly_t *phymod_poly) 65 { 66 switch(tscf_poly){ 67 case FALCON_PRBS_POLYNOMIAL_7: 68 *phymod_poly = phymodPrbsPoly7; 69 break; 70 case FALCON_PRBS_POLYNOMIAL_9: 71 *phymod_poly = phymodPrbsPoly9; 72 break; 73 case FALCON_PRBS_POLYNOMIAL_11: 74 *phymod_poly = phymodPrbsPoly11; 75 break; 76 case FALCON_PRBS_POLYNOMIAL_15: 77 *phymod_poly = phymodPrbsPoly15; 78 break; 79 case FALCON_PRBS_POLYNOMIAL_23: 80 *phymod_poly = phymodPrbsPoly23; 81 break; 82 case FALCON_PRBS_POLYNOMIAL_31: 83 *phymod_poly = phymodPrbsPoly31; 84 break; 85 case FALCON_PRBS_POLYNOMIAL_58: 86 *phymod_poly = phymodPrbsPoly58; 87 break; 88 default: 89 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("uknown poly %u"), tscf_poly)); 90 } 91 return PHYMOD_E_NONE; 92 } 93 94 int falcon_phy_rx_slicer_position_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_slicer_position_t* position) 95 { 96 97 98 /* Not supported */ 99 PHYMOD_DEBUG_ERROR(("falcon_phy_rx_slicer_position_set function is NOT SUPPORTED!!\n")); 100 101 102 return PHYMOD_E_NONE; 103 104 } 105 106 int falcon_phy_rx_slicer_position_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_slicer_position_t* position) 107 { 108 109 110 /* Not supported */ 111 PHYMOD_DEBUG_ERROR(("falcon_phy_rx_slicer_position_get function is NOT SUPPORTED!!\n")); 112 113 114 return PHYMOD_E_NONE; 115 116 } 117 118 119 int falcon_phy_rx_slicer_position_max_get(const phymod_phy_access_t* phy, uint32_t flags, const phymod_slicer_position_t* position_min, const phymod_slicer_position_t* position_max) 120 { 121 122 123 /* Not supported */ 124 PHYMOD_DEBUG_ERROR(("falcon_phy_rx_slicer_position_max_get function is NOT SUPPORTED!!\n")); 125 126 127 return PHYMOD_E_NONE; 128 129 } 130 131 132 int falcon_phy_prbs_config_set(const phymod_phy_access_t* phy, uint32_t flags , const phymod_prbs_t* prbs) 133 { 134 enum srds_prbs_polynomial_enum falcon_poly; 135 phymod_phy_access_t phy_copy; 136 int start_lane, num_lane, i; 137 138 PHYMOD_IF_ERR_RETURN 139 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 140 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 141 142 PHYMOD_IF_ERR_RETURN(_falcon_prbs_poly_phymod_to_falcon(prbs->poly, &falcon_poly)); 143 /*first check which direction */ 144 for (i = 0; i < num_lane; i++) { 145 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 146 continue; 147 } 148 phy_copy.access.lane_mask = 1 << (start_lane + i); 149 if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 150 PHYMOD_IF_ERR_RETURN 151 (falcon_tsc_config_rx_prbs(&phy_copy.access, falcon_poly, PRBS_INITIAL_SEED_HYSTERESIS, prbs->invert)); 152 } else if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 153 PHYMOD_IF_ERR_RETURN 154 (falcon_tsc_config_tx_prbs(&phy_copy.access, falcon_poly, prbs->invert)); 155 } else { 156 PHYMOD_IF_ERR_RETURN 157 (falcon_tsc_config_rx_prbs(&phy_copy.access, falcon_poly, PRBS_INITIAL_SEED_HYSTERESIS, prbs->invert)); 158 PHYMOD_IF_ERR_RETURN 159 (falcon_tsc_config_tx_prbs(&phy_copy.access, falcon_poly, prbs->invert)); 160 } 161 } 162 return PHYMOD_E_NONE; 163 } 164 165 int falcon_phy_prbs_config_get(const phymod_phy_access_t* phy, uint32_t flags , phymod_prbs_t* prbs) 166 { 167 phymod_prbs_t config_tmp; 168 falcon_prbs_polynomial_type_t tscf_poly; 169 170 if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 171 PHYMOD_IF_ERR_RETURN(falcon_prbs_tx_inv_data_get(&phy->access, &config_tmp.invert)); 172 PHYMOD_IF_ERR_RETURN(falcon_prbs_tx_poly_get(&phy->access, &tscf_poly)); 173 PHYMOD_IF_ERR_RETURN(_falcon_prbs_poly_tscf_to_phymod(tscf_poly, &config_tmp.poly)); 174 prbs->invert = config_tmp.invert; 175 prbs->poly = config_tmp.poly; 176 } else if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 177 PHYMOD_IF_ERR_RETURN(falcon_prbs_rx_inv_data_get(&phy->access, &config_tmp.invert)); 178 PHYMOD_IF_ERR_RETURN(falcon_prbs_rx_poly_get(&phy->access, &tscf_poly)); 179 PHYMOD_IF_ERR_RETURN(_falcon_prbs_poly_tscf_to_phymod(tscf_poly, &config_tmp.poly)); 180 prbs->invert = config_tmp.invert; 181 prbs->poly = config_tmp.poly; 182 } else { 183 PHYMOD_IF_ERR_RETURN(falcon_prbs_tx_inv_data_get(&phy->access, &config_tmp.invert)); 184 PHYMOD_IF_ERR_RETURN(falcon_prbs_tx_poly_get(&phy->access, &tscf_poly)); 185 PHYMOD_IF_ERR_RETURN(_falcon_prbs_poly_tscf_to_phymod(tscf_poly, &config_tmp.poly)); 186 prbs->invert = config_tmp.invert; 187 prbs->poly = config_tmp.poly; 188 } 189 return PHYMOD_E_NONE; 190 } 191 192 193 int falcon_phy_prbs_enable_set(const phymod_phy_access_t* phy, uint32_t flags , uint32_t enable) 194 { 195 phymod_phy_access_t phy_copy; 196 int start_lane, num_lane, i; 197 198 PHYMOD_IF_ERR_RETURN 199 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 200 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 201 202 /*first check which direction */ 203 for (i = 0; i < num_lane; i++) { 204 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 205 continue; 206 } 207 phy_copy.access.lane_mask = 1 << (start_lane + i); 208 if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 209 PHYMOD_IF_ERR_RETURN(falcon_tsc_tx_prbs_en(&phy_copy.access, enable)); 210 } else if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 211 PHYMOD_IF_ERR_RETURN(falcon_tsc_rx_prbs_en(&phy_copy.access, enable)); 212 } else { 213 PHYMOD_IF_ERR_RETURN(falcon_tsc_tx_prbs_en(&phy_copy.access, enable)); 214 PHYMOD_IF_ERR_RETURN(falcon_tsc_rx_prbs_en(&phy_copy.access, enable)); 215 } 216 } 217 return PHYMOD_E_NONE; 218 } 219 220 int falcon_phy_prbs_enable_get(const phymod_phy_access_t* phy, uint32_t flags , uint32_t* enable) 221 { 222 uint32_t enable_tmp; 223 if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 224 PHYMOD_IF_ERR_RETURN(falcon_prbs_tx_enable_get(&phy->access, &enable_tmp)); 225 *enable = enable_tmp; 226 } else if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 227 PHYMOD_IF_ERR_RETURN(falcon_prbs_rx_enable_get(&phy->access, &enable_tmp)); 228 *enable = enable_tmp; 229 } else { 230 PHYMOD_IF_ERR_RETURN(falcon_prbs_tx_enable_get(&phy->access, &enable_tmp)); 231 *enable = enable_tmp; 232 PHYMOD_IF_ERR_RETURN(falcon_prbs_rx_enable_get(&phy->access, &enable_tmp)); 233 *enable &= enable_tmp; 234 } 235 236 return PHYMOD_E_NONE; 237 238 } 239 240 241 int falcon_phy_prbs_status_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_prbs_status_t* prbs_status) 242 { 243 uint8_t status = 0; 244 uint32_t prbs_err_count = 0; 245 246 PHYMOD_IF_ERR_RETURN(falcon_tsc_prbs_chk_lock_state(&phy->access, &status)); 247 if (status) { 248 prbs_status->prbs_lock = 1; 249 /*next check the lost of lock and error count */ 250 status = 0; 251 PHYMOD_IF_ERR_RETURN 252 (falcon_tsc_prbs_err_count_state(&phy->access, &prbs_err_count, &status)); 253 if (status) { 254 /*temp lost of lock */ 255 prbs_status->prbs_lock_loss = 1; 256 } else { 257 prbs_status->prbs_lock_loss = 0; 258 prbs_status->error_count = prbs_err_count; 259 } 260 } else { 261 prbs_status->prbs_lock = 0; 262 } 263 264 return PHYMOD_E_NONE; 265 266 } 267 268 269 int falcon_phy_pattern_config_set(const phymod_phy_access_t* phy, const phymod_pattern_t* pattern) 270 { 271 int i,j = 0, bit; 272 char patt[PATTERN_MAX_LENGTH+1]; 273 for (i=0; i< PATTERN_MAX_SIZE; i++) 274 { 275 for (j=0;j<32 && i*32+j <= PATTERN_MAX_LENGTH; j++) 276 { 277 if (i*32+j == pattern->pattern_len) { 278 break; 279 } 280 bit = pattern->pattern[i] >> j & 00000001; 281 switch (bit) { 282 case (1): 283 patt[i*32+j] = '1'; 284 break; 285 default: 286 patt[i*32+j] = '0'; 287 break; 288 } 289 } 290 if (i*32+j == pattern->pattern_len && i*32+j <= PATTERN_MAX_LENGTH) { 291 /* coverity[overrun-local] */ 292 patt[i*32+j] = '\0'; 293 break; 294 } 295 } 296 PHYMOD_IF_ERR_RETURN 297 (falcon_tsc_config_shared_tx_pattern_idx_set(&phy->access, 298 &pattern->pattern_len )); 299 PHYMOD_IF_ERR_RETURN 300 (falcon_tsc_config_shared_tx_pattern (&phy->access, 301 (uint8_t) pattern->pattern_len, (const char *) patt)); 302 303 return PHYMOD_E_NONE; 304 305 } 306 307 int falcon_phy_pattern_config_get(const phymod_phy_access_t* phy, phymod_pattern_t* pattern) 308 { 309 310 PHYMOD_IF_ERR_RETURN 311 (falcon_tsc_config_shared_tx_pattern_idx_get(&phy->access, 312 &pattern->pattern_len, 313 pattern->pattern)); 314 315 return PHYMOD_E_NONE; 316 317 } 318 319 320 int falcon_phy_pattern_enable_set(const phymod_phy_access_t* phy, uint32_t enable, phymod_pattern_t* pattern) 321 { 322 PHYMOD_IF_ERR_RETURN 323 (falcon_tsc_tx_shared_patt_gen_en(&phy->access, (uint8_t) enable, (uint8_t)pattern->pattern_len)); 324 return PHYMOD_E_NONE; 325 326 } 327 328 int falcon_phy_pattern_enable_get(const phymod_phy_access_t* phy, uint32_t* enable) 329 { 330 uint8_t enable_8; 331 PHYMOD_IF_ERR_RETURN 332 (falcon_tsc_tx_shared_patt_gen_en_get(&phy->access, &enable_8)); 333 *enable = (uint32_t) enable_8; 334 return PHYMOD_E_NONE; 335 336 } 337 338 339 int falcon_core_diagnostics_get(const phymod_core_access_t* core, phymod_core_diagnostics_t* diag) 340 { 341 int16_t temperature; 342 343 falcon_tsc_read_die_temperature(&core->access, &temperature); 344 diag->temperature = temperature; 345 346 falcon_tsc_read_pll_range(&core->access, &diag->pll_range); 347 348 return PHYMOD_E_NONE; 349 } 350 351 352 int falcon_phy_diagnostics_get(const phymod_phy_access_t* phy, phymod_phy_diagnostics_t* diag) 353 { 354 355 unsigned char rx_lock; 356 int osr_mode; 357 phymod_diag_eyescan_t_init(&diag->eyescan); 358 phymod_diag_slicer_offset_t_init(&diag->slicer_offset); 359 360 PHYMOD_IF_ERR_RETURN(falcon_tsc_pmd_lock_status(&phy->access, &rx_lock)); 361 diag->rx_lock = (uint32_t ) rx_lock; 362 PHYMOD_IF_ERR_RETURN(falcon_osr_mode_get(&phy->access, &osr_mode)); 363 switch(osr_mode) { 364 case 0: diag->osr_mode = phymodOversampleMode1; break; 365 case 1: diag->osr_mode = phymodOversampleMode2; break; 366 case 2: diag->osr_mode = phymodOversampleMode4; break; 367 case 5: diag->osr_mode = phymodOversampleMode8; break; 368 case 8: diag->osr_mode = phymodOversampleMode16P5; break; 369 case 12: diag->osr_mode = phymodOversampleMode20P625; break; 370 default: 371 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("unsupported OS mode %d"), osr_mode)); 372 } 373 PHYMOD_IF_ERR_RETURN(falcon_tsc_signal_detect(&phy->access, &diag->signal_detect)); 374 375 return PHYMOD_E_NONE; 376 } 377 378 int falcon_phy_pmd_info_dump(const phymod_phy_access_t* phy, const char* type) 379 { 380 int start_lane, num_lane; 381 int tmp_lane_mask; 382 phymod_phy_access_t phy_copy; 383 struct falcon_tsc_detailed_lane_status_st lane_st[4]; 384 int i = 0; 385 int j = 0; 386 387 uint32_t cmd_type; 388 389 uint8_t trace_mem[768]; 390 391 if (!type) { 392 cmd_type = (uint32_t)TEFMOD_DIAG_DSC; 393 } else if ((!PHYMOD_STRCMP(type, "ber")) || 394 (!PHYMOD_STRCMP(type, "Ber")) || 395 (!PHYMOD_STRCMP(type, "BER"))) { 396 cmd_type = (uint32_t)TEFMOD_DIAG_BER; 397 } else if ((!PHYMOD_STRCMP(type, "config")) || 398 (!PHYMOD_STRCMP(type, "Config")) || 399 (!PHYMOD_STRCMP(type, "CONFIG"))) { 400 cmd_type = (uint32_t)TEFMOD_DIAG_CFG; 401 } else if ((!PHYMOD_STRCMP(type, "cl72")) || 402 (!PHYMOD_STRCMP(type, "Cl72")) || 403 (!PHYMOD_STRCMP(type, "CL72"))) { 404 cmd_type = (uint32_t)TEFMOD_DIAG_CL72; 405 } else if ((!PHYMOD_STRCMP(type, "debug")) || 406 (!PHYMOD_STRCMP(type, "Debug")) || 407 (!PHYMOD_STRCMP(type, "DEBUG"))) { 408 cmd_type = (uint32_t)TEFMOD_DIAG_DEBUG; 409 } else if ((!PHYMOD_STRCMP(type, "state")) || 410 (!PHYMOD_STRCMP(type, "State")) || 411 (!PHYMOD_STRCMP(type, "STATE"))) { 412 cmd_type = (uint32_t)TEFMOD_DIAG_STATE; 413 } else if ((!PHYMOD_STRCMP(type, "verbose")) || 414 (!PHYMOD_STRCMP(type, "Verbose")) || 415 (!PHYMOD_STRCMP(type, "VERBOSE"))) { 416 cmd_type = (uint32_t)TEFMOD_DIAG_ALL; 417 } else if (!PHYMOD_STRCMP(type, "STD")) { 418 cmd_type = (uint32_t)TEFMOD_DIAG_DSC_STD; 419 } else { 420 cmd_type = (uint32_t)TEFMOD_DIAG_STATE; 421 } 422 423 PHYMOD_DEBUG_ERROR((" %s:%d type = %d laneMask = 0x%X\n", __func__, __LINE__, cmd_type, phy->access.lane_mask)); 424 425 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 426 427 /*next figure out the lane num and start_lane based on the input*/ 428 PHYMOD_IF_ERR_RETURN 429 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 430 431 if (cmd_type == TEFMOD_DIAG_DSC) { 432 PHYMOD_IF_ERR_RETURN 433 (falcon_tsc_display_core_state(&phy_copy.access)); 434 PHYMOD_IF_ERR_RETURN 435 (falcon_tsc_display_lane_state_hdr(&phy_copy.access)); 436 for (i = 0; i < 4; i++) { 437 phy_copy.access.lane_mask = 0x1 << i ; 438 PHYMOD_IF_ERR_RETURN 439 (falcon_tsc_display_lane_state(&phy_copy.access)); 440 } 441 } else if (cmd_type == TEFMOD_DIAG_DSC_STD) { 442 443 PHYMOD_DIAG_OUT((" +--------------------------------------------------------------------+\n")); 444 PHYMOD_DIAG_OUT((" | DSC Phy: 0x%03x lane_mask: 0x%02x |\n", phy->access.addr, phy->access.lane_mask)); 445 PHYMOD_DIAG_OUT((" +--------------------------------------------------------------------+\n")); 446 PHYMOD_IF_ERR_RETURN 447 (falcon_tsc_display_core_state(&phy_copy.access)); 448 PHYMOD_IF_ERR_RETURN 449 (falcon_tsc_display_lane_state_hdr(&phy_copy.access)); 450 PHYMOD_IF_ERR_RETURN 451 (falcon_tsc_display_lane_state(&phy_copy.access)); 452 tmp_lane_mask = phy_copy.access.lane_mask; 453 for (j = 0; j < 4; j++) { 454 phy_copy.access.lane_mask = 0x1 << j; 455 PHYMOD_IF_ERR_RETURN 456 (falcon_tsc_log_full_pmd_state(&phy_copy.access, &lane_st[j])); 457 } 458 phy_copy.access.lane_mask = tmp_lane_mask; 459 PHYMOD_IF_ERR_RETURN 460 (falcon_tsc_disp_full_pmd_state(&phy_copy.access, lane_st, 4)); 461 PHYMOD_IF_ERR_RETURN 462 (falcon_tsc_read_event_log((&phy_copy.access), trace_mem, 2)); 463 464 } else { 465 for (i = 0; i < num_lane; i++) { 466 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 467 468 switch (cmd_type) { 469 case TEFMOD_DIAG_CFG: 470 PHYMOD_DEBUG_ERROR((" %s:%d type = CFG\n", __func__, __LINE__)); 471 if(i==0) { 472 tmp_lane_mask = phy_copy.access.lane_mask; 473 phy_copy.access.lane_mask = 1; 474 PHYMOD_IF_ERR_RETURN 475 (falcon_tsc_display_core_config(&phy_copy.access)); 476 phy_copy.access.lane_mask = tmp_lane_mask; 477 } 478 PHYMOD_IF_ERR_RETURN 479 (falcon_tsc_display_lane_config(&phy_copy.access)); 480 break; 481 482 case TEFMOD_DIAG_CL72: 483 PHYMOD_DEBUG_ERROR((" %s:%d type = CL72\n", __func__, __LINE__)); 484 PHYMOD_IF_ERR_RETURN 485 (falcon_tsc_display_cl93n72_status(&phy_copy.access)); 486 break; 487 488 case TEFMOD_DIAG_DEBUG: 489 PHYMOD_DEBUG_ERROR((" %s:%d type = DBG\n", __func__, __LINE__)); 490 PHYMOD_IF_ERR_RETURN 491 (falcon_tsc_display_lane_debug_status(&phy_copy.access)); 492 break; 493 494 case TEFMOD_DIAG_BER: 495 PHYMOD_DEBUG_ERROR((" %s:%d type = BER\n", __func__, __LINE__)); 496 break; 497 498 /* 499 * COVERITY 500 * 501 * TEFMOD_DIAG_ALL branch involve information in TEFMOD_DIAG_STATE branch 502 */ 503 /* coverity[unterminated_case] */ 504 case TEFMOD_DIAG_ALL: 505 PHYMOD_DEBUG_ERROR((" %s:%d type = CFG\n", __func__, __LINE__)); 506 if(i==0) { 507 tmp_lane_mask = phy_copy.access.lane_mask; 508 phy_copy.access.lane_mask = 1; 509 PHYMOD_IF_ERR_RETURN 510 (falcon_tsc_display_core_config(&phy_copy.access)); 511 phy_copy.access.lane_mask = tmp_lane_mask; 512 } 513 PHYMOD_IF_ERR_RETURN 514 (falcon_tsc_display_lane_config(&phy_copy.access)); 515 516 PHYMOD_DEBUG_ERROR((" %s:%d type = CL72\n", __func__, __LINE__)); 517 PHYMOD_IF_ERR_RETURN 518 (falcon_tsc_display_cl93n72_status(&phy_copy.access)); 519 520 PHYMOD_DEBUG_ERROR((" %s:%d type = DBG\n", __func__, __LINE__)); 521 PHYMOD_IF_ERR_RETURN 522 (falcon_tsc_display_lane_debug_status(&phy_copy.access)); 523 524 case TEFMOD_DIAG_STATE: 525 default: 526 PHYMOD_DEBUG_ERROR((" %s:%d type = DEF\n", __func__, __LINE__)); 527 PHYMOD_IF_ERR_RETURN 528 (falcon_tsc_display_core_state(&phy_copy.access)); 529 PHYMOD_IF_ERR_RETURN 530 (falcon_tsc_display_lane_state_hdr(&phy_copy.access)); 531 PHYMOD_IF_ERR_RETURN 532 (falcon_tsc_display_lane_state(&phy_copy.access)); 533 tmp_lane_mask = phy_copy.access.lane_mask; 534 for (j = 0; j < 4; j++) { 535 phy_copy.access.lane_mask = 0x1 << j; 536 PHYMOD_IF_ERR_RETURN 537 (falcon_tsc_log_full_pmd_state(&phy_copy.access, &lane_st[j])); 538 } 539 phy_copy.access.lane_mask = tmp_lane_mask; 540 PHYMOD_IF_ERR_RETURN 541 (falcon_tsc_disp_full_pmd_state(&phy_copy.access, lane_st, 4)); 542 PHYMOD_IF_ERR_RETURN 543 (falcon_tsc_read_event_log((&phy_copy.access), trace_mem, 2)); 544 break; 545 } 546 } 547 } 548 return PHYMOD_E_NONE; 549 } 550 551 STATIC err_code_t falcon_phy_meas_lowber_eye (const phymod_access_t *pa, 552 const phymod_phy_eyescan_options_t* eyescan_options, 553 uint32_t *buffer) 554 { 555 struct falcon_tsc_eyescan_options_st e_options; 556 557 e_options.linerate_in_khz = eyescan_options->linerate_in_khz; 558 e_options.timeout_in_milliseconds = eyescan_options->timeout_in_milliseconds; 559 e_options.horz_max = eyescan_options->horz_max; 560 e_options.horz_min = eyescan_options->horz_min; 561 e_options.hstep = eyescan_options->hstep; 562 e_options.vert_max = eyescan_options->vert_max; 563 e_options.vert_min = eyescan_options->vert_min; 564 e_options.vstep = eyescan_options->vstep; 565 e_options.mode = eyescan_options->mode; 566 567 return (falcon_tsc_meas_lowber_eye(pa, e_options, buffer)); 568 } 569 570 STATIC err_code_t falcon_phy_display_lowber_eye (const phymod_access_t *pa, 571 const phymod_phy_eyescan_options_t* eyescan_options, 572 uint32_t *buffer) 573 { 574 struct falcon_tsc_eyescan_options_st e_options; 575 576 e_options.linerate_in_khz = eyescan_options->linerate_in_khz; 577 e_options.timeout_in_milliseconds = eyescan_options->timeout_in_milliseconds; 578 e_options.horz_max = eyescan_options->horz_max; 579 e_options.horz_min = eyescan_options->horz_min; 580 e_options.hstep = eyescan_options->hstep; 581 e_options.vert_max = eyescan_options->vert_max*2; 582 e_options.vert_min = eyescan_options->vert_min*2; 583 e_options.vstep = eyescan_options->vstep*2; 584 e_options.mode = eyescan_options->mode; 585 586 return(falcon_tsc_display_lowber_eye (pa, e_options, buffer)); 587 } 588 589 static void _falcon_diag_uc_reg_dump(const phymod_access_t *pa) 590 { 591 err_code_t errc; 592 593 COMPILER_REFERENCE(errc); 594 595 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 596 PHYMOD_DIAG_OUT(("| MICRO CODE USR CTRL CONFIGURATION REGISTERS |\n")); 597 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 598 PHYMOD_DIAG_OUT(("| config_word [0x00]: 0x%04X |\n", falcon_tsc_rdwl_uc_var(pa,&errc,0x0))); 599 PHYMOD_DIAG_OUT(("| retune_after_restart [0x02]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x2))); 600 PHYMOD_DIAG_OUT(("| clk90_offset_adjust [0x03]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x3))); 601 PHYMOD_DIAG_OUT(("| clk90_offset_override [0x04]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x4))); 602 PHYMOD_DIAG_OUT(("| lane_event_log_level [0x05]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x5))); 603 PHYMOD_DIAG_OUT(("| disable_startup [0x06]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x6))); 604 PHYMOD_DIAG_OUT(("| disable_startup_dfe [0x07]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x7))); 605 PHYMOD_DIAG_OUT(("| disable_steady_state [0x08]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x8))); 606 PHYMOD_DIAG_OUT(("| disable_steady_state_dfe [0x09]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x9))); 607 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 608 PHYMOD_DIAG_OUT(("| MICRO CODE USER STATUS REGISTERS |\n")); 609 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 610 PHYMOD_DIAG_OUT(("| restart_counter [0x0A]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0xa))); 611 PHYMOD_DIAG_OUT(("| reset_counter [0x0B]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0xb))); 612 PHYMOD_DIAG_OUT(("| pmd_lock_counter [0x0C]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0xc))); 613 PHYMOD_DIAG_OUT(("| heye_left [0x0D]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0xd))); 614 PHYMOD_DIAG_OUT(("| heye_left_lsbyte [0x0E]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0xe))); 615 PHYMOD_DIAG_OUT(("| heye_right [0x0F]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0xf))); 616 PHYMOD_DIAG_OUT(("| heye_right_lsbyte [0x10]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x10))); 617 PHYMOD_DIAG_OUT(("| veye_upper [0x11]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x11))); 618 PHYMOD_DIAG_OUT(("| veye_upper_lsbyte [0x12]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x12))); 619 PHYMOD_DIAG_OUT(("| veye_lower [0x13]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x13))); 620 PHYMOD_DIAG_OUT(("| veye_lower_lsbyte [0x14]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x14))); 621 PHYMOD_DIAG_OUT(("| micro_stopped [0x15]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x15))); 622 PHYMOD_DIAG_OUT(("| link_time [0x16]: 0x%04X |\n", falcon_tsc_rdwl_uc_var(pa,&errc,0x16))); 623 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 624 PHYMOD_DIAG_OUT(("| MICRO CODE MISC REGISTERS |\n")); 625 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 626 PHYMOD_DIAG_OUT(("| usr_diag_status [0x18]: 0x%04X |\n", falcon_tsc_rdwl_uc_var(pa,&errc,0x18))); 627 PHYMOD_DIAG_OUT(("| usr_diag_rd_ptr [0x1A]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x1a))); 628 PHYMOD_DIAG_OUT(("| usr_diag_mode [0x1B]: 0x%04X |\n", falcon_tsc_rdbl_uc_var(pa,&errc,0x1b))); 629 PHYMOD_DIAG_OUT(("| usr_var_msb [0x1C]: 0x%04X |\n", falcon_tsc_rdwl_uc_var(pa,&errc,0x1c))); 630 PHYMOD_DIAG_OUT(("| usr_var_lsb [0x1E]: 0x%04X |\n", falcon_tsc_rdwl_uc_var(pa,&errc,0x1e))); 631 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 632 } 633 634 STATIC int falcon_diagnostics_eyescan_run_uc(const phymod_phy_access_t* phy, uint32_t flags) 635 { 636 int ii, rc = PHYMOD_E_NONE; 637 uint32_t stripe[64]; 638 uint16_t status; 639 int j ; 640 phymod_phy_access_t phy_copy; 641 642 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 643 644 for(j=0; j< PHYMOD_CONFIG_MAX_LANES_PER_CORE; j++) { /* Loop for all lanes. */ 645 if ((phy->access.lane_mask & (1<<j))==0) continue; 646 647 phy_copy.access.lane_mask = (phy->access.lane_mask & (1<<j)); 648 649 if(PHYMOD_EYESCAN_F_ENABLE_GET(flags)) { 650 PHYMOD_IF_ERR_RETURN(falcon_tsc_meas_eye_scan_start(&(phy_copy.access), 0)); 651 652 if(!PHYMOD_EYESCAN_F_ENABLE_DONT_WAIT_GET(flags)) { 653 PHYMOD_USLEEP(100000); 654 } 655 } 656 657 if(PHYMOD_EYESCAN_F_PROCESS_GET(flags)) { 658 659 for (ii = 62; ii >= -62; ii=ii-2) { 660 if (ii == 62) { 661 PHYMOD_DIAG_OUT(("\n\n\n")); 662 PHYMOD_DIAG_OUT((" +--------------------------------------------------------------------+\n")); 663 PHYMOD_DIAG_OUT((" | EYESCAN Phy: 0x%03x lane_mask: 0x%02x |\n", phy_copy.access.addr, phy_copy.access.lane_mask)); 664 PHYMOD_DIAG_OUT((" +--------------------------------------------------------------------+\n")); 665 /*display eyescan header*/ 666 PHYMOD_IF_ERR_RETURN(falcon_tsc_display_eye_scan_header(&(phy_copy.access), 1)); 667 } 668 669 rc = falcon_tsc_read_eye_scan_stripe(&(phy_copy.access), stripe, &status); 670 if(rc != PHYMOD_E_NONE) { 671 _falcon_diag_uc_reg_dump(&(phy_copy.access)); 672 PHYMOD_IF_ERR_RETURN(rc); 673 } 674 PHYMOD_IF_ERR_RETURN(falcon_tsc_display_eye_scan_stripe(&(phy_copy.access), ii, &stripe[0])); 675 676 PHYMOD_DIAG_OUT(("\n")); 677 } 678 679 if (rc == PHYMOD_E_NONE) { 680 PHYMOD_IF_ERR_RETURN(falcon_tsc_display_eye_scan_footer(&(phy_copy.access), 1)); 681 PHYMOD_DIAG_OUT(("\n")); 682 } 683 } 684 685 if(PHYMOD_EYESCAN_F_DONE_GET(flags)) { 686 PHYMOD_IF_ERR_RETURN(falcon_tsc_meas_eye_scan_done(&(phy_copy.access))); 687 } 688 } 689 return PHYMOD_E_NONE; 690 } 691 692 STATIC int falcon_diagnostics_eyescan_run_lowber( 693 const phymod_phy_access_t* phy, 694 uint32_t flags, 695 const phymod_phy_eyescan_options_t* eyescan_options 696 ) 697 { 698 uint32_t *buffer; 699 int buffer_size = 64*64; 700 int rv = PHYMOD_E_NONE; 701 702 buffer = PHYMOD_MALLOC(sizeof(uint32_t) * buffer_size, "buffer"); 703 if (NULL == buffer) { 704 return PHYMOD_E_MEMORY; 705 } 706 PHYMOD_MEMSET(buffer, 0, sizeof(uint32_t) * buffer_size); 707 708 /*enable eyescan*/ 709 if(PHYMOD_EYESCAN_F_PROCESS_GET(flags)) { 710 711 rv = falcon_phy_meas_lowber_eye (&(phy->access), eyescan_options, buffer); 712 if (rv < 0) { 713 goto cleanup; 714 } 715 rv = falcon_phy_display_lowber_eye (&(phy->access), eyescan_options, buffer); 716 if (rv < 0) { 717 goto cleanup; 718 } 719 } 720 if (buffer != NULL) { 721 PHYMOD_FREE(buffer); 722 } 723 724 if(PHYMOD_EYESCAN_F_DONE_GET(flags)) { 725 PHYMOD_IF_ERR_RETURN(falcon_tsc_pmd_uc_cmd(&(phy->access), CMD_CAPTURE_BER_END, 0, 2000)); 726 } 727 728 return PHYMOD_E_NONE; 729 730 cleanup: 731 if (buffer != NULL) { 732 PHYMOD_FREE(buffer); 733 } 734 735 return rv; 736 } 737 738 int falcon_diagnostics_eye_margin_proj( const phymod_phy_access_t* phy, uint32_t flags, 739 const phymod_phy_eyescan_options_t* eyescan_options) { 740 #ifdef SERDES_API_FLOATING_POINT 741 int osr_mode; 742 USR_DOUBLE data_rate, data_rate_in_Mhz; 743 phymod_phy_access_t phy_copy; 744 int start_lane, num_lane, i, found=0; 745 746 struct falcon_tsc_uc_core_config_st core_cfg; 747 if(PHYMOD_EYESCAN_F_PROCESS_GET(flags)) { 748 PHYMOD_IF_ERR_RETURN 749 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 750 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 751 for (i = 0; i < num_lane; i++) { 752 phy_copy.access.lane_mask = 1 << (start_lane + i); 753 754 if (found == 0) { 755 PHYMOD_IF_ERR_RETURN(falcon_tsc_get_uc_core_config (&(phy_copy.access), &core_cfg)); 756 PHYMOD_IF_ERR_RETURN(falcon_osr_mode_get(&phy_copy.access, &osr_mode)); 757 data_rate = (core_cfg.vco_rate_in_Mhz * 1000.0 * 1000.0) / (1<<osr_mode); 758 data_rate_in_Mhz = (core_cfg.vco_rate_in_Mhz) / (1<<osr_mode); 759 found = 1; 760 } 761 if(num_lane > 1) { 762 PHYMOD_DIAG_OUT((" l=%0d, data rate = %fMHz\n", i, data_rate_in_Mhz)); 763 } else { 764 PHYMOD_DIAG_OUT((" data rate = %fMHz\n", data_rate_in_Mhz)); 765 } 766 falcon_tsc_eye_margin_proj(&phy_copy.access, data_rate, eyescan_options->ber_proj_scan_mode, 767 eyescan_options->ber_proj_timer_cnt, eyescan_options->ber_proj_err_cnt); 768 } 769 } 770 #else 771 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("BER Proj is supported with SERDES_API_FLOATING_POINT only\n"))); 772 #endif 773 return PHYMOD_E_NONE; 774 } 775 776 int falcon_phy_eyescan_run(const phymod_phy_access_t* phy, 777 uint32_t flags, 778 phymod_eyescan_mode_t mode, 779 const phymod_phy_eyescan_options_t* eyescan_options) 780 { 781 uint8_t pmd_rx_lock=0; 782 783 PHYMOD_IF_ERR_RETURN 784 (falcon_tsc_pmd_lock_status(&phy->access, &pmd_rx_lock)); 785 if(pmd_rx_lock == 0) { 786 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("Can not get eyescan when pmd_rx is not locked\n"))); 787 } 788 789 /* If stage isn't set - perform all stages*/ 790 if(!PHYMOD_EYESCAN_F_ENABLE_GET(flags) 791 && !PHYMOD_EYESCAN_F_PROCESS_GET(flags) 792 && !PHYMOD_EYESCAN_F_DONE_GET(flags)) 793 { 794 PHYMOD_EYESCAN_F_ENABLE_SET(flags); 795 PHYMOD_EYESCAN_F_PROCESS_SET(flags); 796 PHYMOD_EYESCAN_F_DONE_SET(flags); 797 } 798 799 800 /* mode phymodEyescanModeBERProj gives BER projection */ 801 switch(mode) { 802 case phymodEyescanModeFast: 803 return falcon_diagnostics_eyescan_run_uc(phy, flags); 804 case phymodEyescanModeLowBER: 805 return falcon_diagnostics_eyescan_run_lowber(phy, flags, eyescan_options); 806 case phymodEyescanModeBERProj: 807 return falcon_diagnostics_eye_margin_proj(phy, flags, eyescan_options); 808 default: 809 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, (_PHYMOD_MSG("unsupported eyescan mode %u"), mode)); 810 } 811 } 812 813 814 #endif /* PHYMOD_FALCON_SUPPORT */