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_pcieg3_prbs.c (16408B)


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