blackhawk_tsc_prbs.c (52461B)
1 /************************************************************************************** 2 ************************************************************************************** 3 * File Name : blackhawk_tsc_prbs.c * 4 * Created On : 04 Nov 2015 * 5 * Created By : Brent Roberts * 6 * Description : APIs for Serdes IPs * 7 * Revision : * 8 * * 9 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 10 * 11 * Copyright 2007-2019 Broadcom Inc. All rights reserved. * 12 * No portions of this material may be reproduced in any form without * 13 * the written permission of: * 14 * Broadcom Corporation * 15 * 5300 California Avenue * 16 * Irvine, CA 92617 * 17 * * 18 * All information contained in this document is Broadcom Corporation * 19 * company private proprietary, and trade secret. * 20 */ 21 22 /** @file blackhawk_tsc_prbs.c 23 * Implementation of API PRBS functions 24 */ 25 #ifdef EXCLUDE_STD_HEADERS 26 #include <stdio.h> 27 #include <math.h> 28 #endif 29 30 #include <phymod/phymod_system.h> 31 #include "blackhawk_tsc_prbs.h" 32 #include "blackhawk_tsc_common.h" 33 #include "blackhawk_tsc_dependencies.h" 34 #include "blackhawk_tsc_functions.h" 35 #include "blackhawk_tsc_internal.h" 36 #include "blackhawk_tsc_internal_error.h" 37 #include "blackhawk_tsc_select_defns.h" 38 #include "blackhawk_tsc_access.h" 39 40 #ifdef SERDES_API_FLOATING_POINT 41 #include <math.h> 42 #endif 43 44 /******************************/ 45 /* TX Pattern Generator APIs */ 46 /******************************/ 47 48 /* Cofigure shared TX Pattern (Return Val = 0:PASS, 1-6:FAIL (reports 6 possible error scenarios if failed)) */ 49 err_code_t blackhawk_tsc_config_shared_tx_pattern(srds_access_t *sa__, uint8_t patt_length, const char pattern[]) { 50 51 char patt_final[245] = ""; 52 char patt_mod[245] = "", bin[5] = ""; 53 uint8_t str_len, i, k, j = 0; 54 uint8_t offset_len, actual_patt_len = 0, hex = 0; 55 uint8_t zero_pad_len = 0; /* suppress warnings, changed by blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel() */ 56 uint16_t patt_gen_wr_val = 0; 57 uint8_t mode_sel = 0; /* suppress warnings, changed by blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel() */ 58 59 EFUN(blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel(sa__, &mode_sel,&zero_pad_len,patt_length)); 60 61 /* Generating the appropriate write value to patt_gen_seq registers */ 62 str_len = (int8_t)USR_STRLEN(pattern); 63 64 if ((str_len > 2) && ((USR_STRNCMP(pattern, "0x", 2)) == 0)) { 65 /* Hexadecimal Pattern */ 66 for (i=2; i < str_len; i++) { 67 if (pattern[i] != '_') { 68 EFUN(blackhawk_tsc_INTERNAL_compute_bin(sa__, pattern[i],bin)); 69 ENULL_STRNCAT(patt_mod, bin, 4); 70 actual_patt_len = actual_patt_len + 4; 71 if (actual_patt_len > 240) { 72 EFUN_PRINTF(("ERROR: Pattern bigger than max pattern length\n")); 73 return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_PATTERN_BIGGER_THAN_MAXLEN)); 74 } 75 } 76 } 77 78 offset_len = (actual_patt_len - patt_length); 79 if ((offset_len > 3) || (actual_patt_len < patt_length)) { 80 EFUN_PRINTF(("ERROR: Pattern length provided does not match the hexadecimal pattern provided\n")); 81 return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_LEN_MISMATCH)); 82 } 83 else if (offset_len) { 84 for (i=0; i < offset_len; i++) { 85 if (patt_mod[i] != '0') { 86 EFUN_PRINTF(("ERROR: Pattern length provided does not match the hexadecimal pattern provided\n")); 87 return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_LEN_MISMATCH)); 88 } 89 } 90 for (i=offset_len; i <= actual_patt_len; i++) { 91 patt_mod[i - offset_len] = patt_mod[i]; 92 } 93 } 94 } 95 else if ((str_len > 1) && ((USR_STRNCMP(pattern, "p", 1)) == 0)) { 96 /* PAM4 Pattern */ 97 for (i=1; i < str_len; i++) { 98 if (pattern[i] != '_') { 99 EFUN(blackhawk_tsc_INTERNAL_pam4_to_bin(sa__, pattern[i],bin)); 100 ENULL_STRNCAT(patt_mod, bin, 2); 101 actual_patt_len = actual_patt_len + 2; 102 if (actual_patt_len > 240) { 103 EFUN_PRINTF(("ERROR: Pattern bigger than max pattern length\n")); 104 return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_PATTERN_BIGGER_THAN_MAXLEN)); 105 } 106 } 107 } 108 109 offset_len = (actual_patt_len - patt_length); 110 if ((offset_len > 3) || (actual_patt_len < patt_length)) { 111 EFUN_PRINTF(("ERROR: Pattern length provided does not match the PAM4 pattern provided\n")); 112 return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_LEN_MISMATCH)); 113 } 114 else if (offset_len) { 115 for (i=0; i < offset_len; i++) { 116 if (patt_mod[i] != '0') { 117 EFUN_PRINTF(("ERROR: Pattern length provided does not match the PAM4 pattern provided\n")); 118 return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_LEN_MISMATCH)); 119 } 120 } 121 for (i=offset_len; i <= actual_patt_len; i++) { 122 patt_mod[i - offset_len] = patt_mod[i]; 123 } 124 } 125 } 126 else { 127 /* Binary Pattern */ 128 for (i=0; i < str_len; i++) { 129 if ((pattern[i] == '0') || (pattern[i] == '1')) { 130 bin[0] = pattern[i]; 131 bin[1] = '\0'; 132 ENULL_STRNCAT(patt_mod, bin, 1); 133 actual_patt_len++; 134 if (actual_patt_len > 240) { 135 EFUN_PRINTF(("ERROR: Pattern bigger than max pattern length\n")); 136 return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_PATTERN_BIGGER_THAN_MAXLEN)); 137 } 138 } 139 else if (pattern[i] != '_') { 140 EFUN_PRINTF(("ERROR: Invalid input Pattern\n")); 141 return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_INVALID_PATTERN)); 142 } 143 } 144 145 if (actual_patt_len != patt_length) { 146 EFUN_PRINTF(("ERROR: Pattern length provided does not match the binary pattern provided\n")); 147 return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_LEN_MISMATCH)); 148 } 149 } 150 151 /* Zero padding upper bits and concatinating patt_mod to form patt_final */ 152 for (i=0; i < zero_pad_len; i++) { 153 ENULL_STRNCAT(patt_final, "0", 1); 154 j++; 155 } 156 for (i=zero_pad_len; i + patt_length < 241; i = i + patt_length) { 157 ENULL_STRNCAT(patt_final, patt_mod, patt_length); 158 j++; 159 } 160 161 /* EFUN_PRINTF(("\nFinal Pattern = %s\n\n",patt_final)); */ 162 163 for (i=0; i < 15; i++) { 164 165 for (j=0; j < 4; j++) { 166 k = i*16 + j*4; 167 bin[0] = patt_final[k]; 168 bin[1] = patt_final[k+1]; 169 bin[2] = patt_final[k+2]; 170 bin[3] = patt_final[k+3]; 171 bin[4] = '\0'; 172 EFUN(blackhawk_tsc_INTERNAL_compute_hex(sa__, bin, &hex)); 173 patt_gen_wr_val = ((patt_gen_wr_val << 4) | hex); 174 } 175 /* EFUN_PRINTF(("patt_gen_wr_val[%d] = 0x%x\n",(14-i),patt_gen_wr_val)); */ 176 177 /* Writing to apprpriate patt_gen_seq Registers */ 178 switch (i) { 179 case 0: EFUN(wrc_patt_gen_seq_14(patt_gen_wr_val)); 180 break; 181 case 1: EFUN(wrc_patt_gen_seq_13(patt_gen_wr_val)); 182 break; 183 case 2: EFUN(wrc_patt_gen_seq_12(patt_gen_wr_val)); 184 break; 185 case 3: EFUN(wrc_patt_gen_seq_11(patt_gen_wr_val)); 186 break; 187 case 4: EFUN(wrc_patt_gen_seq_10(patt_gen_wr_val)); 188 break; 189 case 5: EFUN(wrc_patt_gen_seq_9(patt_gen_wr_val)); 190 break; 191 case 6: EFUN(wrc_patt_gen_seq_8(patt_gen_wr_val)); 192 break; 193 case 7: EFUN(wrc_patt_gen_seq_7(patt_gen_wr_val)); 194 break; 195 case 8: EFUN(wrc_patt_gen_seq_6(patt_gen_wr_val)); 196 break; 197 case 9: EFUN(wrc_patt_gen_seq_5(patt_gen_wr_val)); 198 break; 199 case 10: EFUN(wrc_patt_gen_seq_4(patt_gen_wr_val)); 200 break; 201 case 11: EFUN(wrc_patt_gen_seq_3(patt_gen_wr_val)); 202 break; 203 case 12: EFUN(wrc_patt_gen_seq_2(patt_gen_wr_val)); 204 break; 205 case 13: EFUN(wrc_patt_gen_seq_1(patt_gen_wr_val)); 206 break; 207 case 14: EFUN(wrc_patt_gen_seq_0(patt_gen_wr_val)); 208 break; 209 default: EFUN_PRINTF(("ERROR: Invalid write to patt_gen_seq register\n")); 210 return (blackhawk_tsc_error(sa__, ERR_CODE_CFG_PATT_INVALID_SEQ_WRITE)); 211 } 212 } 213 214 /* Pattern Generator Mode Select */ 215 /* EFUN(wr_patt_gen_mode_sel(mode_sel)); */ 216 /* EFUN_PRINTF(("Pattern gen Mode = %d\n",mode)); */ 217 218 /* Enable Fixed pattern Generation */ 219 /* EFUN(wr_patt_gen_en(0x1)); */ 220 return(ERR_CODE_NONE); 221 } 222 223 224 /* Enable/Disable Shared TX pattern generator */ 225 err_code_t blackhawk_tsc_tx_shared_patt_gen_en(srds_access_t *sa__, uint8_t enable, uint8_t patt_length) { 226 uint8_t zero_pad_len = 0; /* suppress warnings, changed by blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel() */ 227 uint8_t mode_sel = 0; /* suppress warnings, changed by blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel() */ 228 229 EFUN(blackhawk_tsc_INTERNAL_calc_patt_gen_mode_sel(sa__, &mode_sel,&zero_pad_len,patt_length)); 230 231 if (enable) { 232 if ((mode_sel < 1) || (mode_sel > 6)) { 233 return (blackhawk_tsc_error(sa__, ERR_CODE_PATT_GEN_INVALID_MODE_SEL)); 234 } 235 mode_sel = (12 - mode_sel); 236 EFUN(wr_patt_gen_start_pos(mode_sel)); /* Start position for pattern */ 237 EFUN(wr_patt_gen_stop_pos(0x0)); /* Stop position for pattern */ 238 EFUN(wr_patt_gen_en(0x1)); /* Enable Fixed pattern Generation */ 239 } 240 else { 241 EFUN(wr_patt_gen_en(0x0)); /* Disable Fixed pattern Generation */ 242 } 243 return(ERR_CODE_NONE); 244 } 245 246 /* Configure JP03B Pattern */ 247 err_code_t blackhawk_tsc_config_tx_jp03b_pattern(srds_access_t *sa__, uint8_t enable) { 248 249 if (enable) { 250 /* JP03B Pattern - "p0330" => 8'b_0011_1100 or 8'h3C w/o Gray coding */ 251 /* => 8'b_0010_1000 or 8'h28 with Gray coding */ 252 EFUN(wrc_patt_gen_seq_1(0x2800)); 253 EFUN(wr_pam4_precoder_en(0x0)); 254 EFUN(wr_pam4_gray_enc_en(0x0)); 255 EFUN(wr_pam4_tx_jp03b_patt_en(0x1)); 256 EFUN(wr_patt_gen_en(0x1)); 257 } 258 else { 259 EFUN(wr_patt_gen_en(0x0)); 260 EFUN(wr_pam4_tx_jp03b_patt_en(0x0)); 261 } 262 return(ERR_CODE_NONE); 263 } 264 265 266 /* Configure TX Linearity Pattern */ 267 err_code_t blackhawk_tsc_config_tx_linearity_pattern(srds_access_t *sa__, uint8_t enable) { 268 269 if (enable) { 270 /* Linearity Pattern - "p0123_0303_21" => 20'b_0001_1011_0011_0011_1001 or 20'h1B339 w/o Gray coding */ 271 /* => 20'b_0001_1110_0010_0010_1101 or 20'h1E22D with Gray coding */ 272 EFUN(wrc_patt_gen_seq_0(0xE22D)); 273 EFUN(wrc_patt_gen_seq_1(0x0001)); 274 EFUN(wr_pam4_precoder_en(0x0)); 275 EFUN(wr_pam4_gray_enc_en(0x0)); 276 EFUN(wr_pam4_tx_jp03b_patt_en(0x0)); 277 EFUN(wr_pam4_tx_linearity_patt_en(0x1)); 278 EFUN(wr_patt_gen_en(0x1)); 279 } 280 else { 281 EFUN(wr_patt_gen_en(0x0)); 282 EFUN(wr_pam4_tx_linearity_patt_en(0x0)); 283 } 284 return(ERR_CODE_NONE); 285 } 286 287 /**************************************/ 288 /* PRBS Generator/Checker Functions */ 289 /**************************************/ 290 291 /* Configure PRBS Generator */ 292 err_code_t blackhawk_tsc_config_tx_prbs(srds_access_t *sa__, enum srds_prbs_polynomial_enum prbs_poly_mode, uint8_t prbs_inv) { 293 uint8_t poly_mode_lsb; 294 poly_mode_lsb = prbs_poly_mode & 0x7; 295 296 EFUN(wr_prbs_gen_mode_sel((uint8_t)poly_mode_lsb)); /* PRBS Generator mode sel */ 297 EFUN(wr_prbs_gen_mode_sel_msb(prbs_poly_mode > 7)); /* Set MSB for new Poly mode selections */ 298 EFUN(wr_prbs_gen_inv(prbs_inv)); /* PRBS Invert Enable/Disable */ 299 /* To enable PRBS Generator */ 300 /* EFUN(wr_prbs_gen_en(0x1)); */ 301 return (ERR_CODE_NONE); 302 } 303 304 err_code_t blackhawk_tsc_get_tx_prbs_config(srds_access_t *sa__, enum srds_prbs_polynomial_enum *prbs_poly_mode, uint8_t *prbs_inv) { 305 uint8_t val; 306 307 ESTM(val = rd_prbs_gen_mode_sel()); /* PRBS Generator mode sel */ 308 ESTM(val += (rd_prbs_gen_mode_sel_msb())?8:0); /* Add the MSB for mode_sel */ 309 *prbs_poly_mode = (enum srds_prbs_polynomial_enum)val; 310 ESTM(val = rd_prbs_gen_inv()); /* PRBS Invert Enable/Disable */ 311 *prbs_inv = val; 312 313 return (ERR_CODE_NONE); 314 } 315 316 /* PRBS Generator Enable/Disable */ 317 err_code_t blackhawk_tsc_tx_prbs_en(srds_access_t *sa__, uint8_t enable) { 318 319 if (enable) { 320 EFUN(wr_prbs_gen_en(0x1)); /* Enable PRBS Generator */ 321 } 322 else { 323 EFUN(wr_prbs_gen_en(0x0)); /* Disable PRBS Generator */ 324 } 325 return (ERR_CODE_NONE); 326 } 327 328 /* Get PRBS Generator Enable/Disable */ 329 err_code_t blackhawk_tsc_get_tx_prbs_en(srds_access_t *sa__, uint8_t *enable) { 330 331 ESTM(*enable = rd_prbs_gen_en()); 332 333 return (ERR_CODE_NONE); 334 } 335 336 /* PRBS 1-bit error injection */ 337 err_code_t blackhawk_tsc_tx_prbs_err_inject(srds_access_t *sa__, uint8_t enable) { 338 /* PRBS Error Insert. 339 0 to 1 transition on this signal will insert single bit error in the MSB bit of the data bus. 340 Reset value is 0x0. 341 */ 342 if(enable) 343 EFUN(wr_prbs_gen_err_ins(0x1)); 344 EFUN(wr_prbs_gen_err_ins(0)); 345 return (ERR_CODE_NONE); 346 } 347 348 /* Configure PRBS Checker */ 349 err_code_t blackhawk_tsc_config_rx_prbs(srds_access_t *sa__, enum srds_prbs_polynomial_enum prbs_poly_mode, enum srds_prbs_checker_mode_enum prbs_checker_mode, uint8_t prbs_inv) { 350 uint8_t dig_lpbk = 0; 351 if (prbs_poly_mode == PRBS_AUTO_DETECT) { 352 EFUN(wr_prbs_chk_auto_detect_en(0x1)); /* Enable PRBS checker Auto-Detect */ 353 EFUN(wr_prbs_chk_mode(PRBS_INITIAL_SEED_HYSTERESIS)); /* PRBS Checker mode sel (PRBS LOCK state machine select) */ 354 } 355 else { 356 uint8_t poly_mode_lsb; 357 poly_mode_lsb = prbs_poly_mode & 0x7; 358 359 EFUN(wr_prbs_chk_mode_sel((uint8_t)poly_mode_lsb)); /* PRBS Checker Polynomial mode sel */ 360 EFUN(wr_prbs_chk_mode((uint8_t)prbs_checker_mode)); /* PRBS Checker mode sel (PRBS LOCK state machine select) */ 361 ESTM(dig_lpbk = rd_dig_lpbk_en()); 362 if(dig_lpbk == 0) { 363 /* Only enable auto mode in non-digital loop-back mode */ 364 EFUN(wr_prbs_chk_en_auto_mode(0x1)); /* PRBS Checker enable control - rx_dsc_lock & prbs_chk_en */ 365 } 366 EFUN(wr_prbs_chk_inv(prbs_inv)); /* PRBS Invert Enable/Disable */ 367 EFUN(wr_prbs_chk_mode_sel_msb(prbs_poly_mode > 7)); /* Set MSB for new Poly mode selections */ 368 EFUN(wr_prbs_chk_auto_detect_en(0x0)); /* Disable PRBS checker Auto-Detect */ 369 } 370 /* To enable PRBS Checker */ 371 /* EFUN(wr_prbs_chk_en(0x1)); */ 372 return (ERR_CODE_NONE); 373 } 374 375 /* get PRBS Checker */ 376 err_code_t blackhawk_tsc_get_rx_prbs_config(srds_access_t *sa__, enum srds_prbs_polynomial_enum *prbs_poly_mode, enum srds_prbs_checker_mode_enum *prbs_checker_mode, uint8_t *prbs_inv) { 377 uint8_t val; 378 379 uint8_t auto_det_en; 380 ESTM(auto_det_en = rd_prbs_chk_auto_detect_en()); /* PRBS checker Auto-Detect Enable */ 381 if (auto_det_en) { 382 uint8_t auto_det_lock; 383 ESTM(auto_det_lock = rd_prbs_chk_auto_detect_lock()); /* PRBS checker Auto-Detect Lock */ 384 if (auto_det_lock) { 385 ESTM(val = rd_prbs_chk_mode_sel_auto_detect()); /* PRBS Auto-Detect Checker Polynomial mode sel */ 386 ESTM(val += (rd_prbs_chk_mode_sel_msb_auto_detect())? 8:0); /* Add the MSB for Auto-Detect mode_sel */ 387 *prbs_poly_mode = (enum srds_prbs_polynomial_enum)val; 388 389 ESTM(val = rd_prbs_chk_mode()); /* PRBS Checker mode sel (PRBS LOCK state machine select) */ 390 *prbs_checker_mode = (enum srds_prbs_checker_mode_enum)val; 391 ESTM(val = rd_prbs_chk_inv_auto_detect()); /* PRBS Invert Enable/Disable */ 392 *prbs_inv = val; 393 } 394 else { 395 *prbs_poly_mode = PRBS_UNKNOWN; 396 *prbs_inv = 0; 397 ESTM(val = rd_prbs_chk_mode()); /* PRBS Checker mode sel (PRBS LOCK state machine select) */ 398 *prbs_checker_mode = (enum srds_prbs_checker_mode_enum)val; 399 } 400 } 401 else { 402 ESTM(val = rd_prbs_chk_mode_sel()); /* PRBS Checker Polynomial mode sel */ 403 ESTM(val += (rd_prbs_chk_mode_sel_msb())? 8:0); /* Add the MSB for mode_sel */ 404 *prbs_poly_mode = (enum srds_prbs_polynomial_enum)val; 405 406 ESTM(val = rd_prbs_chk_mode()); /* PRBS Checker mode sel (PRBS LOCK state machine select) */ 407 *prbs_checker_mode = (enum srds_prbs_checker_mode_enum)val; 408 ESTM(val = rd_prbs_chk_inv()); /* PRBS Invert Enable/Disable */ 409 *prbs_inv = val; 410 } 411 return (ERR_CODE_NONE); 412 } 413 414 /* PRBS Checker Enable/Disable */ 415 err_code_t blackhawk_tsc_rx_prbs_en(srds_access_t *sa__, uint8_t enable) { 416 417 if (enable) { 418 EFUN(wr_prbs_chk_en(0x1)); /* Enable PRBS Checker */ 419 } 420 else { 421 EFUN(wr_prbs_chk_en(0x0)); /* Disable PRBS Checker */ 422 } 423 return (ERR_CODE_NONE); 424 } 425 426 err_code_t blackhawk_tsc_get_rx_prbs_en(srds_access_t *sa__, uint8_t *enable) { 427 428 ESTM(*enable = rd_prbs_chk_en()); 429 return (ERR_CODE_NONE); 430 } 431 432 433 /* PRBS Checker Lock State */ 434 err_code_t blackhawk_tsc_prbs_chk_lock_state(srds_access_t *sa__, uint8_t *chk_lock) { 435 if(!chk_lock) { 436 return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 437 } 438 439 ESTM(*chk_lock = rd_prbs_chk_lock()); /* PRBS Checker Lock Indication 1 = Locked, 0 = Out of Lock */ 440 return (ERR_CODE_NONE); 441 } 442 443 /* PRBS Error Count and Lock Lost (bit 31 in lock lost) */ 444 err_code_t blackhawk_tsc_prbs_err_count_ll(srds_access_t *sa__, uint32_t *prbs_err_cnt) { 445 uint16_t rddata; 446 447 if(!prbs_err_cnt) { 448 return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 449 } 450 ESTM(rddata = REG_RD_TLB_RX_PRBS_CHK_ERR_CNT_MSB_STATUS()); 451 *prbs_err_cnt = ((uint32_t) rddata)<<16; 452 ESTM(*prbs_err_cnt = (*prbs_err_cnt | rd_prbs_chk_err_cnt_lsb())); 453 454 455 return (ERR_CODE_NONE); 456 } 457 458 /* PRBS Error Count State */ 459 err_code_t blackhawk_tsc_prbs_err_count_state(srds_access_t *sa__, uint32_t *prbs_err_cnt, uint8_t *lock_lost) { 460 uint8_t dig_lpbk_enable = 0; 461 uint8_t link_training_enable = 0; 462 if(!prbs_err_cnt || !lock_lost) { 463 return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 464 } 465 EFUN(blackhawk_tsc_prbs_err_count_ll(sa__, prbs_err_cnt)); 466 *lock_lost = (*prbs_err_cnt >> 31); 467 *prbs_err_cnt = (*prbs_err_cnt & 0x7FFFFFFF); 468 469 /* Check if Digital Loopback and LinkTrainig both are enabled */ 470 ESTM(dig_lpbk_enable = rd_dig_lpbk_en()); 471 472 ESTM(link_training_enable = rd_linktrn_ieee_training_enable()); 473 if(dig_lpbk_enable && link_training_enable) { 474 EFUN_PRINTF(("WARNING: PRBS Check Lock - Digital Loopback and Link Training both are enabled\n")); 475 } 476 return (ERR_CODE_NONE); 477 } 478 479 /* Save prbs hardware timer config registers */ 480 err_code_t blackhawk_tsc_get_prbs_chk_hw_timer_ctrl(srds_access_t *sa__, struct prbs_chk_hw_timer_ctrl_st * const prbs_chk_hw_timer_ctrl_bak) { 481 ESTM(prbs_chk_hw_timer_ctrl_bak->prbs_chk_burst_err_cnt_en = rd_prbs_chk_burst_err_cnt_en()); 482 ESTM(prbs_chk_hw_timer_ctrl_bak->prbs_chk_en_timer_mode = rd_prbs_chk_en_timer_mode()); 483 ESTM(prbs_chk_hw_timer_ctrl_bak->prbs_chk_en_timeout = rd_prbs_chk_en_timeout()); 484 return ERR_CODE_NONE; 485 } 486 487 /* Restore prbs hardware timer config registers */ 488 err_code_t blackhawk_tsc_set_prbs_chk_hw_timer_ctrl(srds_access_t *sa__, struct prbs_chk_hw_timer_ctrl_st const * const prbs_chk_hw_timer_ctrl_bak) { 489 EFUN(wr_prbs_chk_burst_err_cnt_en(prbs_chk_hw_timer_ctrl_bak->prbs_chk_burst_err_cnt_en)); 490 EFUN(wr_prbs_chk_en_timer_mode(prbs_chk_hw_timer_ctrl_bak->prbs_chk_en_timer_mode)); 491 EFUN(wr_prbs_chk_en_timeout(prbs_chk_hw_timer_ctrl_bak->prbs_chk_en_timeout)); 492 return ERR_CODE_NONE; 493 } 494 495 /* Configure hardware timer to count prbs errors */ 496 err_code_t blackhawk_tsc_config_prbs_chk_hw_timer(srds_access_t *sa__, uint16_t time_ms, uint16_t *time_ms_adjusted) { 497 498 struct prbs_chk_hw_timer_ctrl_st prbs_chk_hw_timer_ctrl; 499 USR_MEMSET(&prbs_chk_hw_timer_ctrl, 0, sizeof(struct prbs_chk_hw_timer_ctrl_st)); 500 501 EFUN(wr_prbs_chk_burst_err_cnt_en(0)); 502 503 /* Figure out timer mode and timer count */ 504 EFUN(blackhawk_tsc_INTERNAL_get_prbs_timeout_count_from_time(time_ms, time_ms_adjusted, &prbs_chk_hw_timer_ctrl)); 505 506 EFUN(wr_prbs_chk_en_timer_mode(prbs_chk_hw_timer_ctrl.prbs_chk_en_timer_mode)); 507 EFUN(wr_prbs_chk_en_timeout(prbs_chk_hw_timer_ctrl.prbs_chk_en_timeout)); 508 509 return ERR_CODE_NONE; 510 } 511 512 /* toggle checker enable to start hardware timers and error counters */ 513 err_code_t blackhawk_tsc_prbs_chk_en_toggle(srds_access_t *sa__) { 514 EFUN(wr_prbs_chk_en(0)); 515 EFUN(wr_prbs_chk_en(1)); 516 return ERR_CODE_NONE; 517 } 518 519 err_code_t blackhawk_tsc_display_detailed_prbs_state_hdr(void) { 520 EFUN_PRINTF(("\nPRBS DETAILED DISPLAY :\n")); 521 522 /* Comment out display of PRBS burst error if BLACKHAWK */ 523 EFUN_PRINTF((" LN TX-Mode TX-PRBS-Inv TX-PMD-Inv RX-Mode RX-PRBS-Inv RX-PMD-Inv Lck LL PRBS-Err-Cnt")); 524 EFUN_PRINTF((" BER\n")); 525 return (ERR_CODE_NONE); 526 } 527 528 const char* blackhawk_tsc_e2s_prbs_mode_enum[17] = { 529 " PRBS_7", 530 " PRBS_9", 531 "PRBS_11", 532 "PRBS_15", 533 "PRBS_23", 534 "PRBS_31", 535 "PRBS_58", 536 "PRBS_49", 537 "PRBS_10", 538 "PRBS_20", 539 "PRBS_13", 540 " ERR ", 541 " ERR ", 542 " ERR ", 543 " ERR ", 544 " ERR ", 545 "UNKNOWN" 546 }; 547 548 err_code_t blackhawk_tsc_display_detailed_prbs_state(srds_access_t *sa__) { 549 uint32_t err_cnt = 0; 550 uint8_t lock_lost = 0; 551 uint8_t enabled; 552 553 ESTM_PRINTF((" %d ",blackhawk_tsc_get_lane(sa__))); 554 555 ESTM(enabled = rd_prbs_gen_en()); 556 if(enabled) { 557 enum srds_prbs_polynomial_enum prbs_poly_mode = PRBS_7; 558 uint8_t prbs_inv = 0; 559 char *prbs_string; 560 EFUN(blackhawk_tsc_get_tx_prbs_config(sa__, &prbs_poly_mode, &prbs_inv)); 561 prbs_string = (char *)blackhawk_tsc_e2s_prbs_mode_enum[prbs_poly_mode]; 562 ESTM_PRINTF(("%s",prbs_string)); 563 ESTM_PRINTF((" %1d ",prbs_inv)); 564 } else { 565 EFUN_PRINTF((" OFF ")); 566 ESTM_PRINTF((" - ")); 567 } 568 ESTM_PRINTF((" %1d ",rd_tx_pmd_dp_invert())); 569 570 ESTM(enabled = rd_prbs_chk_en()); 571 if(enabled) { 572 enum srds_prbs_polynomial_enum prbs_poly_mode = PRBS_7; 573 enum srds_prbs_checker_mode_enum prbs_checker_mode; 574 uint8_t prbs_inv = 0; 575 char *prbs_string; 576 EFUN(blackhawk_tsc_get_rx_prbs_config(sa__, &prbs_poly_mode, &prbs_checker_mode, &prbs_inv)); 577 prbs_string = (char *)blackhawk_tsc_e2s_prbs_mode_enum[prbs_poly_mode]; 578 ESTM_PRINTF((" %s",prbs_string)); 579 ESTM_PRINTF((" %1d ",prbs_inv)); 580 } else { 581 EFUN_PRINTF((" OFF ")); 582 ESTM_PRINTF((" - ")); 583 } 584 585 ESTM_PRINTF((" %1d ",rd_rx_pmd_dp_invert())); 586 ESTM_PRINTF((" %d ",rd_prbs_chk_lock())); 587 EFUN(blackhawk_tsc_prbs_err_count_state(sa__,&err_cnt,&lock_lost)); 588 EFUN_PRINTF((" %d %010d ",lock_lost,err_cnt)); 589 EFUN(blackhawk_tsc_INTERNAL_display_BER(sa__,100)); 590 EFUN_PRINTF(("\n")); 591 592 return (ERR_CODE_NONE); 593 } 594 595 596 /***********************************/ 597 /* PRBS Error Analyzer Functions */ 598 /***********************************/ 599 600 /* Configure PRBS Error Analyzer */ 601 err_code_t blackhawk_tsc_prbs_error_analyzer_config(srds_access_t *sa__, uint16_t prbs_err_fec_size, uint8_t prbs_errcnt_thresh, uint8_t hist_errcnt_thresh) { 602 uint8_t fec_size; 603 uint16_t fec_size_bits; 604 605 if ((prbs_err_fec_size < BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FEC_SIZE_MIN) || (prbs_err_fec_size > BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FEC_SIZE_MAX)) { 606 return (blackhawk_tsc_error(sa__, ERR_CODE_INVALID_PRBS_ERR_ANALYZER_FEC_SIZE)); 607 } 608 if ((prbs_errcnt_thresh < BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MIN) || (prbs_errcnt_thresh > BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MAX)) { 609 return (blackhawk_tsc_error(sa__, ERR_CODE_INVALID_PRBS_ERR_ANALYZER_ERR_THRESH)); 610 } 611 if ((hist_errcnt_thresh < BLACKHAWK_TSC_PRBS_ERR_ANALYZER_HIST_ERR_THRESH_MIN) || (hist_errcnt_thresh > BLACKHAWK_TSC_PRBS_ERR_ANALYZER_HIST_ERR_THRESH_MAX)) { 612 return (blackhawk_tsc_error(sa__, ERR_CODE_INVALID_PRBS_ERR_ANALYZER_HIST_ERR_THRESH)); 613 } 614 615 fec_size = ((prbs_err_fec_size + BLACKHAWK_TSC_PRBS_FEC_FRAME_SIZE_ROUND_UP) / BLACKHAWK_TSC_PRBS_FEC_FRAME_SIZE_MULTIPLIER); 616 617 fec_size_bits = (fec_size * BLACKHAWK_TSC_PRBS_FEC_FRAME_SIZE_MULTIPLIER); 618 if (prbs_err_fec_size != fec_size_bits) { 619 EFUN_PRINTF(("\n << WARNING: FEC Frame size of %d bits NOT programmable. Instead setting frame size to %d bits for Lane %d >>\n", prbs_err_fec_size, fec_size_bits, blackhawk_tsc_get_lane(sa__))); 620 } 621 622 EFUN(wr_tlb_err_fec_size(fec_size)); 623 EFUN(wr_tlb_err_error_count_thresh(prbs_errcnt_thresh)); 624 EFUN(wr_tlb_err_histogram_error_thresh(hist_errcnt_thresh)); 625 EFUN(wr_tlb_err_clear_error_analyzer_status(1)); /* Clear all the error analyzer status registers */ 626 return (ERR_CODE_NONE); 627 } 628 629 /* Get PRBS Error Analyzer Config */ 630 err_code_t blackhawk_tsc_get_prbs_error_analyzer_config(srds_access_t *sa__, uint16_t *prbs_err_fec_size, uint8_t *prbs_errcnt_thresh, uint8_t *hist_errcnt_thresh) { 631 632 if(!prbs_err_fec_size || !prbs_errcnt_thresh || !hist_errcnt_thresh) { 633 return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 634 } 635 636 ESTM(*prbs_err_fec_size = rd_tlb_err_fec_size()); 637 *prbs_err_fec_size = *prbs_err_fec_size * BLACKHAWK_TSC_PRBS_FEC_FRAME_SIZE_MULTIPLIER; 638 ESTM(*prbs_errcnt_thresh = rd_tlb_err_error_count_thresh()); 639 ESTM(*hist_errcnt_thresh = rd_tlb_err_histogram_error_thresh()); 640 return (ERR_CODE_NONE); 641 } 642 643 /* Display PRBS Error Analyzer Config */ 644 err_code_t blackhawk_tsc_display_prbs_error_analyzer_config(srds_access_t *sa__, uint8_t prbs_errcnt_thresh, uint8_t hist_errcnt_thresh, uint32_t timeout_s) { 645 646 uint8_t fec_size; 647 uint16_t fec_size_bits; 648 649 ESTM(fec_size = (uint8_t)rd_tlb_err_fec_size()); 650 fec_size_bits = (fec_size * BLACKHAWK_TSC_PRBS_FEC_FRAME_SIZE_MULTIPLIER); 651 652 EFUN_PRINTF(("\n ****************************************************************************** \n")); 653 EFUN_PRINTF((" PRBS Error Analyzer Config:\n")); 654 EFUN_PRINTF((" ------------------------------------------------------------- \n")); 655 EFUN_PRINTF((" FEC Frame Size = %4d bits\n",fec_size_bits)); 656 EFUN_PRINTF((" PRBS Max Err Threshold (Max) = %4d errors per frame\n",prbs_errcnt_thresh)); 657 EFUN_PRINTF((" PRBS Histogram Start (E) = %4d errors per frame\n",hist_errcnt_thresh)); 658 EFUN_PRINTF((" Time Duration of Analysis = %4d seconds\n",timeout_s)); 659 EFUN_PRINTF((" -------------------------------------------------------------\n")); 660 661 return (ERR_CODE_NONE); 662 } 663 664 /* Get PRBS Error Analyzer Error Count */ 665 err_code_t blackhawk_tsc_prbs_error_analyzer_err_count(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st *err_analyzer) { 666 uint16_t err_cnt; 667 uint8_t prbs_lock; 668 int8_t i; 669 670 if(!err_analyzer) { 671 return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 672 } 673 674 ESTM(err_analyzer->hist_errcnt_thresh = rd_tlb_err_histogram_error_thresh()); 675 ESTM(err_analyzer->prbs_errcnt_thresh = rd_tlb_err_error_count_thresh()); 676 677 ESTM(prbs_lock = rd_prbs_chk_lock()); 678 if(!prbs_lock) { 679 USR_PRINTF(("\nERROR : PRBS Checker is not locked for core %d Lane %d\n",blackhawk_tsc_get_core(sa__),blackhawk_tsc_get_lane(sa__))); 680 for (i=0; i<9; i++) { 681 err_analyzer->prbs_errcnt[i] = 0xFFFFFFFF; 682 } 683 } 684 else { 685 uint32_t frame_errors[9]; 686 uint32_t temp32; 687 688 /* Reading raw data from FEC err_count registers */ 689 ESTM(frame_errors[8] = rd_tlb_err_count_error_lo()); 690 ESTM(err_cnt = rd_tlb_err_count_error_hi()); 691 frame_errors[8] = (frame_errors[8] | (((uint32_t) err_cnt)<<16)); 692 693 ESTM(frame_errors[7] = rd_tlb_err_count_histogram_error_offset_7()); 694 ESTM(frame_errors[6] = rd_tlb_err_count_histogram_error_offset_6()); 695 ESTM(frame_errors[5] = rd_tlb_err_count_histogram_error_offset_5()); 696 ESTM(frame_errors[4] = rd_tlb_err_count_histogram_error_offset_4()); 697 ESTM(frame_errors[3] = rd_tlb_err_count_histogram_error_offset_3()); 698 ESTM(frame_errors[2] = rd_tlb_err_count_histogram_error_offset_2()); 699 ESTM(frame_errors[1] = rd_tlb_err_count_histogram_error_offset_1()); 700 ESTM(frame_errors[0] = rd_tlb_err_count_histogram_error_offset_0()); 701 702 if (PRBS_VERBOSE > 2) { 703 EFUN_PRINTF(("\n\n\t=====> DEBUG INFO (start) [Core = %d, Lane = %d]\n", blackhawk_tsc_get_core(sa__), blackhawk_tsc_get_lane(sa__))); 704 EFUN_PRINTF(("\n\t << Number of Frame Errors as read from the register >>\n")); 705 for (i=0; i<9; i++) { 706 if (i < 8) { 707 EFUN_PRINTF(("\t FEC frames with %2d Errors = %u\n",(i+err_analyzer->hist_errcnt_thresh),frame_errors[i])); 708 } 709 else { 710 EFUN_PRINTF(("\t FEC frames with > %2d Errors = %u\n",err_analyzer->prbs_errcnt_thresh-1,frame_errors[i])); 711 } 712 } 713 } 714 715 /* Calculating cumulative error count for respective values of "t" */ 716 for (i=8; i >= 0; i--) { 717 if ((frame_errors[i] != 0xFFFF) && (frame_errors[i] != 0xFFFFF)) { 718 if (i!=8) { 719 if (frame_errors[i+1] == 0xFFFFFFFF) { 720 frame_errors[i] = 0xFFFFFFFF; 721 } 722 else { 723 frame_errors[i] = (frame_errors[i] + frame_errors[i+1]); 724 } 725 } 726 } 727 else { 728 729 if (PRBS_VERBOSE > 2) { 730 EFUN_PRINTF(("\t frame_errors[%d] == MAX\n", i)); 731 } 732 733 frame_errors[i] = 0xFFFFFFFF; 734 } 735 } 736 737 if (PRBS_VERBOSE > 2) { 738 EFUN_PRINTF(("\n\t=====> DEBUG INFO (end)\n\n")); 739 } 740 741 /* Accumulating error counts and assigning to struct */ 742 for (i=0; i<9; i++) { 743 temp32 = 0xFFFFFFFF - frame_errors[i]; 744 if ((frame_errors[i] == 0xFFFFFFFF) || (temp32 <= err_analyzer->prbs_errcnt[i])) 745 err_analyzer->prbs_errcnt[i] = 0xFFFFFFFF; 746 else 747 err_analyzer->prbs_errcnt[i] = (frame_errors[i] + err_analyzer->prbs_errcnt[i]); 748 } 749 } 750 return (ERR_CODE_NONE); 751 } 752 753 /* Get PRBS Error Analyzer Accumulate Error Count and Clear error counters */ 754 err_code_t blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st *err_analyzer) { 755 756 EFUN(blackhawk_tsc_prbs_error_analyzer_err_count(sa__, err_analyzer)); 757 return (ERR_CODE_NONE); 758 } 759 760 static err_code_t _blackhawk_tsc_display_fec_frame_error(uint8_t errs_per_frame, uint32_t num_frame_errs) { 761 if (num_frame_errs == 0xFFFFFFFF) { 762 EFUN_PRINTF((" FEC Frames with > %2d Errors (t=%2d) = MAX \n",errs_per_frame,errs_per_frame)); 763 } 764 else { 765 EFUN_PRINTF((" FEC Frames with > %2d Errors (t=%2d) = %10u \n",errs_per_frame,errs_per_frame,num_frame_errs)); 766 } 767 return (ERR_CODE_NONE); 768 } 769 770 /* Optimize histogram error count threshold for PRBS Error Analyzer */ 771 err_code_t blackhawk_tsc_optimize_hist_errcnt_thresh(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st *err_analyzer, uint32_t timeout_check, uint32_t timeout_s) { 772 int8_t i = 0; 773 uint8_t errcnt_sat = 0; 774 #ifdef PHYMOD_SUPPORT 775 uint64_t tmp_err, tmp_sat; 776 #endif /* PHYMOD_SUPPORT */ 777 778 if((timeout_check == 0) || timeout_s == 0) { 779 USR_PRINTF(("\nERROR : timeout value cannot be 0 for RX lane %d\n",blackhawk_tsc_get_lane(sa__))); 780 } 781 if(timeout_check > timeout_s) { 782 USR_PRINTF(("\nERROR : timeout_check value has to be <= timeout_s value for RX lane %d\n",blackhawk_tsc_get_lane(sa__))); 783 } 784 785 /* Read the current histogram settings*/ 786 ESTM(err_analyzer->hist_errcnt_thresh = rd_tlb_err_histogram_error_thresh()); 787 788 /* Extrapolate and check for saturation */ 789 #ifdef PHYMOD_SUPPORT 790 for(i = BLACKHAWK_TSC_PRBS_ERR_ANALYZER_NUM_COUNTERS-1; i>=0 ; i--) { 791 /* 792 * 64-bit operations use COMPILER_64_XXX macros 793 */ 794 /* tmp_err = (uint64_t)timeout_s * err_analyzer->prbs_errcnt[i] */ 795 COMPILER_64_SET(tmp_err, 0, (uint32_t)1); 796 COMPILER_64_UMUL_32(tmp_err, timeout_s); 797 COMPILER_64_UMUL_32(tmp_err, err_analyzer->prbs_errcnt[i]); 798 799 /* tmp_sat = (uint64_t)timeout_check * 0xFFFF */ 800 COMPILER_64_SET(tmp_sat, 0, (uint32_t)1); 801 COMPILER_64_UMUL_32(tmp_sat, timeout_check); 802 COMPILER_64_UMUL_32(tmp_sat, 0xFFFF); 803 804 if (COMPILER_64_GE(tmp_err, tmp_sat)) { 805 errcnt_sat = 1; 806 break; 807 } 808 } 809 #else 810 for(i = BLACKHAWK_TSC_PRBS_ERR_ANALYZER_NUM_COUNTERS-1; i>=0 ; i--) { 811 if((uint64_t)timeout_s * err_analyzer->prbs_errcnt[i] > (uint64_t)timeout_check * (0xFFFF)) { 812 errcnt_sat = 1; 813 break; 814 } 815 } 816 #endif /* PHYMOD_SUPPORT */ 817 818 if((errcnt_sat == 1) && (i != 0)) { 819 if((i+err_analyzer->hist_errcnt_thresh) >= BLACKHAWK_TSC_PRBS_ERR_ANALYZER_HIST_ERR_THRESH_MAX) { 820 err_analyzer->hist_errcnt_thresh = BLACKHAWK_TSC_PRBS_ERR_ANALYZER_HIST_ERR_THRESH_MAX-1; 821 err_analyzer->prbs_errcnt_thresh = BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MAX; 822 EFUN_PRINTF(("\tLane %d: Setting the histogram error count threshold to maximum value = %d and PRBS error count threshold = %d\n \n ", blackhawk_tsc_get_lane(sa__), err_analyzer->hist_errcnt_thresh, BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MAX)); 823 824 } else { 825 err_analyzer->hist_errcnt_thresh += i; 826 err_analyzer->prbs_errcnt_thresh = err_analyzer->hist_errcnt_thresh + 8; 827 EFUN_PRINTF(("\tLane %d: Optimum histogram error count threshold found\n", blackhawk_tsc_get_lane(sa__))); 828 USR_PRINTF((" Changing histogram error count threshold to %d and PRBS error count threshold to %d\n \n ", err_analyzer->hist_errcnt_thresh, err_analyzer->prbs_errcnt_thresh)); 829 } 830 /* Reconfigure */ 831 EFUN(wr_tlb_err_histogram_error_thresh(err_analyzer->hist_errcnt_thresh)); 832 EFUN(wr_tlb_err_error_count_thresh(err_analyzer->prbs_errcnt_thresh)); 833 } else if ((err_analyzer->prbs_errcnt[0] == 0) && (err_analyzer->hist_errcnt_thresh != BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MIN)) { 834 EFUN_PRINTF(("\tLane %d: WARNING: Error counters are all 0 after %ds. Try reducing hist_errcnt_thresh or increasing timeout_check and rerun the projection\n \n ", blackhawk_tsc_get_lane(sa__), timeout_check)); 835 } else if ((err_analyzer->prbs_errcnt[0] == 0) && (err_analyzer->hist_errcnt_thresh == BLACKHAWK_TSC_PRBS_ERR_ANALYZER_ERR_THRESH_MIN)) { 836 EFUN_PRINTF(("\tLane %d: WARNING: Error counters are all 0 after %ds. Try increasing timeout_check and/or timeout and rerun the projection\n \n ", blackhawk_tsc_get_lane(sa__), timeout_check)); 837 } else { 838 EFUN_PRINTF(("\tLane %d: Current hist_errcnt_thresh is the optimized value. Value = %d is unchanged. \n \n ", blackhawk_tsc_get_lane(sa__), err_analyzer->hist_errcnt_thresh)); 839 } 840 841 /* Clear all the error analyzer status registers */ 842 EFUN(wr_tlb_err_clear_error_analyzer_status(1)); 843 844 return (ERR_CODE_NONE); 845 } 846 847 /* PRBS Error Analyzer Display */ 848 err_code_t blackhawk_tsc_display_prbs_error_analyzer_err_count(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer) { 849 uint8_t t, i; 850 851 t = err_analyzer.hist_errcnt_thresh - 1; /* number of FEC correctable errors */ 852 853 /* Display PRBS Error Analyzer Err_Counts */ 854 EFUN_PRINTF(("\n -------------------------------------------------------------\n")); 855 EFUN_PRINTF((" PRBS Error Analyzer Error_Counts:\n")); 856 EFUN_PRINTF((" -------------------------------------------------------------\n")); 857 for (i=0; i<8; i++) { 858 EFUN(_blackhawk_tsc_display_fec_frame_error(t+i, err_analyzer.prbs_errcnt[i])); 859 } 860 EFUN(_blackhawk_tsc_display_fec_frame_error(err_analyzer.prbs_errcnt_thresh-1, err_analyzer.prbs_errcnt[8])); 861 EFUN_PRINTF((" -------------------------------------------------------------\n")); 862 863 return (ERR_CODE_NONE); 864 } 865 866 867 /* Display PRBS Error Analyzer Projection */ 868 err_code_t blackhawk_tsc_display_prbs_error_analyzer_proj(srds_access_t *sa__, uint16_t prbs_err_fec_size, uint8_t hist_errcnt_thresh, uint32_t timeout_s) { 869 uint8_t hrs, mins, secs; 870 uint8_t prbs_lock; 871 uint32_t time_remaining_s; 872 int8_t i = 0; 873 blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer; 874 875 if (timeout_s == 0) { 876 EFUN_PRINTF(("\nERROR: timeout_s value cannot be 0 for Lane %d >>\n", blackhawk_tsc_get_lane(sa__))); 877 } 878 879 ESTM(prbs_lock = rd_prbs_chk_lock()); 880 if(!prbs_lock) { 881 USR_PRINTF(("\nERROR : PRBS Checker is not locked for RX lane %d\n",blackhawk_tsc_get_lane(sa__))); 882 } 883 else { 884 USR_MEMSET(&err_analyzer, 0, sizeof(blackhawk_tsc_prbs_err_analyzer_errcnt_st)); 885 err_analyzer.prbs_errcnt_thresh = hist_errcnt_thresh + 8; /* Since 20bit err_cnt register counts Frames with errors >= prbs_errcnt_thresh errors */ 886 err_analyzer.hist_errcnt_thresh = hist_errcnt_thresh; 887 EFUN(blackhawk_tsc_prbs_error_analyzer_config(sa__, prbs_err_fec_size, err_analyzer.prbs_errcnt_thresh, err_analyzer.hist_errcnt_thresh)); /* Configure PRBS Error Analyzer */ 888 EFUN(wr_tlb_err_clear_status_on_read(1)); 889 /* Clear the error counters for a fresh start */ 890 for (i = 0; i <= BLACKHAWK_TSC_PRBS_ERR_ANALYZER_NUM_COUNTERS; i++) { 891 err_analyzer.prbs_errcnt[i] = 0; 892 } 893 894 EFUN(blackhawk_tsc_INTERNAL_seconds_to_displayformat(timeout_s, &hrs, &mins, &secs)); 895 EFUN_PRINTF((" \n Waiting for PRBS Error Analyzer measurement: time approx %d seconds (%d hr:%d mins: %ds) ",timeout_s,hrs,mins,secs)); 896 897 /* Wait for required duration and accumulate errors */ 898 time_remaining_s = timeout_s; 899 while (time_remaining_s > 0) { 900 if (time_remaining_s > 5) { 901 EFUN(USR_DELAY_MS(5000)); 902 EFUN(blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(sa__, &err_analyzer)); 903 EFUN_PRINTF((".")); 904 time_remaining_s = time_remaining_s - 5; 905 } 906 else { 907 EFUN(USR_DELAY_MS(((uint32_t)time_remaining_s) * 1000)); 908 EFUN(blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(sa__, &err_analyzer)); 909 EFUN_PRINTF(("\n")); 910 time_remaining_s = 0; 911 } 912 } 913 914 /* Display PRBS Error Analyzer Config */ 915 EFUN(blackhawk_tsc_display_prbs_error_analyzer_config(sa__, err_analyzer.prbs_errcnt_thresh, err_analyzer.hist_errcnt_thresh, timeout_s)); 916 917 /* Display PRBS Error Analyzer Err_Counts */ 918 EFUN(blackhawk_tsc_display_prbs_error_analyzer_err_count(sa__, err_analyzer)); 919 920 /* Compute and display PRBS Error Analyzer Projection */ 921 EFUN(blackhawk_tsc_prbs_error_analyzer_compute_proj(sa__, err_analyzer, timeout_s)); 922 } 923 return (ERR_CODE_NONE); 924 } 925 926 /* Display PRBS Error Analyzer Projection with automatic threshold adjusting */ 927 err_code_t blackhawk_tsc_display_prbs_error_analyzer_proj_auto_threshold(srds_access_t *sa__, uint16_t prbs_err_fec_size, uint32_t timeout_s) { 928 uint8_t hrs, mins, secs; 929 uint8_t prbs_lock; 930 uint32_t time_remaining_s, timeout_frac; 931 int8_t i = 0; 932 blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer; 933 934 if (timeout_s == 0) { 935 EFUN_PRINTF(("\nERROR: timeout_s value cannot be 0 for Lane %d >>\n", blackhawk_tsc_get_lane(sa__))); 936 } 937 938 ESTM(prbs_lock = rd_prbs_chk_lock()); 939 if(!prbs_lock) { 940 USR_PRINTF(("\nERROR : PRBS Checker is not locked for RX lane %d\n",blackhawk_tsc_get_lane(sa__))); 941 } 942 else { 943 USR_MEMSET(&err_analyzer, 0, sizeof(blackhawk_tsc_prbs_err_analyzer_errcnt_st)); 944 err_analyzer.hist_errcnt_thresh = BLACKHAWK_TSC_PRBS_ERR_ANALYZER_HIST_ERR_THRESH_MIN; 945 err_analyzer.prbs_errcnt_thresh = err_analyzer.hist_errcnt_thresh + 8; /* Since 20bit err_cnt register counts Frames with errors >= prbs_errcnt_thresh errors */ 946 947 EFUN(blackhawk_tsc_prbs_error_analyzer_config(sa__, prbs_err_fec_size, err_analyzer.prbs_errcnt_thresh, err_analyzer.hist_errcnt_thresh)); /* Configure PRBS Error Analyzer */ 948 949 EFUN(wr_tlb_err_clear_status_on_read(1)); 950 951 timeout_frac = (5*timeout_s+99)/100; /* 99 is used to generate CEIL function of 5% of timeout_s */ 952 EFUN(blackhawk_tsc_INTERNAL_seconds_to_displayformat(timeout_frac, &hrs, &mins, &secs)); 953 EFUN_PRINTF(("\n \n Running a quick PRBS Error Analyzer measurement : time approx %d seconds (%d hr:%d mins: %ds) to check if any error counters would saturate\n \n ",timeout_frac,hrs,mins,secs)); 954 955 /* Run a quick test (5% of timeout_s) and optimize the hist_errcnt_thresh */ 956 EFUN(USR_DELAY_MS(1000*timeout_frac)); 957 EFUN(blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(sa__, &err_analyzer)); 958 EFUN(blackhawk_tsc_optimize_hist_errcnt_thresh(sa__, &err_analyzer, timeout_frac, timeout_s)); 959 960 /* Clear the error counters for a fresh start */ 961 for (i = 0; i <= BLACKHAWK_TSC_PRBS_ERR_ANALYZER_NUM_COUNTERS; i++) { 962 err_analyzer.prbs_errcnt[i] = 0; 963 } 964 965 EFUN(blackhawk_tsc_INTERNAL_seconds_to_displayformat(timeout_s, &hrs, &mins, &secs)); 966 EFUN_PRINTF((" \n Waiting for PRBS Error Analyzer measurement: time approx %d seconds (%d hr:%d mins: %ds) ",timeout_s,hrs,mins,secs)); 967 968 /* Wait for required duration and accumulate errors */ 969 time_remaining_s = timeout_s; 970 while (time_remaining_s > 0) { 971 if (time_remaining_s > 5) { 972 EFUN(USR_DELAY_MS(5000)); 973 EFUN(blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(sa__, &err_analyzer)); 974 EFUN_PRINTF((".")); 975 time_remaining_s = time_remaining_s - 5; 976 } 977 else { 978 EFUN(USR_DELAY_MS(((uint32_t)time_remaining_s) * 1000)); 979 EFUN(blackhawk_tsc_prbs_error_analyzer_accumulate_err_count(sa__, &err_analyzer)); 980 EFUN_PRINTF(("\n")); 981 time_remaining_s = 0; 982 } 983 } 984 985 /* Display PRBS Error Analyzer Config */ 986 EFUN(blackhawk_tsc_display_prbs_error_analyzer_config(sa__, err_analyzer.prbs_errcnt_thresh, err_analyzer.hist_errcnt_thresh, timeout_s)); 987 988 /* Display PRBS Error Analyzer Err_Counts */ 989 EFUN(blackhawk_tsc_display_prbs_error_analyzer_err_count(sa__, err_analyzer)); 990 991 /* Compute and display PRBS Error Analyzer Projection */ 992 EFUN(blackhawk_tsc_prbs_error_analyzer_compute_proj(sa__, err_analyzer, timeout_s)); 993 } 994 return (ERR_CODE_NONE); 995 } 996 997 998 /*----------------------------------------------------------------------------------------------------------------*/ 999 /* Following calculations are used for projecting the Bit Error Rate (BER) from the PRBS Error Analyzer result */ 1000 /* - test_time_in_bits = test_time_ms * num_bits_per_ms */ 1001 /* - num_frames_in_test = test_time_in_bits / (num_bits_per_frame * frame_overlap_ratio) */ 1002 /* - frame_err_rate (FER) = num_frame_errors / num_frames_in_test */ 1003 /* - bit_err_rate (BER) = FER / num_bits_per_frame */ 1004 /* => BER = (num_frame_errors * frame_overlap_ratio) / (test_time_ms * num_bits_per_ms) */ 1005 /* where, frame_overlap_ratio = 1 / frame_overlap_factor */ 1006 /* */ 1007 /* Following guidelines are used while computing projected values - */ 1008 /* i) Only "frame_errors" that are in between "10 and 65535" are considered as valid data points for projection */ 1009 /* ii) Need atleast 2 valid data points to generated projected data */ 1010 /*----------------------------------------------------------------------------------------------------------------*/ 1011 err_code_t blackhawk_tsc_prbs_error_analyzer_report_proj(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer, uint32_t timeout_s, blackhawk_tsc_prbs_err_analyzer_report_st *err_analyzer_report) { 1012 #ifdef SERDES_API_FLOATING_POINT 1013 uint8_t t, delta_n; 1014 int8_t i; 1015 uint8_t start_idx, stop_idx; 1016 uint32_t num_bits_per_ms; 1017 USR_DOUBLE meas_fec_ber[9]; 1018 USR_DOUBLE proj_ber[16]; 1019 USR_DOUBLE x, y; 1020 USR_DOUBLE Exy = 0.0; 1021 USR_DOUBLE Eyy = 0.0; 1022 USR_DOUBLE Exx = 0.0; 1023 USR_DOUBLE Ey = 0.0; 1024 USR_DOUBLE Ex = 0.0; 1025 USR_DOUBLE alpha = 0.0, alpha2 = 0.0, sq_r = 0.0; 1026 USR_DOUBLE beta = 0.0; 1027 1028 if (timeout_s == 0) { 1029 EFUN_PRINTF(("\nERROR: timeout_s value cannot be 0 for Lane %d >>\n", blackhawk_tsc_get_lane(sa__))); 1030 return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1031 } 1032 1033 USR_MEMSET(err_analyzer_report, 0, sizeof(blackhawk_tsc_prbs_err_analyzer_report_st)); 1034 t = err_analyzer.hist_errcnt_thresh - 1; /* Number of FEC correctable errors */ 1035 EFUN(blackhawk_tsc_INTERNAL_get_num_bits_per_ms(sa__, &num_bits_per_ms)); 1036 1037 if (num_bits_per_ms == 0) { 1038 EFUN_PRINTF(("\nERROR: num_bits_per_ms value cannot be 0 for Lane %d >>\n", blackhawk_tsc_get_lane(sa__))); 1039 return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1040 } 1041 1042 if (PRBS_VERBOSE > 2) { 1043 EFUN_PRINTF(("\n\t=====> DEBUG INFO (start)\n")); 1044 EFUN_PRINTF(("\n\t << Measured Equivalent BER for specific error correcting FEC >>\n")); 1045 } 1046 1047 /* Loop to calculate the measured BER based on above mentioned calculations */ 1048 1049 for(i=0; i < 9; i++) { 1050 meas_fec_ber[i] = ((((USR_DOUBLE)(err_analyzer.prbs_errcnt[i]) / (USR_DOUBLE) BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FRAME_OVERLAP_FACTOR) / (USR_DOUBLE)(timeout_s * 1000)) / (USR_DOUBLE) num_bits_per_ms); 1051 if (PRBS_VERBOSE > 2) { 1052 EFUN_PRINTF(("\t Measured Equivalent BER at 't=%2d' (((frameErr/overlap_factor)/time_ms)/rate) = (((%u/%d)/%d)/%d): %0.3e \n",(t+i), err_analyzer.prbs_errcnt[i], 1053 BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FRAME_OVERLAP_FACTOR, timeout_s*1000, num_bits_per_ms, meas_fec_ber[i])); 1054 } 1055 } 1056 1057 /* Calculating number of MEASURED points available for extrapolation */ 1058 /* start_idx - first non-max FEC frame error value; stop_idx - index where FEC frame errors < 10 errors */ 1059 start_idx = 0; 1060 stop_idx = 0; 1061 if (err_analyzer.prbs_errcnt[8] != 0xFFFFFFFF) { 1062 stop_idx = 9; 1063 } 1064 for (i=8; i >= 0; i--) { 1065 if (err_analyzer.prbs_errcnt[i] != 0xFFFFFFFF) { 1066 start_idx = i; 1067 } 1068 if (err_analyzer.prbs_errcnt[i] < 10*BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FRAME_OVERLAP_FACTOR) { /* "10*BLACKHAWK_TSC_PRBS_ERR_ANALYZER_FRAME_OVERLAP_FACTOR" means "10 error events" */ 1069 stop_idx = i; 1070 } 1071 } 1072 delta_n = stop_idx - start_idx; /* Number of MEASURED points available for extrapolation */ 1073 1074 /* Compute covariance and mean for extrapolation */ 1075 if (delta_n >= 2) { /* There are at least 2 points to trace a line for extrapolation */ 1076 for(i=start_idx; i < stop_idx; i++) { 1077 x = (USR_DOUBLE) (t + i); 1078 y = pow((-log10(meas_fec_ber[i])),BLACKHAWK_TSC_PRBS_ERR_ANALYZER_LINEARITY_ADJUST); 1079 Exy += ((x * y)/(USR_DOUBLE)delta_n); 1080 Eyy += ((y * y)/(USR_DOUBLE)delta_n); 1081 Exx += ((x * x)/(USR_DOUBLE)delta_n); 1082 Ey += (( y )/(USR_DOUBLE)delta_n); 1083 Ex += (( x )/(USR_DOUBLE)delta_n); 1084 } 1085 1086 /* Compute fit slope and offset: ber = alpha*frame_err_thresh + beta */ 1087 alpha = (Exy - Ey*Ex) / (Exx - Ex*Ex); 1088 beta = Ey - Ex*alpha; 1089 /* Compute alpha2: slope of regression: frame_err_thresh = alpha2*ber + beta2 */ 1090 alpha2 = (Exy - Ey*Ex) / (Eyy - Ey*Ey); 1091 /* Compute correlation index sq_r */ 1092 sq_r = alpha*alpha2; 1093 } 1094 1095 if (PRBS_VERBOSE > 2) { 1096 EFUN_PRINTF(("\n\t << Computing linear fit from Measured Equivalent BER points >>\n")); 1097 EFUN_PRINTF(("\t Number of measured points used for extrapolation = %d\n",delta_n)); 1098 EFUN_PRINTF(("\t Exy=%lf, Eyy=%lf, Exx=%lf, Ey=%lf, Ex=%lf\n",Exy,Eyy,Exx,Ey,Ex)); 1099 EFUN_PRINTF(("\t alpha=%lf, beta=%lf\n",alpha,beta)); 1100 EFUN_PRINTF(("\t sq_r=%lf\n",sq_r)); 1101 EFUN_PRINTF(("\n\t=====> DEBUG INFO (end)\n\n")); 1102 } 1103 1104 1105 /* Calulate Projected BER => Equivalent projected post-FEC BER for t=15 */ 1106 if (delta_n >= 2) { 1107 proj_ber[15] = ((alpha * 15) + beta); 1108 proj_ber[15] = pow(proj_ber[15],1.0/BLACKHAWK_TSC_PRBS_ERR_ANALYZER_LINEARITY_ADJUST); 1109 proj_ber[15] = pow(10,-proj_ber[15]); 1110 } 1111 else { 1112 proj_ber[15] = 0.0; 1113 } 1114 1115 1116 1117 /* Populate output structure */ 1118 err_analyzer_report->proj_ber = proj_ber[15]; 1119 err_analyzer_report->ber_proj_invalid = 0; /* To be populated: 0 -> valid, +1 -> BER greater than; -1 -> BER less than */ 1120 err_analyzer_report->delta_n = delta_n; 1121 return (ERR_CODE_NONE); 1122 #else 1123 UNUSED(err_analyzer); 1124 UNUSED(timeout_s); 1125 UNUSED(*err_analyzer_report); 1126 EFUN_PRINTF(("This function needs SERDES_API_FLOATING_POINT define to operate \n")); 1127 return(blackhawk_tsc_error(sa__, ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 1128 #endif /* SERDES_API_FLOATING_POINT */ 1129 } 1130 1131 err_code_t blackhawk_tsc_prbs_error_analyzer_compute_proj(srds_access_t *sa__, blackhawk_tsc_prbs_err_analyzer_errcnt_st err_analyzer, uint32_t timeout_s) { 1132 1133 #ifdef SERDES_API_FLOATING_POINT 1134 blackhawk_tsc_prbs_err_analyzer_report_st err_analyzer_rep; 1135 1136 if (timeout_s == 0) { 1137 EFUN_PRINTF(("\nERROR: timeout_s value cannot be 0 for Lane %d >>\n", blackhawk_tsc_get_lane(sa__))); 1138 } 1139 1140 EFUN(blackhawk_tsc_prbs_error_analyzer_report_proj(sa__, err_analyzer, timeout_s, &err_analyzer_rep)); 1141 1142 1143 /* Displaying Projected BER => Equivalent projected post-FEC BER for t=15 */ 1144 if (err_analyzer_rep.delta_n >= 2) { 1145 EFUN_PRINTF(("\n PRBS Error Analyzer Projected BER (Equivalent projected post-FEC BER for t=15) for Lane %d = %0.3e\n\n",blackhawk_tsc_get_lane(sa__), err_analyzer_rep.proj_ber)); 1146 } 1147 else { 1148 EFUN_PRINTF(("\n << WARNING: Not enough valid measured points available for BER Projection for Lane %d ! >>\n\n",blackhawk_tsc_get_lane(sa__))); 1149 } 1150 1151 #else 1152 UNUSED(err_analyzer); 1153 UNUSED(timeout_s); 1154 #endif /* SERDES_API_FLOATING_POINT */ 1155 1156 1157 return (ERR_CODE_NONE); 1158 } 1159 1160 err_code_t blackhawk_tsc_get_prbsfb_status(srds_access_t *sa__, uint8_t *done_once) { 1161 /* D003_XX has this register read macro defined*/ 1162 uint16_t ucode_version_major; 1163 /*Extracting the major version number*/ 1164 ESTM(ucode_version_major = rdcv_common_ucode_version() & 0xFFF); 1165 if (ucode_version_major >= 0x3) { 1166 ESTM((*done_once = rdv_opt_err_pam4_prbsfb_byte_byte() & 0x40)); 1167 } else { 1168 *done_once = 1; 1169 EFUN_PRINTF(("ERROR: Need microcode version D003_xx for prbsfb status read to work correctly, setting done_once to 1 \n")); 1170 } 1171 return(ERR_CODE_NONE); 1172 } 1173 1174 1175