blackhawk_diagnostics.c (42288B)
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_diag.h> 17 #include <phymod/phymod_diagnostics_dispatch.h> 18 #include <phymod/chip/blackhawk.h> 19 #include <phymod/chip/blackhawk_diagnostics.h> 20 #include "blackhawk/tier1/blackhawk_cfg_seq.h" 21 #include "blackhawk/tier1/common/srds_api_enum.h" 22 #include "blackhawk/tier1/blackhawk_tsc_enum.h" 23 #include "blackhawk/tier1/blackhawk_tsc_common.h" 24 #include "blackhawk/tier1/blackhawk_tsc_interface.h" 25 #include "blackhawk/tier1/blackhawk_tsc_dependencies.h" 26 #include "blackhawk/tier1/blackhawk_tsc_internal.h" 27 #include "blackhawk/tier1/public/blackhawk_api_uc_vars_rdwr_defns_public.h" 28 #include "blackhawk/tier1/blackhawk_tsc_access.h" 29 #include "blackhawk/tier1/blackhawk_tsc_types.h" 30 31 32 33 #define PATTERN_MAX_LENGTH 240 34 #ifdef PHYMOD_BLACKHAWK_SUPPORT 35 36 37 /*phymod, internal enum mappings*/ 38 STATIC 39 int _blackhawk_prbs_poly_phymod_to_blackhawk(phymod_prbs_poly_t phymod_poly, enum srds_prbs_polynomial_enum *blackhawk_poly) 40 { 41 switch(phymod_poly){ 42 case phymodPrbsPoly7: 43 *blackhawk_poly = PRBS_7; 44 break; 45 case phymodPrbsPoly9: 46 *blackhawk_poly = PRBS_9; 47 break; 48 case phymodPrbsPoly11: 49 *blackhawk_poly = PRBS_11; 50 break; 51 case phymodPrbsPoly15: 52 *blackhawk_poly = PRBS_15; 53 break; 54 case phymodPrbsPoly23: 55 *blackhawk_poly = PRBS_23; 56 break; 57 case phymodPrbsPoly31: 58 *blackhawk_poly = PRBS_31; 59 break; 60 case phymodPrbsPoly58: 61 *blackhawk_poly = PRBS_58; 62 break; 63 case phymodPrbsPoly49: 64 *blackhawk_poly = PRBS_49; 65 break; 66 case phymodPrbsPoly10: 67 *blackhawk_poly = PRBS_10; 68 break; 69 case phymodPrbsPoly20: 70 *blackhawk_poly = PRBS_20; 71 break; 72 case phymodPrbsPoly13: 73 *blackhawk_poly = PRBS_13; 74 break; 75 default: 76 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, (_PHYMOD_MSG("unsupported poly for blackhawk %u"), phymod_poly)); 77 } 78 return PHYMOD_E_NONE; 79 } 80 81 STATIC 82 int _blackhawk_prbs_poly_blackhawk_to_phymod(enum srds_prbs_polynomial_enum *blackhawk_poly, phymod_prbs_poly_t *phymod_poly) 83 { 84 switch(*blackhawk_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 case PRBS_49: 107 *phymod_poly = phymodPrbsPoly49; 108 break; 109 case PRBS_10: 110 *phymod_poly = phymodPrbsPoly10; 111 break; 112 case PRBS_20: 113 *phymod_poly = phymodPrbsPoly20; 114 break; 115 case PRBS_13: 116 *phymod_poly = phymodPrbsPoly13; 117 break; 118 default: 119 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("uknown poly %u"), *blackhawk_poly)); 120 } 121 return PHYMOD_E_NONE; 122 } 123 124 int blackhawk_phy_rx_slicer_position_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_slicer_position_t* position) 125 { 126 127 128 /* Not supported */ 129 PHYMOD_DEBUG_ERROR(("blackhawk_phy_rx_slicer_position_set function is NOT SUPPORTED!!\n")); 130 131 132 return PHYMOD_E_NONE; 133 134 } 135 136 int blackhawk_phy_rx_slicer_position_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_slicer_position_t* position) 137 { 138 139 140 /* Not supported */ 141 PHYMOD_DEBUG_ERROR(("blackhawk_phy_rx_slicer_position_get function is NOT SUPPORTED!!\n")); 142 143 144 return PHYMOD_E_NONE; 145 146 } 147 148 149 int blackhawk_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) 150 { 151 152 153 /* Not supported */ 154 PHYMOD_DEBUG_ERROR(("blackhawk_phy_rx_slicer_position_max_get function is NOT SUPPORTED!!\n")); 155 156 157 return PHYMOD_E_NONE; 158 159 } 160 161 162 int blackhawk_phy_prbs_config_set(const phymod_phy_access_t* phy, uint32_t flags , const phymod_prbs_t* prbs) 163 { 164 enum srds_prbs_polynomial_enum blackhawk_poly; 165 phymod_phy_access_t phy_copy; 166 int start_lane, num_lane, i; 167 phymod_firmware_lane_config_t fw_config; 168 169 PHYMOD_IF_ERR_RETURN 170 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 171 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 172 173 /* next to see if the port is PAM4 or not */ 174 PHYMOD_IF_ERR_RETURN 175 (blackhawk_phy_firmware_lane_config_get(phy, &fw_config)); 176 177 PHYMOD_IF_ERR_RETURN(_blackhawk_prbs_poly_phymod_to_blackhawk(prbs->poly, &blackhawk_poly)); 178 /*first check which direction */ 179 for (i = 0; i < num_lane; i++) { 180 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 181 continue; 182 } 183 phy_copy.access.lane_mask = 1 << (start_lane + i); 184 if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 185 /* if PAM4 speed, use mode 2 */ 186 if (fw_config.ForcePAM4Mode) { 187 PHYMOD_IF_ERR_RETURN 188 (blackhawk_tsc_config_rx_prbs(&phy_copy.access, blackhawk_poly,PRBS_INITIAL_SEED_NO_HYSTERESIS, prbs->invert)); 189 } else { 190 PHYMOD_IF_ERR_RETURN 191 (blackhawk_tsc_config_rx_prbs(&phy_copy.access, blackhawk_poly,PRBS_INITIAL_SEED_HYSTERESIS, prbs->invert)); 192 } 193 } else if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 194 PHYMOD_IF_ERR_RETURN 195 (blackhawk_tsc_config_tx_prbs(&phy_copy.access, blackhawk_poly, prbs->invert)); 196 } else { 197 /* if PAM4 speed, use mode 2 */ 198 if (fw_config.ForcePAM4Mode) { 199 PHYMOD_IF_ERR_RETURN 200 (blackhawk_tsc_config_rx_prbs(&phy_copy.access, blackhawk_poly,PRBS_INITIAL_SEED_NO_HYSTERESIS, prbs->invert)); 201 } else { 202 PHYMOD_IF_ERR_RETURN 203 (blackhawk_tsc_config_rx_prbs(&phy_copy.access, blackhawk_poly,PRBS_INITIAL_SEED_HYSTERESIS, prbs->invert)); 204 } 205 PHYMOD_IF_ERR_RETURN 206 (blackhawk_tsc_config_tx_prbs(&phy_copy.access, blackhawk_poly, prbs->invert)); 207 } 208 } 209 return PHYMOD_E_NONE; 210 } 211 212 int blackhawk_phy_prbs_config_get(const phymod_phy_access_t* phy, uint32_t flags , phymod_prbs_t* prbs) 213 { 214 phymod_prbs_t config_tmp; 215 enum srds_prbs_polynomial_enum blackhawk_poly; 216 enum srds_prbs_checker_mode_enum prbs_checker_mode; 217 phymod_phy_access_t phy_copy; 218 uint8_t invert; 219 220 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 221 222 223 if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 224 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_get_tx_prbs_config(&phy_copy.access, &blackhawk_poly, &invert)); 225 config_tmp.invert = invert; 226 PHYMOD_IF_ERR_RETURN(_blackhawk_prbs_poly_blackhawk_to_phymod(&blackhawk_poly, &config_tmp.poly)); 227 prbs->invert = config_tmp.invert; 228 prbs->poly = config_tmp.poly; 229 } else if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 230 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_get_rx_prbs_config(&phy_copy.access, 231 &blackhawk_poly, 232 &prbs_checker_mode, 233 &invert)); 234 config_tmp.invert = invert; 235 PHYMOD_IF_ERR_RETURN(_blackhawk_prbs_poly_blackhawk_to_phymod(&blackhawk_poly, &config_tmp.poly)); 236 prbs->invert = config_tmp.invert; 237 prbs->poly = config_tmp.poly; 238 } else { 239 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_get_tx_prbs_config(&phy_copy.access, &blackhawk_poly, &invert)); 240 config_tmp.invert = invert; 241 PHYMOD_IF_ERR_RETURN(_blackhawk_prbs_poly_blackhawk_to_phymod(&blackhawk_poly, &config_tmp.poly)); 242 prbs->invert = config_tmp.invert; 243 prbs->poly = config_tmp.poly; 244 } 245 return PHYMOD_E_NONE; 246 } 247 248 int blackhawk_phy_prbs_enable_set(const phymod_phy_access_t* phy, uint32_t flags , uint32_t enable) 249 { 250 phymod_phy_access_t phy_copy; 251 int start_lane, num_lane, i; 252 253 PHYMOD_IF_ERR_RETURN 254 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 255 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 256 257 /*first check which direction */ 258 for (i = 0; i < num_lane; i++) { 259 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 260 continue; 261 } 262 phy_copy.access.lane_mask = 1 << (start_lane + i); 263 if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 264 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_tx_prbs_en(&phy_copy.access, enable)); 265 } else if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 266 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_rx_prbs_en(&phy_copy.access, enable)); 267 } else { 268 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_tx_prbs_en(&phy_copy.access, enable)); 269 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_rx_prbs_en(&phy_copy.access, enable)); 270 } 271 } 272 return PHYMOD_E_NONE; 273 } 274 275 int blackhawk_phy_prbs_enable_get(const phymod_phy_access_t* phy, uint32_t flags , uint32_t* enable) 276 { 277 uint8_t enable_tmp; 278 phymod_phy_access_t phy_copy; 279 280 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 281 282 if (PHYMOD_PRBS_DIRECTION_TX_GET(flags)) { 283 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_get_tx_prbs_en(&phy_copy.access, &enable_tmp)); 284 *enable = enable_tmp; 285 } else if (PHYMOD_PRBS_DIRECTION_RX_GET(flags)) { 286 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_get_rx_prbs_en(&phy_copy.access, &enable_tmp)); 287 *enable = enable_tmp; 288 } else { 289 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_get_tx_prbs_en(&phy_copy.access, &enable_tmp)); 290 *enable = enable_tmp; 291 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_get_rx_prbs_en(&phy_copy.access, &enable_tmp)); 292 *enable &= enable_tmp; 293 } 294 295 return PHYMOD_E_NONE; 296 297 } 298 299 300 int blackhawk_phy_prbs_status_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_prbs_status_t* prbs_status) 301 { 302 uint8_t status = 0; 303 uint32_t prbs_err_count = 0; 304 int i, start_lane, num_lane; 305 phymod_phy_access_t phy_copy; 306 307 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 308 /* next figure out the lane num and start_lane based on the input */ 309 PHYMOD_IF_ERR_RETURN 310 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 311 312 prbs_status->prbs_lock = 0; 313 prbs_status->error_count = 0; 314 prbs_status->prbs_lock_loss = 0; 315 prbs_status->prbs_lock = 1; 316 317 for (i = 0; i < num_lane; i++) { 318 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 319 continue; 320 } 321 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 322 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_prbs_chk_lock_state(&phy_copy.access, &status)); 323 if (status) { 324 /*next check the lost of lock and error count */ 325 status = 0; 326 PHYMOD_IF_ERR_RETURN 327 (blackhawk_tsc_prbs_err_count_state(&phy_copy.access, &prbs_err_count, &status)); 328 PHYMOD_DEBUG_VERBOSE((" Lane :: %d PRBS Error count :: %d\n", i, prbs_err_count)); 329 if (status) { 330 /*temp lost of lock */ 331 prbs_status->prbs_lock_loss = 1; 332 } else { 333 prbs_status->error_count += prbs_err_count; 334 } 335 } else { 336 PHYMOD_DEBUG_VERBOSE((" Lane :: %d PRBS not locked\n", i )); 337 prbs_status->prbs_lock = 0; 338 /* return PHYMOD_E_NONE; */ 339 } 340 } 341 return PHYMOD_E_NONE; 342 343 } 344 345 346 int blackhawk_phy_pattern_config_set(const phymod_phy_access_t* phy, const phymod_pattern_t* pattern) 347 { 348 int i,j = 0, bit; 349 char patt[PATTERN_MAX_LENGTH+1]; 350 phymod_phy_access_t phy_copy; 351 352 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 353 354 for (i=0; i< PATTERN_MAX_SIZE; i++) 355 { 356 for (j=0;j<32 && i*32+j <= PATTERN_MAX_LENGTH; j++) 357 { 358 if (i*32+j == pattern->pattern_len) { 359 break; 360 } 361 bit = pattern->pattern[i] >> j & 00000001; 362 switch (bit) { 363 case (1): 364 patt[i*32+j] = '1'; 365 break; 366 default: 367 patt[i*32+j] = '0'; 368 break; 369 } 370 } 371 if (i*32+j == pattern->pattern_len && i*32+j <= PATTERN_MAX_LENGTH) { 372 /* coverity[overrun-local] */ 373 patt[i*32+j] = '\0'; 374 break; 375 } 376 } 377 /* coverity[divide_by_zero : FALSE] */ 378 PHYMOD_IF_ERR_RETURN 379 (blackhawk_tsc_config_shared_tx_pattern (&phy_copy.access, 380 (uint8_t) pattern->pattern_len, (const char *) patt)); 381 return PHYMOD_E_NONE; 382 383 } 384 385 int blackhawk_phy_pattern_config_get(const phymod_phy_access_t* phy, phymod_pattern_t* pattern) 386 { 387 phymod_phy_access_t phy_copy; 388 389 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 390 PHYMOD_IF_ERR_RETURN 391 (blackhawk_tsc_config_shared_tx_pattern_idx_get(&phy_copy.access, 392 &pattern->pattern_len, 393 pattern->pattern)); 394 395 return PHYMOD_E_NONE; 396 397 } 398 399 400 int blackhawk_phy_pattern_enable_set(const phymod_phy_access_t* phy, uint32_t enable, const phymod_pattern_t* pattern) 401 { 402 phymod_phy_access_t phy_copy; 403 404 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 405 PHYMOD_IF_ERR_RETURN 406 (blackhawk_tsc_tx_shared_patt_gen_en(&phy_copy.access, (uint8_t) enable, (uint8_t)pattern->pattern_len)); 407 return PHYMOD_E_NONE; 408 409 } 410 411 int blackhawk_phy_pattern_enable_get(const phymod_phy_access_t* phy, uint32_t* enable) 412 { 413 phymod_phy_access_t phy_copy; 414 uint8_t enable_8; 415 416 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 417 PHYMOD_IF_ERR_RETURN 418 (blackhawk_tsc_tx_shared_patt_gen_en_get(&phy_copy.access, &enable_8)); 419 420 *enable = enable_8; 421 return PHYMOD_E_NONE; 422 423 } 424 425 426 int blackhawk_core_diagnostics_get(const phymod_core_access_t* core, phymod_core_diagnostics_t* diag) 427 { 428 429 return PHYMOD_E_NONE; 430 } 431 432 433 int blackhawk_phy_diagnostics_get(const phymod_phy_access_t* phy, phymod_phy_diagnostics_t* diag) 434 { 435 436 return PHYMOD_E_NONE; 437 } 438 439 int blackhawk_phy_pmd_info_dump(const phymod_phy_access_t* phy, const char* type) 440 { 441 int start_lane, num_lane; 442 uint32_t i, j, tmp_lane_mask; 443 phymod_phy_access_t phy_copy; 444 445 phymod_diag_type_t cmd_type; 446 srds_info_t *tsc_info_ptr = NULL; 447 448 if (!type) { 449 cmd_type = phymod_diag_DSC; 450 } else if ((!PHYMOD_STRCMP(type, "ber")) || 451 (!PHYMOD_STRCMP(type, "Ber")) || 452 (!PHYMOD_STRCMP(type, "BER"))) { 453 cmd_type = phymod_diag_BER; 454 } else if ((!PHYMOD_STRCMP(type, "config")) || 455 (!PHYMOD_STRCMP(type, "Config")) || 456 (!PHYMOD_STRCMP(type, "CONFIG"))) { 457 cmd_type = phymod_diag_CFG; 458 } else if ((!PHYMOD_STRCMP(type, "cl72")) || 459 (!PHYMOD_STRCMP(type, "Cl72")) || 460 (!PHYMOD_STRCMP(type, "CL72"))) { 461 cmd_type = phymod_diag_CL72; 462 } else if ((!PHYMOD_STRCMP(type, "debug")) || 463 (!PHYMOD_STRCMP(type, "Debug")) || 464 (!PHYMOD_STRCMP(type, "DEBUG"))) { 465 cmd_type = phymod_diag_DEBUG; 466 } else if ((!PHYMOD_STRCMP(type, "state")) || 467 (!PHYMOD_STRCMP(type, "State")) || 468 (!PHYMOD_STRCMP(type, "STATE"))) { 469 cmd_type = phymod_diag_STATE; 470 } else if ((!PHYMOD_STRCMP(type, "verbose")) || 471 (!PHYMOD_STRCMP(type, "Verbose")) || 472 (!PHYMOD_STRCMP(type, "VERBOSE"))) { 473 cmd_type = phymod_diag_ALL; 474 } else if (!PHYMOD_STRCMP(type, "STD")) { 475 cmd_type = phymod_diag_DSC_STD; 476 } else { 477 cmd_type = phymod_diag_STATE; 478 } 479 480 PHYMOD_DEBUG_ERROR((" %s:%d type = %d laneMask = 0x%X\n", __func__, __LINE__, cmd_type, phy->access.lane_mask)); 481 482 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 483 484 /* Make sure information table is initialized */ 485 tsc_info_ptr = blackhawk_tsc_INTERNAL_get_blackhawk_tsc_info_ptr(&phy_copy.access); 486 if (tsc_info_ptr->signature == 0) { 487 PHYMOD_IF_ERR_RETURN 488 (blackhawk_tsc_init_blackhawk_tsc_info(&phy_copy.access)); 489 } 490 /*next figure out the lane num and start_lane based on the input*/ 491 PHYMOD_IF_ERR_RETURN 492 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 493 494 if (cmd_type == phymod_diag_DSC) { 495 for (i = start_lane; i < start_lane + num_lane; i++) { 496 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, i)) { 497 continue; 498 } 499 phy_copy.access.lane_mask = 0x1 << i ; 500 PHYMOD_IF_ERR_RETURN 501 (blackhawk_tsc_display_diag_data(&phy_copy.access, SRDS_DIAG_CORE)); 502 } 503 } else if (cmd_type == phymod_diag_DSC_STD) { 504 505 PHYMOD_DIAG_OUT((" +--------------------------------------------------------------------+\n")); 506 PHYMOD_DIAG_OUT((" | DSC Phy: 0x%03x lane_mask: 0x%02x |\n", phy->access.addr, phy->access.lane_mask)); 507 PHYMOD_DIAG_OUT((" +--------------------------------------------------------------------+\n")); 508 tmp_lane_mask = phy_copy.access.lane_mask; 509 for (j = 0; j < 8; j++) { 510 phy_copy.access.lane_mask = 0x1 << j; 511 PHYMOD_IF_ERR_RETURN 512 (blackhawk_tsc_display_diag_data(&phy_copy.access, SRDS_DIAG_CORE | SRDS_DIAG_LANE | SRDS_DIAG_EVENT)); 513 } 514 515 } else { 516 for (i = 0; i < num_lane; i++) { 517 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 518 continue; 519 } 520 phy_copy.access.lane_mask = 1 << (start_lane + i); 521 522 switch (cmd_type) { 523 case phymod_diag_CFG: 524 PHYMOD_DEBUG_ERROR((" %s:%d type = CFG\n", __func__, __LINE__)); 525 if(i==0) { 526 tmp_lane_mask = phy_copy.access.lane_mask; 527 phy_copy.access.lane_mask = 1; 528 PHYMOD_IF_ERR_RETURN 529 (blackhawk_tsc_display_core_config(&phy_copy.access)); 530 phy_copy.access.lane_mask = tmp_lane_mask; 531 } 532 PHYMOD_IF_ERR_RETURN 533 (blackhawk_tsc_display_lane_config(&phy_copy.access)); 534 break; 535 536 #if 0 537 casephymod_diag_CL72: 538 PHYMOD_DEBUG_ERROR((" %s:%d type = CL72\n", __func__, __LINE__)); 539 PHYMOD_IF_ERR_RETURN 540 (blackhawk_tsc_display_cl93n72_status(&phy_copy.access)); 541 break; 542 #endif 543 544 case phymod_diag_DEBUG: 545 PHYMOD_DEBUG_ERROR((" %s:%d type = DBG\n", __func__, __LINE__)); 546 PHYMOD_IF_ERR_RETURN 547 (blackhawk_tsc_display_lane_debug_status(&phy_copy.access)); 548 break; 549 550 case phymod_diag_BER: 551 PHYMOD_DEBUG_ERROR((" %s:%d type = BER\n", __func__, __LINE__)); 552 break; 553 554 /* 555 * COVERITY 556 * 557 * TEFMOD_DIAG_ALL branch involve information in TEFMOD_DIAG_STATE branch 558 */ 559 /* coverity[unterminated_case] */ 560 case phymod_diag_ALL: 561 PHYMOD_DEBUG_ERROR((" %s:%d type = CFG\n", __func__, __LINE__)); 562 if(i==0) { 563 tmp_lane_mask = phy_copy.access.lane_mask; 564 phy_copy.access.lane_mask = 1; 565 PHYMOD_IF_ERR_RETURN 566 (blackhawk_tsc_display_core_config(&phy_copy.access)); 567 phy_copy.access.lane_mask = tmp_lane_mask; 568 } 569 PHYMOD_IF_ERR_RETURN 570 (blackhawk_tsc_display_lane_config(&phy_copy.access)); 571 572 #if 0 573 PHYMOD_DEBUG_ERROR((" %s:%d type = CL72\n", __func__, __LINE__)); 574 PHYMOD_IF_ERR_RETURN 575 (blackhawk_tsc_display_cl93n72_status(&phy_copy.access)); 576 #endif 577 578 PHYMOD_DEBUG_ERROR((" %s:%d type = DBG\n", __func__, __LINE__)); 579 PHYMOD_IF_ERR_RETURN 580 (blackhawk_tsc_display_lane_debug_status(&phy_copy.access)); 581 break; 582 583 case phymod_diag_STATE: 584 default: 585 PHYMOD_DEBUG_ERROR((" %s:%d type = DEF\n", __func__, __LINE__)); 586 for (j = 0; j < 8; j++) { 587 phy_copy.access.lane_mask = 0x1 << j; 588 if (j==0){ 589 PHYMOD_IF_ERR_RETURN 590 (blackhawk_tsc_display_diag_data(&phy_copy.access, SRDS_DIAG_CORE | SRDS_DIAG_LANE | SRDS_DIAG_EVENT | SRDS_DIAG_REG_LANE | SRDS_DIAG_REG_CORE | SRDS_DIAG_UC_LANE | SRDS_DIAG_UC_CORE)); 591 } else { 592 PHYMOD_IF_ERR_RETURN 593 (blackhawk_tsc_display_diag_data(&phy_copy.access, SRDS_DIAG_LANE | SRDS_DIAG_EVENT | SRDS_DIAG_REG_LANE | SRDS_DIAG_UC_LANE )); 594 } 595 } 596 break; 597 } 598 } 599 } 600 return PHYMOD_E_NONE; 601 } 602 603 static void _blackhawk_diag_uc_reg_dump(phymod_access_t *pa) 604 { 605 err_code_t errc; 606 607 COMPILER_REFERENCE(errc); 608 609 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 610 PHYMOD_DIAG_OUT(("| MICRO CODE USR CTRL CONFIGURATION REGISTERS |\n")); 611 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 612 PHYMOD_DIAG_OUT(("| config_word [0x00]: 0x%04X |\n", blackhawk_tsc_rdwl_uc_var(pa,&errc,0x0))); 613 PHYMOD_DIAG_OUT(("| usr_misc_ctrl_word [0x04]: 0x%04X |\n", blackhawk_tsc_rdwl_uc_var(pa,&errc,0x4))); 614 PHYMOD_DIAG_OUT(("| retune_after_restart [0x06]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x6))); 615 PHYMOD_DIAG_OUT(("| clk90_offset_adjust [0x07]: 0x%04X |\n", blackhawk_tsc_rdbls_uc_var(pa,&errc,0x7))); 616 PHYMOD_DIAG_OUT(("| clk90_offset_override [0x08]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x8))); 617 PHYMOD_DIAG_OUT(("| lane_event_log_level [0x09]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x9))); 618 PHYMOD_DIAG_OUT(("| pam4_chn_loss [0x0A]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0xa))); 619 PHYMOD_DIAG_OUT(("| cl93n72_frc_byte [0x0B]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0xb))); 620 PHYMOD_DIAG_OUT(("| disable_startup [0x0C]: 0x%04X |\n", blackhawk_tsc_rdwl_uc_var(pa,&errc,0xc))); 621 PHYMOD_DIAG_OUT(("| disable_steady_state [0x0E]: 0x%04X |\n", blackhawk_tsc_rdwl_uc_var(pa,&errc,0xe))); 622 PHYMOD_DIAG_OUT(("| disable_startup_dfe [0x10]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x10))); 623 PHYMOD_DIAG_OUT(("| disable_steady_state_dfe [0x11]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x11))); 624 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 625 PHYMOD_DIAG_OUT(("| MICRO CODE USER STATUS REGISTERS |\n")); 626 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 627 PHYMOD_DIAG_OUT(("| restart_counter [0x12]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x12))); 628 PHYMOD_DIAG_OUT(("| reset_counter [0x13]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x13))); 629 PHYMOD_DIAG_OUT(("| pmd_lock_counter [0x14]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x14))); 630 PHYMOD_DIAG_OUT(("| heye_left [0x15]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x15))); 631 PHYMOD_DIAG_OUT(("| heye_right [0x16]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x16))); 632 PHYMOD_DIAG_OUT(("| veye_upper [0x17]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x17))); 633 PHYMOD_DIAG_OUT(("| veye_lower [0x18]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x18))); 634 PHYMOD_DIAG_OUT(("| micro_stopped [0x19]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x19))); 635 PHYMOD_DIAG_OUT(("| link_time [0x1C]: 0x%04X |\n", blackhawk_tsc_rdwl_uc_var(pa,&errc,0x1c))); 636 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 637 PHYMOD_DIAG_OUT(("| MICRO CODE MISC REGISTERS |\n")); 638 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 639 PHYMOD_DIAG_OUT(("| usr_diag_status [0x1E]: 0x%04X |\n", blackhawk_tsc_rdwl_uc_var(pa,&errc,0x1e))); 640 PHYMOD_DIAG_OUT(("| usr_diag_rd_ptr [0x20]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x20))); 641 PHYMOD_DIAG_OUT(("| usr_diag_mode [0x21]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x21))); 642 PHYMOD_DIAG_OUT(("| usr_main_tap_est [0x22]: 0x%04X |\n", blackhawk_tsc_rdwls_uc_var(pa,&errc,0x22))); 643 PHYMOD_DIAG_OUT(("| usr_sts_phase_hoffset [0x24]: 0x%04X |\n", blackhawk_tsc_rdbls_uc_var(pa,&errc,0x24))); 644 PHYMOD_DIAG_OUT(("| usr_diag_wr_ptr [0x25]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x25))); 645 PHYMOD_DIAG_OUT(("| status_byte [0x26]: 0x%04X |\n", blackhawk_tsc_rdbl_uc_var(pa,&errc,0x26))); 646 PHYMOD_DIAG_OUT(("+-------------------------------------------------+\n")); 647 } 648 649 STATIC int blackhawk_diagnostics_eyescan_run_uc(const phymod_phy_access_t* phy, uint32_t flags) 650 { 651 int rc = PHYMOD_E_NONE; 652 int j ; 653 phymod_phy_access_t phy_copy; 654 655 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 656 657 if(PHYMOD_EYESCAN_F_PROCESS_GET(flags)) { 658 for(j=0; j< PHYMOD_CONFIG_MAX_LANES_PER_CORE; j++) { /* Loop for all lanes. */ 659 if ((phy->access.lane_mask & (1<<j))==0) continue; 660 661 phy_copy.access.lane_mask = (phy->access.lane_mask & (1<<j)); 662 663 PHYMOD_DIAG_OUT(("\n\n\n")); 664 PHYMOD_DIAG_OUT((" +--------------------------------------------------------------------+\n")); 665 PHYMOD_DIAG_OUT((" | EYESCAN Phy: 0x%03x lane_mask: 0x%02x |\n", phy_copy.access.addr, phy_copy.access.lane_mask)); 666 PHYMOD_DIAG_OUT((" +--------------------------------------------------------------------+\n")); 667 668 rc = blackhawk_tsc_display_eye_scan(&(phy_copy.access)); 669 if(rc != PHYMOD_E_NONE) { 670 _blackhawk_diag_uc_reg_dump(&(phy_copy.access)); 671 PHYMOD_IF_ERR_RETURN(rc); 672 } 673 } 674 } 675 return PHYMOD_E_NONE; 676 } 677 678 int blackhawk_diagnostics_eye_margin_proj( const phymod_phy_access_t* phy, uint32_t flags, 679 const phymod_phy_eyescan_options_t* eyescan_options) 680 { 681 #ifdef SERDES_API_FLOATING_POINT 682 int osr_mode; 683 USR_DOUBLE data_rate, data_rate_in_Mhz; 684 phymod_phy_access_t phy_copy; 685 int start_lane, num_lane, i, found=0; 686 phymod_phy_speed_config_t speed_config; 687 688 struct blackhawk_tsc_uc_core_config_st core_cfg; 689 if(PHYMOD_EYESCAN_F_PROCESS_GET(flags)) { 690 PHYMOD_IF_ERR_RETURN 691 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 692 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 693 for (i = 0; i < num_lane; i++) { 694 phy_copy.access.lane_mask = 1 << (start_lane + i); 695 696 if (found == 0) { 697 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_get_uc_core_config(&(phy_copy.access), &core_cfg)); 698 PHYMOD_IF_ERR_RETURN(blackhawk_osr_mode_get(&phy_copy.access, &osr_mode)); 699 PHYMOD_IF_ERR_RETURN(phymod_phy_speed_config_t_init(&speed_config)); 700 PHYMOD_IF_ERR_RETURN(blackhawk_phy_speed_config_get(phy, &speed_config)); 701 data_rate = speed_config.data_rate * 1000.0 * 1000.0; 702 data_rate_in_Mhz = speed_config.data_rate; 703 found = 1; 704 } 705 if(num_lane > 1) { 706 PHYMOD_DIAG_OUT((" l=%0d, baud rate = %fMB/s \n", i, data_rate_in_Mhz)); 707 } else { 708 PHYMOD_DIAG_OUT((" baud rate = %fMB/s \n", data_rate_in_Mhz)); 709 } 710 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_eye_margin_proj(&phy_copy.access, data_rate, eyescan_options->ber_proj_scan_mode, 711 eyescan_options->ber_proj_timer_cnt, eyescan_options->ber_proj_err_cnt)); 712 } 713 } 714 #else 715 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("BER Proj is supported with SERDES_API_FLOATING_POINT only\n"))); 716 #endif 717 718 return PHYMOD_E_NONE; 719 } 720 721 int blackhawk_phy_eyescan_run(const phymod_phy_access_t* phy, 722 uint32_t flags, 723 phymod_eyescan_mode_t mode, 724 const phymod_phy_eyescan_options_t* eyescan_options) 725 { 726 uint8_t pmd_rx_lock=0; 727 phymod_phy_access_t phy_copy; 728 729 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 730 731 PHYMOD_IF_ERR_RETURN 732 (blackhawk_tsc_pmd_lock_status(&phy_copy.access, &pmd_rx_lock)); 733 734 if(pmd_rx_lock == 0) { 735 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("Can not get eyescan when pmd_rx is not locked\n"))); 736 } 737 738 /* If stage isn't set - perform all stages*/ 739 if(!PHYMOD_EYESCAN_F_ENABLE_GET(flags) 740 && !PHYMOD_EYESCAN_F_PROCESS_GET(flags) 741 && !PHYMOD_EYESCAN_F_DONE_GET(flags)) 742 { 743 PHYMOD_EYESCAN_F_ENABLE_SET(flags); 744 PHYMOD_EYESCAN_F_PROCESS_SET(flags); 745 PHYMOD_EYESCAN_F_DONE_SET(flags); 746 } 747 748 /* mode phymodEyescanModeBERProj gives BER projection */ 749 switch(mode) { 750 case phymodEyescanModeFast: 751 return blackhawk_diagnostics_eyescan_run_uc(phy, flags); 752 case phymodEyescanModeBERProj: 753 return blackhawk_diagnostics_eye_margin_proj(phy, flags, eyescan_options); 754 default: 755 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, (_PHYMOD_MSG("unsupported eyescan mode %u"), mode)); 756 } 757 758 return PHYMOD_E_NONE; 759 } 760 761 int blackhawk_phy_PAM4_tx_pattern_enable_set(const phymod_phy_access_t* phy, phymod_PAM4_tx_pattern_t pattern_type, uint32_t enable) 762 { 763 phymod_phy_access_t phy_copy; 764 765 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 766 767 switch (pattern_type) { 768 case phymod_PAM4TxPattern_JP03B: 769 PHYMOD_IF_ERR_RETURN 770 (blackhawk_tsc_config_tx_jp03b_pattern(&phy_copy.access, (uint8_t) enable)); 771 break; 772 case phymod_PAM4TxPattern_Linear: 773 PHYMOD_IF_ERR_RETURN 774 (blackhawk_tsc_config_tx_linearity_pattern(&phy_copy.access, (uint8_t) enable)); 775 break; 776 default: 777 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, (_PHYMOD_MSG("unsupported PAM4 tx pattern %u"), pattern_type)); 778 } 779 return PHYMOD_E_NONE; 780 781 } 782 783 int blackhawk_phy_PAM4_tx_pattern_enable_get(const phymod_phy_access_t* phy, phymod_PAM4_tx_pattern_t pattern_type, uint32_t* enable) 784 { 785 phymod_phy_access_t phy_copy; 786 787 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 788 789 PHYMOD_IF_ERR_RETURN 790 (blackhawk_tsc_pam4_tx_pattern_enable_get(&phy_copy.access, pattern_type, enable)); 791 return PHYMOD_E_NONE; 792 793 } 794 795 int _blackhawk_phy_post_fec_ber_proj(const phymod_phy_access_t* phy, const phymod_phy_ber_proj_options_t* options) 796 { 797 phymod_phy_access_t phy_copy; 798 uint8_t default_hist_errcnt_thresh = 1; 799 uint8_t default_prbs_errcnt_thresh; 800 uint8_t hist_errcnt_thresh = 0, prbs_errcnt_thresh = 0; 801 int timeout_s; 802 blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer; 803 int start_lane, num_lane, i; 804 805 PHYMOD_IF_ERR_RETURN(phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 806 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 807 808 switch (options->ber_proj_phase) { 809 case PHYMOD_BER_PROJ_PHASE_F_PRE: 810 /* This is pre-config stage. Only needed when 811 * options->ber_proj_hist_errcnt_thresh == 0. 812 */ 813 if (options->ber_proj_fec_size == 0) { 814 /* If user use unsupported FEC type, Portmod will set fec_size to 0. 815 * So here we check whether fec_size equals to 0. If so, return error. 816 */ 817 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, 818 (_PHYMOD_MSG("Unsupported FEC type for Post FEC BER Projection."))); 819 } 820 821 default_prbs_errcnt_thresh = default_hist_errcnt_thresh + 8; 822 for (i = 0; i < num_lane; i++) { 823 phy_copy.access.lane_mask = 1 << (start_lane + i); 824 /* Configure PRBS Error Analyzer */ 825 PHYMOD_IF_ERR_RETURN 826 (blackhawk_tsc_prbs_error_analyzer_config(&phy_copy.access, 827 options->ber_proj_fec_size, 828 default_prbs_errcnt_thresh, 829 default_hist_errcnt_thresh)); 830 } 831 break; 832 case PHYMOD_BER_PROJ_PHASE_F_CONFIG: 833 if (options->ber_proj_fec_size == 0) { 834 /* If user use unsupported FEC type, Portmod will set fec_size to 0. 835 * So here we check whether fec_size equals to 0. If so, return error. 836 */ 837 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, (_PHYMOD_MSG("Unsupported FEC type for Post FEC BER Projection."))); 838 } 839 /* PLP team recommend 5% proj_timeout value as the timeout_s to get optimized thershold */ 840 /* 99 is used to generate CEIL function of 5% of timeout_s */ 841 timeout_s = (options->ber_proj_timeout_s * 5 + 99)/ 100; 842 843 for (i = 0; i < num_lane; i++) { 844 phy_copy.access.lane_mask = 1 << (start_lane + i); 845 PHYMOD_DIAG_OUT(("\nConfigure PRBS Error Analyzer: Phy: 0x%03x, Lane: 0x%01x", phy->access.addr, start_lane+i)); 846 if ((options->ber_proj_hist_errcnt_thresh == 0)) { 847 PHYMOD_DIAG_OUT(("\n------------------------------------------------------------------------------------------------\n")); 848 /* Use optimized Hist_Errcnt_Threshold */ 849 /* Initialize err cnt */ 850 PHYMOD_MEMSET(&err_analyzer, 0, sizeof(blackhawk_tsc_prbs_err_analyzer_errcnt_st)); 851 /* Get the error count */ 852 PHYMOD_IF_ERR_RETURN 853 (blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(&phy_copy.access, &err_analyzer)); 854 /* Get the optimized hist errcnt threshold. */ 855 PHYMOD_IF_ERR_RETURN 856 (blackhawk_tsc_optimize_hist_errcnt_thresh(&phy_copy.access, 857 &err_analyzer, 858 timeout_s, 859 options->ber_proj_timeout_s)); 860 hist_errcnt_thresh = err_analyzer.hist_errcnt_thresh; 861 PHYMOD_DIAG_OUT(("------------------------------------------------------------------------------------------------\n")); 862 } else if (options->ber_proj_hist_errcnt_thresh > 7) { 863 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, (_PHYMOD_MSG("hist_errcnt_threshold is out of range. Valid range is [1,7]."))); 864 } else { 865 hist_errcnt_thresh = options->ber_proj_hist_errcnt_thresh; 866 } 867 prbs_errcnt_thresh = hist_errcnt_thresh + 8; 868 PHYMOD_IF_ERR_RETURN 869 (blackhawk_tsc_prbs_error_analyzer_config(&phy_copy.access, 870 options->ber_proj_fec_size, 871 prbs_errcnt_thresh, 872 hist_errcnt_thresh)); 873 PHYMOD_IF_ERR_RETURN 874 (blackhawk_tsc_display_prbs_error_analyzer_config(&phy_copy.access, prbs_errcnt_thresh, hist_errcnt_thresh, options->ber_proj_timeout_s)); 875 } 876 break; 877 case PHYMOD_BER_PROJ_PHASE_F_START: 878 for (i = 0; i < num_lane; i++) { 879 phy_copy.access.lane_mask = 1 << (start_lane + i); 880 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_error_analyzer_status_clear(&phy_copy.access)); 881 } 882 break; 883 case PHYMOD_BER_PROJ_PHASE_F_COLLECT: 884 for (i = 0; i < num_lane; i++) { 885 phy_copy.access.lane_mask = 1 << (start_lane + i); 886 PHYMOD_MEMSET(&err_analyzer, 0, sizeof(blackhawk_tsc_prbs_err_analyzer_errcnt_st)); 887 PHYMOD_MEMCPY(err_analyzer.prbs_errcnt, options->ber_proj_prbs_errcnt[i].prbs_errcnt, sizeof(err_analyzer.prbs_errcnt)); 888 PHYMOD_IF_ERR_RETURN( 889 blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(&phy_copy.access, &err_analyzer)); 890 PHYMOD_MEMCPY(options->ber_proj_prbs_errcnt[i].prbs_errcnt, err_analyzer.prbs_errcnt, sizeof(err_analyzer.prbs_errcnt)); 891 } 892 break; 893 case PHYMOD_BER_PROJ_PHASE_F_CAL: 894 for (i = 0; i < num_lane; i++) { 895 phy_copy.access.lane_mask = 1 << (start_lane + i); 896 PHYMOD_MEMSET(&err_analyzer, 0, sizeof(blackhawk_tsc_prbs_err_analyzer_errcnt_st)); 897 if ((options->ber_proj_hist_errcnt_thresh == 0)) { 898 PHYMOD_IF_ERR_RETURN( 899 blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(&phy_copy.access, &err_analyzer)); 900 } else { 901 err_analyzer.hist_errcnt_thresh = options->ber_proj_hist_errcnt_thresh; 902 err_analyzer.prbs_errcnt_thresh = options->ber_proj_hist_errcnt_thresh + 8; 903 } 904 PHYMOD_MEMCPY(err_analyzer.prbs_errcnt, options->ber_proj_prbs_errcnt[i].prbs_errcnt, sizeof(err_analyzer.prbs_errcnt)); 905 PHYMOD_DIAG_OUT(("\nPost-FEC BER: Phy: 0x%03x, Lane: 0x%01x", phy->access.addr, start_lane+i)); 906 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_display_prbs_error_analyzer_err_count(&phy_copy.access, err_analyzer)); 907 PHYMOD_IF_ERR_RETURN( 908 blackhawk_tsc_prbs_error_analyzer_compute_proj(&phy_copy.access, err_analyzer, options->ber_proj_timeout_s)); 909 } 910 break; 911 default: 912 return PHYMOD_E_PARAM; 913 } 914 return PHYMOD_E_NONE; 915 } 916 917 /* BER Projection*/ 918 int blackhawk_phy_ber_proj(const phymod_phy_access_t* phy, phymod_ber_proj_mode_t mode, const phymod_phy_ber_proj_options_t* options) 919 { 920 switch (mode) { 921 case phymodBERProjModePostFEC: 922 PHYMOD_IF_ERR_RETURN(_blackhawk_phy_post_fec_ber_proj(phy, options)); 923 break; 924 default: 925 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_PARAM, (_PHYMOD_MSG("unsupported BER PROJECTION mode %u"), mode)); 926 } 927 return PHYMOD_E_NONE; 928 } 929 930 /* fast BER Projection get*/ 931 int blackhawk_phy_fast_ber_proj_get(const phymod_phy_access_t* phy, uint32_t* ber_proj_data) 932 { 933 struct ber_data_st ber_data_local; 934 int start_lane, num_lane; 935 phymod_phy_access_t phy_copy; 936 937 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 938 939 /* next figure out the lane num and start_lane based on the input */ 940 PHYMOD_IF_ERR_RETURN 941 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 942 943 phy_copy.access.lane_mask = 0x1 << start_lane; 944 945 /* collect prbs in 100 ms */ 946 PHYMOD_IF_ERR_RETURN 947 (blackhawk_tsc_INTERNAL_get_BER_data(&phy_copy.access, 100, &ber_data_local, 0)); 948 949 /* first check if PRBS enabled or prbs lost lock */ 950 if ((ber_data_local.prbs_chk_en == 0) || (ber_data_local.lcklost == 1)) { 951 *ber_proj_data = 0xffffffff; 952 } else { 953 uint16_t x = 0,y = 0,z = 0,div; 954 955 if (COMPILER_64_GE(ber_data_local.num_errs, ber_data_local.num_bits)) { 956 x = 1; 957 y = 0; 958 z = 0; 959 } else { 960 uint64_t tmp_num_errs, tmp_num_bits, tmp_div; 961 while (1) { 962 /* 963 * div = (uint16_t)(((ber_data_local.num_errs<<1) + ber_data_local.num_bits)/(ber_data_local.num_bits<<1)); 964 */ 965 COMPILER_64_COPY(tmp_num_errs, ber_data_local.num_errs); 966 COMPILER_64_COPY(tmp_num_bits, ber_data_local.num_bits); 967 968 /* first check if the number of error is 0 or the error is too small */ 969 if (COMPILER_64_IS_ZERO(tmp_num_errs) || (z > 40)) { 970 /* the prbs error count is too small to have a meaningful estimate, return 0 */ 971 *ber_proj_data = 0; 972 return PHYMOD_E_NONE; 973 } 974 /* ber_data_local.num_errs << 1 */ 975 COMPILER_64_SHL(tmp_num_errs, 1); 976 977 /* (ber_data_local.num_errs << 1) + ber_data_local.num_bits */ 978 COMPILER_64_ADD_64(tmp_num_errs, ber_data_local.num_bits); 979 980 /* ber_data_local.num_bits << 1 */ 981 COMPILER_64_SHL(tmp_num_bits, 1); 982 983 COMPILER_64_COPY(tmp_div, tmp_num_errs); 984 COMPILER_64_UDIV_64(tmp_div, tmp_num_bits); 985 div = (uint16_t)(COMPILER_64_LO(tmp_div)); 986 987 if (div >= 10) break; 988 /* 989 * ber_data_local.num_errs = ber_data_local.num_errs*10; 990 */ 991 COMPILER_64_UMUL_32(ber_data_local.num_errs, (uint32_t) 10); 992 z = z + 1; 993 } 994 if(div >= 100) { 995 div = div / 10; 996 z = z - 1; 997 } 998 x = div / 10; 999 y = div - 10 * x; 1000 z = z - 1; 1001 } 1002 *ber_proj_data = x << 24 | y << 16 | z; 1003 } 1004 1005 return PHYMOD_E_NONE; 1006 } 1007 1008 1009 #endif /* PHYMOD_BLACKHAWK_SUPPORT */