openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

merlin16_prbs.c (16896B)


      1 /**************************************************************************************
      2  **************************************************************************************
      3  *  File Name     :  merlin16_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 merlin16_prbs.c
     23  * Implementation of API PRBS functions
     24  */
     25 #ifdef NON_SDK
     26 #include <stdio.h>
     27 #include <math.h>
     28 #endif
     29 
     30 #include "merlin16_prbs.h"
     31 #include "merlin16_common.h"
     32 #include "merlin16_dependencies.h"
     33 #include "merlin16_functions.h"
     34 #include "merlin16_internal.h"
     35 #include "merlin16_internal_error.h"
     36 #include "merlin16_select_defns.h"
     37 #include "merlin16_access.h"
     38 
     39 
     40 /******************************/
     41 /*  TX Pattern Generator APIs */
     42 /******************************/
     43 
     44 /* Cofigure shared TX Pattern (Return Val = 0:PASS, 1-6:FAIL (reports 6 possible error scenarios if failed)) */
     45 err_code_t merlin16_config_shared_tx_pattern(srds_access_t *sa__, uint8_t patt_length, const char pattern[]) {
     46 
     47   char       patt_final[245] = "";
     48   char       patt_mod[245]   = "", bin[5] = "";
     49   uint8_t    str_len, i, k, j = 0;
     50   uint8_t    offset_len, actual_patt_len = 0, hex = 0;
     51   uint8_t    zero_pad_len    = 0; /* suppress warnings, changed by merlin16_INTERNAL_calc_patt_gen_mode_sel() */
     52   uint16_t   patt_gen_wr_val = 0;
     53   uint8_t    mode_sel        = 0; /* suppress warnings, changed by merlin16_INTERNAL_calc_patt_gen_mode_sel() */
     54 
     55   EFUN(merlin16_INTERNAL_calc_patt_gen_mode_sel(&mode_sel,&zero_pad_len,patt_length));
     56 
     57   /* Generating the appropriate write value to patt_gen_seq registers */
     58   str_len = (int8_t)USR_STRLEN(pattern);
     59 
     60   if ((str_len > 2) && ((USR_STRNCMP(pattern, "0x", 2)) == 0)) {
     61     /* Hexadecimal Pattern */
     62     for (i=2; i < str_len; i++) {
     63       if (pattern[i] != '_') {
     64         EFUN(merlin16_INTERNAL_compute_bin(pattern[i],bin));
     65         ENULL_STRNCAT(patt_mod, bin, 4);
     66         actual_patt_len = actual_patt_len + 4;
     67         if (actual_patt_len > 240) {
     68           EFUN_PRINTF(("ERROR: Pattern bigger than max pattern length\n"));
     69           return (_error(ERR_CODE_CFG_PATT_PATTERN_BIGGER_THAN_MAXLEN));
     70         }
     71       }
     72     }
     73 
     74     offset_len = (actual_patt_len - patt_length);
     75     if ((offset_len > 3)  || (actual_patt_len < patt_length)) {
     76       EFUN_PRINTF(("ERROR: Pattern length provided does not match the hexadecimal pattern provided\n"));
     77       return (_error(ERR_CODE_CFG_PATT_LEN_MISMATCH));
     78     }
     79     else if (offset_len) {
     80       for (i=0; i < offset_len; i++) {
     81         if (patt_mod[i] != '0') {
     82           EFUN_PRINTF(("ERROR: Pattern length provided does not match the hexadecimal pattern provided\n"));
     83           return (_error(ERR_CODE_CFG_PATT_LEN_MISMATCH));
     84         }
     85       }
     86       for (i=offset_len; i <= actual_patt_len; i++) {
     87         patt_mod[i - offset_len] = patt_mod[i];
     88       }
     89     }
     90   }
     91   else {
     92     /* Binary Pattern */
     93     for (i=0; i < str_len; i++) {
     94       if ((pattern[i] == '0') || (pattern[i] == '1')) {
     95         bin[0] = pattern[i];
     96         bin[1] = '\0';
     97         ENULL_STRNCAT(patt_mod, bin, 1);
     98         actual_patt_len++;
     99         if (actual_patt_len > 240) {
    100           EFUN_PRINTF(("ERROR: Pattern bigger than max pattern length\n"));
    101           return (_error(ERR_CODE_CFG_PATT_PATTERN_BIGGER_THAN_MAXLEN));
    102         }
    103       }
    104       else if (pattern[i] != '_') {
    105         EFUN_PRINTF(("ERROR: Invalid input Pattern\n"));
    106         return (_error(ERR_CODE_CFG_PATT_INVALID_PATTERN));
    107       }
    108     }
    109 
    110     if (actual_patt_len != patt_length) {
    111       EFUN_PRINTF(("ERROR: Pattern length provided does not match the binary pattern provided\n"));
    112       return (_error(ERR_CODE_CFG_PATT_LEN_MISMATCH));
    113     }
    114   }
    115 
    116   /* Zero padding upper bits and concatinating patt_mod to form patt_final */
    117   for (i=0; i < zero_pad_len; i++) {
    118     ENULL_STRNCAT(patt_final, "0", 1);
    119     j++;
    120   }
    121   for (i=zero_pad_len; i + patt_length < 241; i = i + patt_length) {
    122     ENULL_STRNCAT(patt_final, patt_mod, patt_length);
    123     j++;
    124   }
    125 
    126   /* EFUN_PRINTF(("\nFinal Pattern = %s\n\n",patt_final));    */
    127 
    128   for (i=0; i < 15; i++) {
    129 
    130     for (j=0; j < 4; j++) {
    131       k = i*16 + j*4;
    132       bin[0] = patt_final[k];
    133       bin[1] = patt_final[k+1];
    134       bin[2] = patt_final[k+2];
    135       bin[3] = patt_final[k+3];
    136       bin[4] = '\0';
    137       EFUN(merlin16_INTERNAL_compute_hex(bin, &hex));
    138       patt_gen_wr_val = ((patt_gen_wr_val << 4) | hex);
    139     }
    140     /* EFUN_PRINTF(("patt_gen_wr_val[%d] = 0x%x\n",(14-i),patt_gen_wr_val));    */
    141 
    142     /* Writing to apprpriate patt_gen_seq Registers */
    143     switch (i) {
    144       case 0:  EFUN(wrc_patt_gen_seq_14(patt_gen_wr_val));
    145                break;
    146       case 1:  EFUN(wrc_patt_gen_seq_13(patt_gen_wr_val));
    147                break;
    148       case 2:  EFUN(wrc_patt_gen_seq_12(patt_gen_wr_val));
    149                break;
    150       case 3:  EFUN(wrc_patt_gen_seq_11(patt_gen_wr_val));
    151                break;
    152       case 4:  EFUN(wrc_patt_gen_seq_10(patt_gen_wr_val));
    153                break;
    154       case 5:  EFUN(wrc_patt_gen_seq_9(patt_gen_wr_val));
    155                break;
    156       case 6:  EFUN(wrc_patt_gen_seq_8(patt_gen_wr_val));
    157                break;
    158       case 7:  EFUN(wrc_patt_gen_seq_7(patt_gen_wr_val));
    159                break;
    160       case 8:  EFUN(wrc_patt_gen_seq_6(patt_gen_wr_val));
    161                break;
    162       case 9:  EFUN(wrc_patt_gen_seq_5(patt_gen_wr_val));
    163                break;
    164       case 10: EFUN(wrc_patt_gen_seq_4(patt_gen_wr_val));
    165                break;
    166       case 11: EFUN(wrc_patt_gen_seq_3(patt_gen_wr_val));
    167                break;
    168       case 12: EFUN(wrc_patt_gen_seq_2(patt_gen_wr_val));
    169                break;
    170       case 13: EFUN(wrc_patt_gen_seq_1(patt_gen_wr_val));
    171                break;
    172       case 14: EFUN(wrc_patt_gen_seq_0(patt_gen_wr_val));
    173                break;
    174       default: EFUN_PRINTF(("ERROR: Invalid write to patt_gen_seq register\n"));
    175                return (_error(ERR_CODE_CFG_PATT_INVALID_SEQ_WRITE));
    176     }
    177   }
    178 
    179   /* Pattern Generator Mode Select */
    180   /* EFUN(wr_patt_gen_mode_sel(mode_sel)); */
    181   /* EFUN_PRINTF(("Pattern gen Mode = %d\n",mode));    */
    182 
    183   /* Enable Fixed pattern Generation */
    184   /* EFUN(wr_patt_gen_en(0x1)); */
    185   return(ERR_CODE_NONE);
    186 }
    187 
    188 
    189 /* Enable/Disable Shared TX pattern generator */
    190 err_code_t merlin16_tx_shared_patt_gen_en(srds_access_t *sa__, uint8_t enable, uint8_t patt_length) {
    191   uint8_t zero_pad_len = 0; /* suppress warnings, changed by merlin16_INTERNAL_calc_patt_gen_mode_sel() */
    192   uint8_t mode_sel     = 0; /* suppress warnings, changed by merlin16_INTERNAL_calc_patt_gen_mode_sel() */
    193 
    194   EFUN(merlin16_INTERNAL_calc_patt_gen_mode_sel(&mode_sel,&zero_pad_len,patt_length));
    195 
    196   if (enable) {
    197     if ((mode_sel < 1) || (mode_sel > 6)) {
    198       return (_error(ERR_CODE_PATT_GEN_INVALID_MODE_SEL));
    199     }
    200     mode_sel = (12 - mode_sel);
    201     EFUN(wr_patt_gen_start_pos(mode_sel));            /* Start position for pattern */
    202     EFUN(wr_patt_gen_stop_pos(0x0));                  /* Stop position for pattern */
    203     EFUN(wr_patt_gen_en(0x1));                        /* Enable Fixed pattern Generation  */
    204   }
    205   else {
    206     EFUN(wr_patt_gen_en(0x0));                        /* Disable Fixed pattern Generation  */
    207   }
    208   return(ERR_CODE_NONE);
    209 }
    210 
    211 
    212 /**************************************/
    213 /*  PRBS Generator/Checker Functions  */
    214 /**************************************/
    215 
    216 /* Configure PRBS Generator */
    217 err_code_t merlin16_config_tx_prbs(srds_access_t *sa__, enum srds_prbs_polynomial_enum prbs_poly_mode, uint8_t prbs_inv) {
    218     uint8_t poly_mode_lsb;
    219     poly_mode_lsb = prbs_poly_mode & 0x7;
    220 
    221   EFUN(wr_prbs_gen_mode_sel((uint8_t)poly_mode_lsb));   /* PRBS Generator mode sel */
    222   EFUN(wr_prbs_gen_inv(prbs_inv));                      /* PRBS Invert Enable/Disable */
    223   /* To enable PRBS Generator */
    224   /* EFUN(wr_prbs_gen_en(0x1)); */
    225   return (ERR_CODE_NONE);
    226 }
    227 
    228 err_code_t merlin16_get_tx_prbs_config(srds_access_t *sa__, enum srds_prbs_polynomial_enum *prbs_poly_mode, uint8_t *prbs_inv) {
    229     uint8_t val;
    230 
    231   ESTM(val = rd_prbs_gen_mode_sel());                   /* PRBS Generator mode sel */
    232   *prbs_poly_mode = (enum srds_prbs_polynomial_enum)val;
    233   ESTM(val = rd_prbs_gen_inv());                        /* PRBS Invert Enable/Disable */
    234   *prbs_inv = val;
    235 
    236   return (ERR_CODE_NONE);
    237 }
    238 
    239 /* PRBS Generator Enable/Disable */
    240 err_code_t merlin16_tx_prbs_en(srds_access_t *sa__, uint8_t enable) {
    241 
    242   if (enable) {
    243     EFUN(wr_prbs_gen_en(0x1));                          /* Enable PRBS Generator */
    244   }
    245   else {
    246     EFUN(wr_prbs_gen_en(0x0));                          /* Disable PRBS Generator */
    247   }
    248   return (ERR_CODE_NONE);
    249 }
    250 
    251 /* Get PRBS Generator Enable/Disable */
    252 err_code_t merlin16_get_tx_prbs_en(srds_access_t *sa__, uint8_t *enable) {
    253 
    254   ESTM(*enable = rd_prbs_gen_en());
    255 
    256   return (ERR_CODE_NONE);
    257 }
    258 
    259 /* PRBS 1-bit error injection */
    260 err_code_t merlin16_tx_prbs_err_inject(srds_access_t *sa__, uint8_t enable) {
    261   /* PRBS Error Insert.
    262      0 to 1 transition on this signal will insert single bit error in the MSB bit of the data bus.
    263      Reset value is 0x0.
    264   */
    265   if(enable)
    266     EFUN(wr_prbs_gen_err_ins(0x1));
    267   EFUN(wr_prbs_gen_err_ins(0));
    268   return (ERR_CODE_NONE);
    269 }
    270 
    271 /* Configure PRBS Checker */
    272 err_code_t merlin16_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) {
    273     uint8_t dig_lpbk = 0;
    274     uint8_t poly_mode_lsb;
    275     poly_mode_lsb = prbs_poly_mode & 0x7;
    276 
    277     EFUN(wr_prbs_chk_mode_sel((uint8_t)poly_mode_lsb));  /* PRBS Checker Polynomial mode sel  */
    278     EFUN(wr_prbs_chk_mode((uint8_t)prbs_checker_mode));  /* PRBS Checker mode sel (PRBS LOCK state machine select) */
    279     ESTM(dig_lpbk = rd_dig_lpbk_en());
    280     if(dig_lpbk == 0) {
    281         /* Only enable auto mode in non-digital loop-back mode */
    282         EFUN(wr_prbs_chk_en_auto_mode(0x1));                 /* PRBS Checker enable control - rx_dsc_lock & prbs_chk_en */
    283     }
    284     EFUN(wr_prbs_chk_inv(prbs_inv));                     /* PRBS Invert Enable/Disable */
    285   /* To enable PRBS Checker */
    286   /* EFUN(wr_prbs_chk_en(0x1)); */
    287   return (ERR_CODE_NONE);
    288 }
    289 
    290 /* get PRBS Checker */
    291 err_code_t merlin16_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) {
    292   uint8_t val;
    293 
    294     ESTM(val = rd_prbs_chk_mode_sel());                 /* PRBS Checker Polynomial mode sel  */
    295     *prbs_poly_mode = (enum srds_prbs_polynomial_enum)val;
    296 
    297     ESTM(val = rd_prbs_chk_mode());                     /* PRBS Checker mode sel (PRBS LOCK state machine select) */
    298     *prbs_checker_mode = (enum srds_prbs_checker_mode_enum)val;
    299     ESTM(val = rd_prbs_chk_inv());                      /* PRBS Invert Enable/Disable */
    300     *prbs_inv = val;
    301   return (ERR_CODE_NONE);
    302 }
    303 
    304 /* PRBS Checker Enable/Disable */
    305 err_code_t merlin16_rx_prbs_en(srds_access_t *sa__, uint8_t enable) {
    306 
    307     if (enable) {
    308         EFUN(wr_prbs_chk_burst_err_cnt_en(0x1));            /* Must be enabled before prbs_chk_en */
    309         EFUN(wr_prbs_chk_en(0x1));                          /* Enable PRBS Checker */
    310     }
    311     else {
    312         EFUN(wr_prbs_chk_en(0x0));                          /* Disable PRBS Checker */
    313         EFUN(wr_prbs_chk_burst_err_cnt_en(0x0));
    314     }
    315     return (ERR_CODE_NONE);
    316 }
    317 
    318 err_code_t merlin16_get_rx_prbs_en(srds_access_t *sa__, uint8_t *enable) {
    319 
    320     ESTM(*enable = rd_prbs_chk_en());
    321     return (ERR_CODE_NONE);
    322 }
    323 
    324 
    325 /* PRBS Checker Lock State */
    326 err_code_t merlin16_prbs_chk_lock_state(srds_access_t *sa__, uint8_t *chk_lock) {
    327     if(!chk_lock) {
    328         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    329     }
    330 
    331     ESTM(*chk_lock = rd_prbs_chk_lock());                  /* PRBS Checker Lock Indication 1 = Locked, 0 = Out of Lock */
    332     return (ERR_CODE_NONE);
    333 }
    334 
    335 /* PRBS Error Count and Lock Lost (bit 31 in lock lost) */
    336 err_code_t merlin16_prbs_err_count_ll(srds_access_t *sa__, uint32_t *prbs_err_cnt) {
    337     uint16_t rddata;
    338 
    339     if(!prbs_err_cnt) {
    340         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    341     }
    342     ESTM(rddata = REG_RD_TLB_RX_PRBS_CHK_ERR_CNT_MSB_STATUS());
    343     *prbs_err_cnt = ((uint32_t) rddata)<<16;
    344     ESTM(*prbs_err_cnt = (*prbs_err_cnt | rd_prbs_chk_err_cnt_lsb()));
    345     return (ERR_CODE_NONE);
    346 }
    347 
    348 /* PRBS Error Count State  */
    349 err_code_t merlin16_prbs_err_count_state(srds_access_t *sa__, uint32_t *prbs_err_cnt, uint8_t *lock_lost) {
    350     uint8_t dig_lpbk_enable = 0;
    351     uint8_t link_training_enable = 0;
    352     if(!prbs_err_cnt || !lock_lost) {
    353         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    354     }
    355     EFUN(merlin16_prbs_err_count_ll(sa__, prbs_err_cnt));
    356     *lock_lost    = (*prbs_err_cnt >> 31);
    357     *prbs_err_cnt = (*prbs_err_cnt & 0x7FFFFFFF);
    358 
    359     /* Check if Digital Loopback and LinkTrainig both are enabled */
    360     ESTM(dig_lpbk_enable = rd_dig_lpbk_en());
    361 
    362     ESTM(link_training_enable = rd_cl72_ieee_training_enable());
    363     if(dig_lpbk_enable && link_training_enable) {
    364         EFUN_PRINTF(("WARNING: PRBS Check Lock - Digital Loopback and Link Training both are enabled\n"));
    365     }
    366     return (ERR_CODE_NONE);
    367 }
    368 
    369 
    370 /* toggle checker enable to start hardware timers and error counters */
    371 err_code_t merlin16_prbs_chk_en_toggle(srds_access_t *sa__) {
    372     EFUN(wr_prbs_chk_en(0));
    373     EFUN(wr_prbs_chk_en(1));
    374     return ERR_CODE_NONE;
    375 }
    376 
    377 err_code_t merlin16_display_detailed_prbs_state_hdr(void) {
    378     EFUN_PRINTF(("\nPRBS DETAILED DISPLAY :\n"));
    379 
    380 /* Comment out display of PRBS burst error if BLACKHAWK */
    381     EFUN_PRINTF((" LN TX-Mode TX-PRBS-Inv TX-PMD-Inv RX-Mode RX-PRBS-Inv RX-PMD-Inv Lck LL PRBS-Err-Cnt Burst-Err"));
    382     EFUN_PRINTF(("     BER\n"));
    383     return (ERR_CODE_NONE);
    384 }
    385 
    386   const char* merlin16_e2s_prbs_mode_enum[8] = {
    387     " PRBS_7",
    388     " PRBS_9",
    389     "PRBS_11",
    390     "PRBS_15",
    391     "PRBS_23",
    392     "PRBS_31",
    393     "PRBS_58",
    394     "  ERR  "
    395   };
    396 
    397 err_code_t merlin16_display_detailed_prbs_state(srds_access_t *sa__) {
    398     uint32_t err_cnt = 0;
    399     uint8_t lock_lost = 0;
    400     uint8_t enabled;
    401 
    402     ESTM_PRINTF(("  %d ",merlin16_get_lane(sa__)));
    403 
    404     ESTM(enabled = rd_prbs_gen_en());
    405     if(enabled) {
    406         enum srds_prbs_polynomial_enum prbs_poly_mode = PRBS_7;
    407         uint8_t prbs_inv = 0;
    408         char *prbs_string;
    409         EFUN(merlin16_get_tx_prbs_config(sa__, &prbs_poly_mode, &prbs_inv));
    410         prbs_string = (char *)merlin16_e2s_prbs_mode_enum[prbs_poly_mode];
    411         ESTM_PRINTF(("%s",prbs_string));
    412         ESTM_PRINTF(("      %1d     ",prbs_inv));
    413     } else {
    414         EFUN_PRINTF(("  OFF  "));
    415         ESTM_PRINTF(("      -     "));
    416     }
    417     ESTM_PRINTF(("     %1d     ",rd_tx_pmd_dp_invert()));
    418 
    419     ESTM(enabled = rd_prbs_chk_en());
    420     if(enabled) {
    421         enum srds_prbs_polynomial_enum prbs_poly_mode = PRBS_7;
    422         enum srds_prbs_checker_mode_enum prbs_checker_mode;
    423         uint8_t prbs_inv = 0;
    424         char *prbs_string;
    425         EFUN(merlin16_get_rx_prbs_config(sa__, &prbs_poly_mode, &prbs_checker_mode, &prbs_inv));
    426         prbs_string = (char *)merlin16_e2s_prbs_mode_enum[prbs_poly_mode];
    427         ESTM_PRINTF((" %s",prbs_string));
    428         ESTM_PRINTF(("      %1d     ",prbs_inv));
    429     } else {
    430         EFUN_PRINTF(("   OFF  "));
    431         ESTM_PRINTF(("      -     "));
    432     }
    433 
    434     ESTM_PRINTF(("     %1d     ",rd_rx_pmd_dp_invert()));
    435     ESTM_PRINTF(("  %d ",rd_prbs_chk_lock()));
    436     EFUN(merlin16_prbs_err_count_state(sa__,&err_cnt,&lock_lost));
    437     EFUN_PRINTF(("  %d  %010d ",lock_lost,err_cnt));
    438     ESTM_PRINTF(("    %4d  ",rd_prbs_chk_burst_err_cnt()));
    439     EFUN(merlin16_INTERNAL_display_BER(sa__,100));
    440     EFUN_PRINTF(("\n"));
    441 
    442     return (ERR_CODE_NONE);
    443 }
    444 
    445 
    446 
    447