qtce16_diagnostics.c (17896B)
1 /* 2 * 3 * 4 * 5 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 6 * 7 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 8 */ 9 10 #include <phymod/phymod.h> 11 #include <phymod/phymod_system.h> 12 #include <phymod/phymod_diagnostics.h> 13 #include <phymod/phymod_config.h> 14 #include <phymod/phymod_util.h> 15 #include <phymod/phymod_config.h> 16 #include "qtce16/tier1/qmod16_enum_defines.h" 17 #include "qtce16/tier1/qmod16.h" 18 #include "merlin16/tier1/merlin16_common.h" 19 #include "merlin16/tier1/merlin16_interface.h" 20 #include "merlin16/tier1/merlin16_cfg_seq.h" 21 #include "merlin16/tier1/merlin16_debug_functions.h" 22 23 #ifdef PHYMOD_QTCE16_SUPPORT 24 25 int qtce16_phy_rx_slicer_position_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_slicer_position_t* position) 26 { 27 28 return PHYMOD_E_NONE; 29 30 } 31 32 int qtce16_phy_rx_slicer_position_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_slicer_position_t* position) 33 { 34 35 return PHYMOD_E_NONE; 36 37 } 38 39 40 int qtce16_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) 41 { 42 43 /* Place your code here */ 44 45 46 return PHYMOD_E_NONE; 47 48 } 49 50 STATIC 51 int _qtce16_prbs_poly_phymod_to_merlin16(phymod_prbs_poly_t phymod_poly, enum srds_prbs_polynomial_enum *merlin16_poly) 52 { 53 switch(phymod_poly){ 54 case phymodPrbsPoly7: 55 *merlin16_poly = PRBS_7; 56 break; 57 case phymodPrbsPoly9: 58 *merlin16_poly = PRBS_9; 59 break; 60 case phymodPrbsPoly11: 61 *merlin16_poly = PRBS_11; 62 break; 63 case phymodPrbsPoly15: 64 *merlin16_poly = PRBS_15; 65 break; 66 case phymodPrbsPoly23: 67 *merlin16_poly = PRBS_23; 68 break; 69 case phymodPrbsPoly31: 70 *merlin16_poly = PRBS_31; 71 break; 72 case phymodPrbsPoly58: 73 *merlin16_poly = PRBS_58; 74 break; 75 default: 76 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, (_PHYMOD_MSG("unsupported poly for qtce %u"), phymod_poly)); 77 } 78 return PHYMOD_E_NONE; 79 } 80 81 STATIC 82 int _qtce16_prbs_poly_qtce_to_phymod(enum srds_prbs_polynomial_enum merlin16_poly, phymod_prbs_poly_t *phymod_poly) 83 { 84 switch(merlin16_poly){ 85 case PRBS_7: 86 *phymod_poly = phymodPrbsPoly7; 87 break; 88 case PRBS_9: 89 *phymod_poly = phymodPrbsPoly9; 90 break; 91 case PRBS_11: 92 *phymod_poly = phymodPrbsPoly11; 93 break; 94 case PRBS_15: 95 *phymod_poly = phymodPrbsPoly15; 96 break; 97 case PRBS_23: 98 *phymod_poly = phymodPrbsPoly23; 99 break; 100 case PRBS_31: 101 *phymod_poly = phymodPrbsPoly31; 102 break; 103 case PRBS_58: 104 *phymod_poly = phymodPrbsPoly58; 105 break; 106 default: 107 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("uknown poly %u"), merlin16_poly)); 108 } 109 return PHYMOD_E_NONE; 110 } 111 112 #ifdef PHYMOD_TO_QTCE_OS_MODE_TRANS 113 STATIC 114 int _qtce_os_mode_phymod_to_qtce(phymod_osr_mode_t phymod_os_mode, qmod16_os_mode_type *tsce_os_mode) 115 { 116 switch(phymod_os_mode){ 117 case phymodOversampleMode1: 118 *tsce_os_mode = QMOD16_PMA_OS_MODE_1; 119 break; 120 case phymodOversampleMode2: 121 *tsce_os_mode = QMOD16_PMA_OS_MODE_2; 122 break; 123 case phymodOversampleMode3: 124 *tsce_os_mode = QMOD16_PMA_OS_MODE_3; 125 break; 126 case phymodOversampleMode3P3: 127 *tsce_os_mode = QMOD16_PMA_OS_MODE_3_3; 128 break; 129 case phymodOversampleMode4: 130 *tsce_os_mode = QMOD16_PMA_OS_MODE_4; 131 break; 132 case phymodOversampleMode5: 133 *tsce_os_mode = QMOD16_PMA_OS_MODE_5; 134 break; 135 case phymodOversampleMode8: 136 *tsce_os_mode = QMOD16_PMA_OS_MODE_8; 137 break; 138 case phymodOversampleMode8P25: 139 *tsce_os_mode = QMOD16_PMA_OS_MODE_8_25; 140 break; 141 case phymodOversampleMode10: 142 *tsce_os_mode = QMOD16_PMA_OS_MODE_10; 143 break; 144 default: 145 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, (_PHYMOD_MSG("unsupported over sample mode for qtce %u"), phymod_os_mode)); 146 } 147 return PHYMOD_E_NONE; 148 } 149 #endif 150 151 STATIC 152 int _qtce16_os_mode_qtce_to_phymod(qmod16_os_mode_type tsce_os_mode, phymod_osr_mode_t *phymod_os_mode) 153 { 154 switch(tsce_os_mode){ 155 case QMOD16_PMA_OS_MODE_1: 156 *phymod_os_mode = phymodOversampleMode1; 157 break; 158 case QMOD16_PMA_OS_MODE_2: 159 *phymod_os_mode = phymodOversampleMode2; 160 break; 161 case QMOD16_PMA_OS_MODE_3: 162 *phymod_os_mode = phymodOversampleMode3; 163 break; 164 case QMOD16_PMA_OS_MODE_3_3: 165 *phymod_os_mode = phymodOversampleMode3P3; 166 break; 167 case QMOD16_PMA_OS_MODE_4: 168 *phymod_os_mode = phymodOversampleMode4; 169 break; 170 case QMOD16_PMA_OS_MODE_5: 171 *phymod_os_mode = phymodOversampleMode5; 172 break; 173 case QMOD16_PMA_OS_MODE_8: 174 *phymod_os_mode = phymodOversampleMode8; 175 break; 176 case QMOD16_PMA_OS_MODE_8_25: 177 *phymod_os_mode = phymodOversampleMode8P25; 178 break; 179 case QMOD16_PMA_OS_MODE_10: 180 *phymod_os_mode = phymodOversampleMode10; 181 break; 182 default: 183 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("uknown os mode %u"), tsce_os_mode)); 184 } 185 return PHYMOD_E_NONE; 186 } 187 188 int qtce16_phy_prbs_config_set(const phymod_phy_access_t* phy, uint32_t flags , const phymod_prbs_t* prbs) 189 { 190 191 phymod_phy_access_t phy_copy; 192 int start_lane, num_lane, lane_id, sub_port; 193 int i = 0; 194 195 enum srds_prbs_polynomial_enum merlin16_poly; 196 197 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 198 199 /*next figure out the lane num and start_lane based on the input*/ 200 PHYMOD_IF_ERR_RETURN 201 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 202 PHYMOD_IF_ERR_RETURN 203 (qmod16_lane_info(&phy->access, &lane_id, &sub_port)); 204 start_lane = lane_id; 205 206 PHYMOD_IF_ERR_RETURN(_qtce16_prbs_poly_phymod_to_merlin16(prbs->poly, &merlin16_poly)); 207 /*first check which direction */ 208 if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 209 for (i = 0; i < num_lane; i++) { 210 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 211 PHYMOD_IF_ERR_RETURN 212 (merlin16_config_rx_prbs(&phy_copy.access, merlin16_poly, PRBS_INITIAL_SEED_HYSTERESIS, prbs->invert)); 213 } 214 } else if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 215 for (i = 0; i < num_lane; i++) { 216 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 217 PHYMOD_IF_ERR_RETURN 218 (merlin16_config_tx_prbs(&phy_copy.access, merlin16_poly, prbs->invert)); 219 } 220 } else { 221 for (i = 0; i < num_lane; i++) { 222 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 223 PHYMOD_IF_ERR_RETURN 224 (merlin16_config_rx_prbs(&phy_copy.access, merlin16_poly, PRBS_INITIAL_SEED_HYSTERESIS, prbs->invert)); 225 PHYMOD_IF_ERR_RETURN 226 (merlin16_config_tx_prbs(&phy_copy.access, merlin16_poly, prbs->invert)); 227 } 228 } 229 return PHYMOD_E_NONE; 230 231 } 232 233 int qtce16_phy_prbs_config_get(const phymod_phy_access_t* phy, uint32_t flags , phymod_prbs_t* prbs) 234 { 235 phymod_phy_access_t phy_copy; 236 uint8_t invert; 237 enum srds_prbs_checker_mode_enum merlin16_checker_mode; 238 enum srds_prbs_polynomial_enum merlin16_poly; 239 240 int lane_id, sub_port; 241 242 PHYMOD_IF_ERR_RETURN 243 (qmod16_lane_info(&phy->access, &lane_id, &sub_port)); 244 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 245 /*There is only single lane mode in QTCE*/ 246 phy_copy.access.lane_mask = 0x1 << lane_id; 247 248 if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 249 PHYMOD_IF_ERR_RETURN(merlin16_get_tx_prbs_config(&phy_copy.access, &merlin16_poly, &invert)); 250 } else if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 251 PHYMOD_IF_ERR_RETURN(merlin16_get_rx_prbs_config(&phy_copy.access, &merlin16_poly, &merlin16_checker_mode, &invert)); 252 } else { 253 PHYMOD_IF_ERR_RETURN(merlin16_get_tx_prbs_config(&phy_copy.access, &merlin16_poly, &invert)); 254 } 255 256 prbs->invert = (uint32_t) invert; 257 PHYMOD_IF_ERR_RETURN(_qtce16_prbs_poly_qtce_to_phymod(merlin16_poly, &(prbs->poly))); 258 259 return PHYMOD_E_NONE; 260 261 } 262 263 264 int qtce16_phy_prbs_enable_set(const phymod_phy_access_t* phy, uint32_t flags , uint32_t enable) 265 { 266 267 phymod_phy_access_t phy_copy; 268 int start_lane, num_lane, lane_id, sub_port; 269 int i = 0; 270 271 272 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 273 274 /*next figure out the lane num and start_lane based on the input*/ 275 PHYMOD_IF_ERR_RETURN 276 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 277 PHYMOD_IF_ERR_RETURN 278 (qmod16_lane_info(&phy->access, &lane_id, &sub_port)); 279 start_lane = lane_id; 280 281 if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 282 for (i = 0; i < num_lane; i++) { 283 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 284 PHYMOD_IF_ERR_RETURN(merlin16_tx_prbs_en(&phy_copy.access, enable)); 285 } 286 } else if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 287 for (i = 0; i < num_lane; i++) { 288 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 289 PHYMOD_IF_ERR_RETURN(merlin16_rx_prbs_en(&phy_copy.access, enable)); 290 } 291 } else { 292 for (i = 0; i < num_lane; i++) { 293 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 294 PHYMOD_IF_ERR_RETURN(merlin16_tx_prbs_en(&phy_copy.access, enable)); 295 PHYMOD_IF_ERR_RETURN(merlin16_rx_prbs_en(&phy_copy.access, enable)); 296 } 297 } 298 return PHYMOD_E_NONE; 299 300 } 301 302 int qtce16_phy_prbs_enable_get(const phymod_phy_access_t* phy, uint32_t flags , uint32_t* enable) 303 { 304 uint8_t enable_tmp; 305 phymod_phy_access_t phy_copy; 306 int lane_id, sub_port; 307 308 PHYMOD_IF_ERR_RETURN 309 (qmod16_lane_info(&phy->access, &lane_id, &sub_port)); 310 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 311 /*There is only single lane mode in QTCE*/ 312 phy_copy.access.lane_mask = 0x1 << lane_id; 313 314 if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 315 PHYMOD_IF_ERR_RETURN(merlin16_get_tx_prbs_en(&phy_copy.access, &enable_tmp)); 316 *enable = enable_tmp; 317 } else if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 318 PHYMOD_IF_ERR_RETURN(merlin16_get_rx_prbs_en(&phy_copy.access, &enable_tmp)); 319 *enable = enable_tmp; 320 } else { 321 PHYMOD_IF_ERR_RETURN(merlin16_get_tx_prbs_en(&phy_copy.access, &enable_tmp)); 322 *enable = enable_tmp; 323 PHYMOD_IF_ERR_RETURN(merlin16_get_rx_prbs_en(&phy_copy.access, &enable_tmp)); 324 *enable &= enable_tmp; 325 } 326 327 return PHYMOD_E_NONE; 328 329 } 330 331 332 int qtce16_phy_prbs_status_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_prbs_status_t* prbs_status) 333 { 334 uint8_t status = 0; 335 uint32_t prbs_err_count = 0; 336 int i, start_lane, num_lane, lane_id, sub_port; 337 phymod_phy_access_t phy_copy; 338 339 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 340 /* next figure out the lane num and start_lane based on the input */ 341 PHYMOD_IF_ERR_RETURN 342 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 343 PHYMOD_IF_ERR_RETURN 344 (qmod16_lane_info(&phy->access, &lane_id, &sub_port)); 345 start_lane = lane_id; 346 347 prbs_status->prbs_lock = 1; 348 prbs_status->error_count = 0; 349 prbs_status->prbs_lock_loss = 0; 350 351 for (i = 0; i < num_lane; i++) { 352 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 353 PHYMOD_IF_ERR_RETURN(merlin16_prbs_chk_lock_state(&phy_copy.access, &status)); 354 if (status) { 355 /*next check the lost of lock and error count */ 356 status = 0; 357 PHYMOD_IF_ERR_RETURN 358 (merlin16_prbs_err_count_state(&phy_copy.access, &prbs_err_count, &status)); 359 PHYMOD_DEBUG_VERBOSE((" Lane :: %d PRBS Error count :: %d lock_loss=%0d\n", i, prbs_err_count, status)); 360 if (status) { 361 /*temp lost of lock */ 362 prbs_status->prbs_lock_loss = 1; 363 } else { 364 prbs_status->error_count += prbs_err_count; 365 } 366 } else { 367 PHYMOD_DEBUG_VERBOSE((" Lane :: %d PRBS not locked\n", i )); 368 prbs_status->prbs_lock = 0; 369 return PHYMOD_E_NONE; 370 } 371 } 372 return PHYMOD_E_NONE; 373 374 } 375 376 377 int qtce16_phy_pattern_config_set(const phymod_phy_access_t* phy, const phymod_pattern_t* pattern) 378 { 379 380 return PHYMOD_E_NONE; 381 382 } 383 384 int qtce16_phy_pattern_config_get(const phymod_phy_access_t* phy, phymod_pattern_t* pattern) 385 { 386 387 return PHYMOD_E_NONE; 388 389 } 390 391 392 int qtce16_phy_pattern_enable_set(const phymod_phy_access_t* phy, uint32_t enable, const phymod_pattern_t* pattern) 393 { 394 395 /* Place your code here */ 396 397 398 return PHYMOD_E_NONE; 399 400 } 401 402 int qtce16_phy_pattern_enable_get(const phymod_phy_access_t* phy, uint32_t* enable) 403 { 404 405 /* Place your code here */ 406 407 408 return PHYMOD_E_NONE; 409 410 } 411 412 413 int qtce16_core_diagnostics_get(const phymod_core_access_t* core, phymod_core_diagnostics_t* diag) 414 { 415 416 417 return PHYMOD_E_NONE; 418 419 } 420 421 422 int qtce16_phy_diagnostics_get(const phymod_phy_access_t* phy, phymod_phy_diagnostics_t* diag) 423 { 424 phymod_phy_access_t phy_copy; 425 int lane_id, sub_port; 426 qmod16_os_mode_type os_mode = QMOD16_PMA_OS_MODE_1; 427 phymod_diag_eyescan_t_init(&diag->eyescan); 428 phymod_diag_slicer_offset_t_init(&diag->slicer_offset); 429 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 430 PHYMOD_IF_ERR_RETURN 431 (qmod16_lane_info(&phy->access, &lane_id, &sub_port)); 432 /*There is only single lane mode in QTCE*/ 433 phy_copy.access.lane_mask = 0x1 << lane_id; 434 435 PHYMOD_IF_ERR_RETURN(qmod16_pmd_lock_get(&phy_copy.access, &diag->rx_lock)); 436 437 PHYMOD_IF_ERR_RETURN(_qtce16_os_mode_qtce_to_phymod(os_mode, &diag->osr_mode)); 438 439 return PHYMOD_E_NONE; 440 } 441 442 443 int qtce16_phy_pmd_info_dump(const phymod_phy_access_t* phy, const char* type) 444 { 445 int start_lane, num_lane, lane_id, sub_port; 446 phymod_phy_access_t phy_copy; 447 int i = 0; 448 uint32_t cmd_type; 449 int is_in_reset = 0; 450 451 if (!type) { 452 cmd_type = (uint32_t)QMOD16_DIAG_DSC; 453 } else if (!PHYMOD_STRCMP(type, "ber")) { 454 cmd_type = (uint32_t)QMOD16_DIAG_BER; 455 } else if (!PHYMOD_STRCMP(type, "config")) { 456 cmd_type = (uint32_t)QMOD16_DIAG_CFG; 457 } else if (!PHYMOD_STRCMP(type, "CL72")||!PHYMOD_STRCMP(type, "cl72")) { 458 cmd_type = (uint32_t)QMOD16_DIAG_CL72; 459 } else if (!PHYMOD_STRCMP(type, "debug")) { 460 cmd_type = (uint32_t)QMOD16_DIAG_DEBUG; 461 } else if (!PHYMOD_STRCMP(type, "state")) { 462 cmd_type = (uint32_t)QMOD16_DIAG_STATE; 463 } else { 464 cmd_type = (uint32_t)QMOD16_DIAG_DSC; 465 } 466 467 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 468 469 /*next figure out the lane num and start_lane based on the input*/ 470 PHYMOD_IF_ERR_RETURN 471 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 472 PHYMOD_IF_ERR_RETURN 473 (qmod16_lane_info(&phy->access, &lane_id, &sub_port)); 474 start_lane = lane_id; 475 476 if(cmd_type==QMOD16_DIAG_DSC) { 477 PHYMOD_IF_ERR_RETURN 478 (merlin16_display_core_state(&phy_copy.access)); 479 PHYMOD_IF_ERR_RETURN 480 (merlin16_display_lane_state_hdr()); 481 for (i = 0; i < 4; i++) { 482 phy_copy.access.lane_mask = 0x1 << i ; 483 PHYMOD_IF_ERR_RETURN 484 (qmod16_pmd_x4_reset_get(&phy_copy.access, &is_in_reset)); 485 if(is_in_reset) { 486 PHYMOD_DIAG_OUT((" - skip lane=%0d\n", i)); 487 continue; 488 } 489 PHYMOD_IF_ERR_RETURN 490 (merlin16_display_lane_state(&phy_copy.access)); 491 } 492 } else { 493 for (i = 0; i < num_lane; i++) { 494 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 495 496 switch(cmd_type) { 497 case QMOD16_DIAG_CFG: 498 PHYMOD_IF_ERR_RETURN 499 (merlin16_display_core_config(&phy_copy.access)); 500 PHYMOD_IF_ERR_RETURN 501 (merlin16_display_lane_config(&phy_copy.access)); 502 break; 503 504 case QMOD16_DIAG_CL72: 505 PHYMOD_IF_ERR_RETURN 506 (merlin16_display_cl72_status(&phy_copy.access)); 507 break; 508 509 case QMOD16_DIAG_DEBUG: 510 PHYMOD_IF_ERR_RETURN 511 (merlin16_display_lane_debug_status(&phy_copy.access)); 512 break; 513 514 case QMOD16_DIAG_BER: 515 break; 516 517 case QMOD16_DIAG_STATE: 518 default: 519 PHYMOD_IF_ERR_RETURN 520 (merlin16_display_core_state_hdr()); 521 PHYMOD_IF_ERR_RETURN 522 (merlin16_display_core_state_line(&phy_copy.access)); 523 PHYMOD_IF_ERR_RETURN 524 (merlin16_display_core_state(&phy_copy.access)); 525 PHYMOD_IF_ERR_RETURN 526 (merlin16_display_lane_state_hdr()); 527 PHYMOD_IF_ERR_RETURN 528 (merlin16_display_lane_state(&phy_copy.access)); 529 PHYMOD_IF_ERR_RETURN 530 (merlin16_read_event_log(&phy_copy.access)); 531 break; 532 } 533 } 534 } 535 return PHYMOD_E_NONE; 536 537 } 538 539 540 int qtce16_phy_pcs_info_dump(const phymod_phy_access_t* phy, const char* type) 541 { 542 int lane_id, sub_port; 543 phymod_phy_access_t phy_copy; 544 545 PHYMOD_IF_ERR_RETURN 546 (qmod16_lane_info(&phy->access, &lane_id, &sub_port)); 547 548 PHYMOD_MEMCPY (&phy_copy, phy, sizeof(phy_copy)); 549 phy_copy.access.lane_mask = 0x1 << lane_id; 550 551 PHYMOD_IF_ERR_RETURN (qmod16_diag_disp(&phy_copy.access, type)); 552 553 return PHYMOD_E_NONE; 554 } 555 556 557 #endif /* PHYMOD_QTCE16_SUPPORT */