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

tomahawk3_ep_init.c (42955B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        tomahawk3_ep_init.c
      8  * Purpose:
      9  * Requires:
     10  */
     11 
     12 
     13 #include <shared/bsl.h>
     14 #include <soc/tdm/core/tdm_top.h>
     15 
     16 #include <soc/defs.h>
     17 #include <soc/mem.h>
     18 
     19 #if defined(BCM_TOMAHAWK3_SUPPORT)
     20 
     21 #include <soc/init/tomahawk3_ep_init.h>
     22 #include <soc/flexport/flexport_common.h>
     23 #include <soc/init/tomahawk3_tdm.h>
     24 
     25 /*** START SDK API COMMON CODE ***/
     26 
     27 
     28 #define TH3_EP_SLOT_LAT_DPP_LATENCY_W_EFP    51
     29 #define TH3_EP_SLOT_LAT_DPP_LATENCY_WO_EFP   37
     30 #define TH3_EP_SLOT_LAT_CREDIT_LOOP          12
     31 #define TH3_EP_SLOT_LAT_EXTRA_LAT_EARB_DPP    3
     32 #define TH3_EP_SLOT_LAT_DOMAIN_CROSSING       3
     33 #define TH3_EP_SLOT_LAT_OUTSTANDING_CREDIT   21
     34 #define TH3_EP_SLOT_LAT_DEF_MARGIN            3
     35 #define TH3_EP_SLOT_LAT_MAX_ACCUM_DPPR_1      4
     36 #define TH3_EP_MAX_CT_CLASSES                16
     37 #define TH3_EP_NUM_CT_CLASSES                 8
     38 
     39 /* EP2MMU credits for Aux ports */
     40 #define TH3_EP_EP2MMU_CRED_CPU               13
     41 #define TH3_EP_EP2MMU_CRED_MGM                8
     42 #define TH3_EP_EP2MMU_CRED_LBK               48
     43 
     44 #define TH3_EP_XMIT_START_CNT_MGM            12
     45 
     46 /*! @file tomahawk3_ep_init.c
     47  *  @brief EP (EDB) Init/FlexPort APIs for Tomahawk2.
     48  *  Details are shown below.
     49  */
     50 
     51 
     52 /* EDB Credits and XMIT_CNT Table  */
     53 static const soc_th3_ep_core_cfg_t
     54     soc_th3_ep_core_cfg_tbl[] = {
     55    /* speed   ct    ep2mmu   ep2mmu     xmit_cnt
     56    *         class  credits  credits
     57    *                general optimized   saf  ct
     58    */
     59     {     0,   0,     0,       0,     {{ 0,  0}} },   /*  SAF  */
     60     { 10000,   1,     8,       7,     {{ 4, 23}} },   /* 10GE  */
     61     { 25000,   2,    15,      11,     {{10, 43}} },   /* 25GE  */
     62     { 40000,   3,    20,      14,     {{16, 26}} },   /* 40GE  */
     63     { 50000,   4,    28,      20,     {{20, 85}} },   /* 50GE  */
     64     {100000,   5,    57,      42,     {{23, 54}} },   /* 100GE */
     65     {200000,   6,   100,      71,     {{28, 65}} },   /* 200GE */
     66     {400000,   7,   142,     110,     {{29, 57}} }    /* 400GE */
     67 };
     68 
     69 
     70 /*! @fn int soc_tomahawk3_div_round_up(
     71  *    int nominator,
     72  *    int denominator)
     73  *  @param int nominator
     74  *  @param int denominator
     75  *  @brief API for round int division
     76  * Description:
     77  *      round int division
     78  */
     79 static int soc_tomahawk3_div_round_up(
     80     int nominator,
     81     int denominator)
     82 {
     83     if (denominator == 0) { return 1; }
     84 
     85     return ( (nominator + denominator - 1) / denominator );
     86 }
     87 
     88 
     89 /*! @fn int soc_tomahawk3_div_round(
     90  *    int nominator,
     91  *    int denominator)
     92  *  @param int nominator
     93  *  @param int denominator
     94  *  @brief API for round int division
     95  * Description:
     96  *      round int division
     97  */
     98 int soc_tomahawk3_div_round(
     99     int nominator,
    100     int denominator)
    101 {
    102     int modulo;
    103 
    104     if (denominator == 0) { return 1; }
    105 
    106     modulo = nominator % denominator;
    107 
    108     if (modulo >= ((denominator + 1) / 2)) {
    109         return ( (nominator + denominator - 1) / denominator );
    110     } else {
    111         return ( nominator / denominator );
    112     }
    113 }
    114 
    115 
    116 /*! @fn int soc_tomahawk3_get_set_slot_pipeline_latency()
    117  * Return Value:
    118  *      SOC_E_*
    119  * Description:
    120  * Input parameters:
    121  * Core frequency
    122  * Dpp Frequency
    123  * DPP Latency (DPPL)
    124  * Extra latency in DPP clk (A)
    125  * Domain crossing for output event fifo(B)
    126  * N - Credit loop (12)
    127  * C - Outstanding Credit (20)
    128  * Default margin (D)
    129  * Early retrieval in core clk (E)
    130  */
    131 int soc_tomahawk3_get_set_slot_pipeline_latency(
    132     int core_freq,
    133     int dpp_freq,
    134     int dppl,
    135     int A_in,
    136     int B_in,
    137     int N_in,
    138     int C_in,
    139     int D_in,
    140     int E_in,
    141     int *slot_latency)
    142 {
    143     int max_accum_latency;
    144 
    145     *slot_latency = soc_tomahawk3_div_round(((dppl + A_in + B_in) * core_freq), dpp_freq);
    146 
    147     max_accum_latency  = (core_freq == dpp_freq) ? TH3_EP_SLOT_LAT_MAX_ACCUM_DPPR_1 :
    148        soc_tomahawk3_div_round_up(core_freq *
    149        (C_in + TH3_EP_SLOT_LAT_MAX_ACCUM_DPPR_1), dpp_freq)
    150         - N_in;
    151 
    152     *slot_latency += D_in + E_in + max_accum_latency;
    153 
    154     return SOC_E_NONE;
    155 }
    156 
    157 
    158 /*! @fn int soc_tomahawk3_ep_set_slot_pipeline_config(
    159  *    int unit,
    160  *    soc_port_schedule_state_t *port_schedule_state,
    161  *    int pipe_num)
    162  *  @param unit Chip unit number.
    163  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    164  *             struct variable.
    165  *  @param pipe pipe number.
    166  *  @brief API to initialize EPOST_SLOT_PIPELINE_CONFIG
    167  * Description:
    168  *      API to initialize EPOST_SLOT_PIPELINE_CONFIG
    169  *      Regs/Mems configured: EP-EARB
    170  * Parameters:
    171  *      unit - Device number
    172  *      *port_schedule_state_t - Agreed structure between SDK and DV
    173  * Return Value:
    174  *      SOC_E_*
    175  */
    176 int soc_tomahawk3_ep_set_slot_pipeline_config(
    177     int unit,
    178     soc_port_schedule_state_t *port_schedule_state)
    179 {
    180     soc_reg_t reg;
    181     uint32 rval;
    182     int dpp_clks_latency = 0;
    183     int core_clks_latency, bypass_mode = 0;
    184     int core_clock_freq, dpp_clock_freq;
    185 
    186     reg = EPOST_SLOT_PIPELINE_CONFIGr;
    187 
    188     /*
    189      * slot_latency = ROUND[ (DPPL + A + B) * R] + M + D
    190      * DPPL - DPP Latency                     (FULL = 57; EFP BYPASS = 44)
    191      * A    - Latency due to async interfaces in between Earb and DPP (6)
    192      * B    - Domain crossing for output event fifo                   (3)
    193      * M    - Maximum latency  - see formula
    194      * D    - Default margin. This should be the minimal number that the
    195      *         DPP can work properly in order to have minimal latency (5)
    196      * R    - dpp ratio = (Foreq_core / Freq_dpp)
    197      *
    198      *
    199      * M = ( R == 1) ? 4 : ROUND_UP[R*(N*(R-1)/R + C - N  + 4)]
    200      *    N - Credit loop (12)
    201      *    C - Outstanding Credit (20)
    202      */
    203 
    204 
    205     /* Set the latency in Slot Pipeline config register, need to be
    206      * programmed before any traffic going through the EP */
    207     rval = 0;
    208     bypass_mode = soc_property_get(unit, spn_SWITCH_BYPASS_MODE, SOC_SWITCH_BYPASS_MODE_NONE);
    209     if (bypass_mode == 3) {
    210         /* w/o EFP */
    211         dpp_clks_latency = TH3_EP_SLOT_LAT_DPP_LATENCY_WO_EFP;
    212     } else {
    213         /* w/ EFP */
    214         dpp_clks_latency = TH3_EP_SLOT_LAT_DPP_LATENCY_W_EFP;
    215     }
    216 
    217     core_clock_freq = port_schedule_state->frequency;
    218     dpp_clock_freq = port_schedule_state->in_port_map.port_p2PBLK_inst_mapping[0];
    219 
    220     soc_tomahawk3_get_set_slot_pipeline_latency(
    221         core_clock_freq,
    222         dpp_clock_freq,
    223         dpp_clks_latency,                     /* DPP Latency (DPPL) */
    224         TH3_EP_SLOT_LAT_EXTRA_LAT_EARB_DPP,   /* Extra latency in DPP clk (A) */
    225         TH3_EP_SLOT_LAT_DOMAIN_CROSSING,      /* Domain crossing for output event fifo(B) */
    226         TH3_EP_SLOT_LAT_CREDIT_LOOP,          /* N - Credit loop (12) */
    227         TH3_EP_SLOT_LAT_OUTSTANDING_CREDIT,   /* C - Outstanding Credit (20) */
    228         TH3_EP_SLOT_LAT_DEF_MARGIN,           /*  Default margin (D) */
    229         0,                                    /* Early retrieval in core clk (E); 0 for EP*/
    230         &core_clks_latency);
    231 
    232     soc_reg_field_set(unit, reg, &rval, WR_ENf, 0);
    233     soc_reg_field_set(unit, reg, &rval, LATENCYf, core_clks_latency);
    234     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    235 
    236     soc_reg_field_set(unit, reg, &rval, WR_ENf, 1);
    237     soc_reg_field_set(unit, reg, &rval, LATENCYf, core_clks_latency);
    238     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    239 
    240     return SOC_E_NONE;
    241 }
    242 
    243 
    244 /*! @fn int soc_tomahawk3_ep_set_dev_to_phy(
    245  *    int unit,
    246  *    soc_port_schedule_state_t *port_schedule_state,
    247  *    int pipe,
    248  *    int phy_port,
    249  *    int is_port_down)
    250  *  @param unit Chip unit number.
    251  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    252  *             struct variable.
    253  *  @param pipe pipe number.
    254  *  @param phy_port phy_port to configure.
    255  *  @param phy_port is_port_down. boolean to indicate if port goes down
    256  *  @brief API to initialize/clear per port EDB_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPING
    257  * Description:
    258  *      API to initialize/clear per port EDB_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPING
    259  *      Regs/Mems configured: EDB
    260  * Parameters:
    261  *      unit - Device number
    262  *      *port_schedule_state_t - Agreed structure between SDK and DV
    263  * Return Value:
    264  *      SOC_E_*
    265  */
    266 int soc_tomahawk3_ep_set_dev_to_phy(
    267     int unit,
    268     soc_port_schedule_state_t *port_schedule_state,
    269     int pipe_num,
    270     int phy_port,
    271     int is_port_down)
    272 {
    273     soc_mem_t mem;
    274     uint32 memfld;
    275     uint32 entry[SOC_MAX_MEM_WORDS];
    276     int logical_port;
    277 
    278     mem = EDB_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGm;
    279     if (0 == is_port_down) {
    280         logical_port = port_schedule_state->out_port_map.port_p2l_mapping[phy_port];
    281         memfld = phy_port;
    282     } else {
    283         logical_port = port_schedule_state->in_port_map.port_p2l_mapping[phy_port];
    284         memfld = 0x1FF;
    285     }
    286     sal_memset(entry, 0, sizeof(uint32) *
    287            soc_mem_entry_words(unit, EDB_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGm));
    288     soc_mem_field_set(unit, mem, entry, DATAf, &memfld);
    289 
    290     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, logical_port,
    291                                   entry));
    292 
    293     return SOC_E_NONE;
    294 }
    295 
    296 /*! @fn int soc_tomahawk3_ep_set_mmu_cell_credit(
    297  *    int unit,
    298  *    soc_port_schedule_state_t *port_schedule_state,
    299  *    int pipe,
    300  *    int phy_port,
    301  *    int is_port_down)
    302  *  @param unit Chip unit number.
    303  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    304  *             struct variable.
    305  *  @param pipe pipe number.
    306  *  @param phy_port phy_port to configure.
    307  *  @param phy_port is_port_down. boolean to indicate if port goes down
    308  *  @brief API to initialize/clear per port EGR_MMU_CELL_CREDIT
    309  * Description:
    310  *      API to initialize/clear per port EGR_MMU_CELL_CREDIT
    311  *      Regs/Mems configured: EDB
    312  * Parameters:
    313  *      unit - Device number
    314  *      *port_schedule_state_t - Agreed structure between SDK and DV
    315  * Return Value:
    316  *      SOC_E_*
    317  */
    318 int soc_tomahawk3_ep_set_mmu_cell_credit(
    319     int unit,
    320     soc_port_schedule_state_t *port_schedule_state,
    321     int pipe_num,
    322     int phy_port,
    323     int is_port_down)
    324 {
    325     uint32 entry[SOC_MAX_MEM_WORDS];
    326     uint32 memfld;
    327     soc_mem_t mem;
    328 
    329     if (0 == is_port_down) { /* port up */
    330         memfld = soc_tomahawk3_ep_get_ep2mmu_credit(unit, port_schedule_state,
    331                                                     phy_port);
    332     } else {                /* port down */
    333         memfld = 0;
    334     }
    335 
    336     mem = EGR_MMU_CELL_CREDITm;
    337     sal_memset(entry, 0, sizeof(uint32) *
    338                soc_mem_entry_words(unit, EGR_MMU_CELL_CREDITm));
    339     soc_mem_field_set(unit, mem, entry, CREDITf, &memfld);
    340     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, phy_port,
    341                                       entry));
    342     return SOC_E_NONE;
    343 }
    344 
    345 
    346 /*! @fn int soc_tomahawk3_get_freq_encoding(
    347  *    int unit,
    348  *    soc_port_schedule_state_t *port_schedule_state)
    349  *  @param unit Chip unit number.
    350  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    351  *             struct variable.
    352  *  Calculates index into xmit_cnt_per_freq array
    353  *  Return Value:
    354  *      SOC_E_*
    355  */
    356 static int soc_tomahawk3_get_freq_encoding(
    357     int unit,
    358     soc_port_schedule_state_t *port_schedule_state,
    359     int *freq_encoding)
    360 {
    361 
    362     /* All Core/PP frequencies have the same settings for xmit_cnt */
    363     *freq_encoding = 0;
    364     return SOC_E_NONE;
    365 }
    366 
    367 
    368 /*! @fn int soc_tomahawk3_get_speed_encoding(
    369  *  int speed,
    370  *  int *speed_encoding)
    371  *  @param speed Speed
    372  *  @param *speed_encoding speed encoding
    373  *  @brief Helper function to get CT class
    374  */
    375 int
    376 soc_tomahawk3_get_speed_encoding(
    377     int speed,
    378     int *speed_encoding)
    379 {
    380     *speed_encoding = 0;
    381     switch (speed) {
    382     case 10000:   *speed_encoding = 1; break;
    383     case 25000:   *speed_encoding = 2; break;
    384     case 40000:   *speed_encoding = 3; break;
    385     case 50000:   *speed_encoding = 4; break;
    386     case 100000:  *speed_encoding = 5; break;
    387     case 200000:  *speed_encoding = 6; break;
    388     case 400000:  *speed_encoding = 7; break;
    389     default:      return SOC_E_PARAM;  break;
    390     }
    391     return SOC_E_NONE;
    392 }
    393 
    394 /*! @fn int soc_tomahawk3_get_ct_class(int speed)
    395  *  @param speed Speed
    396  *  @brief Helper function to get CT class
    397  */
    398 int
    399 soc_tomahawk3_get_ct_class(int speed)
    400 {
    401     int speed_encoding;
    402     SOC_IF_ERROR_RETURN(
    403         soc_tomahawk3_get_speed_encoding(speed, &speed_encoding));
    404     return soc_th3_ep_core_cfg_tbl[speed_encoding].ct_class;
    405 }
    406 
    407 /*! @fn int soc_tomahawk3_ep_get_ep2mmu_credit(int unit,
    408  *              soc_port_schedule_state_t *port_schedule_state, int phy_port)
    409  *  @param unit Chip unit number.
    410  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t struct
    411  *         variable
    412  *  @param logical_port Dev port num
    413  *  @param ovs_ratio ovs_ratio inside {10-LR, 15-OVS 3:2, 20- OVS 2:1}
    414  *  @brief Helper function to get EP2MMU credit for a port;
    415  * This API assumes that credits were retrieved for active ports after FlexPort
    416  */
    417 int
    418 soc_tomahawk3_ep_get_ep2mmu_credit(
    419     int unit, soc_port_schedule_state_t *port_schedule_state, int phy_port)
    420 {
    421     int logical_port, speed;
    422     int ep2mmu_credit = 0;
    423 
    424     if (_TH3_PHY_IS_FRONT_PANEL_PORT(phy_port)) {
    425         /* Either Init or FlexPort, out_port_map should be used
    426          * since this function is called only on port up */
    427         logical_port =
    428             port_schedule_state->out_port_map.port_p2l_mapping[phy_port];
    429         speed = port_schedule_state->out_port_map.log_port_speed[logical_port];
    430         SOC_IF_ERROR_RETURN(
    431             soc_tomahawk3_ep_get_ep2mmu_credit_per_speed(
    432                 unit, port_schedule_state, speed, &ep2mmu_credit));
    433     } else if (phy_port == _TH3_PHY_PORT_CPU) {
    434         ep2mmu_credit = TH3_EP_EP2MMU_CRED_CPU; /* CPU credits for 25G */
    435     } else if ((phy_port == _TH3_PHY_PORT_MNG0) ||
    436                  (phy_port == _TH3_PHY_PORT_MNG1) ) {
    437         ep2mmu_credit = TH3_EP_EP2MMU_CRED_MGM; /* MGM credits for 10G */
    438     } else if ( (phy_port >=  _TH3_PHY_PORT_LPBK0) &&
    439                 (phy_port <=  _TH3_PHY_PORT_LPBK7) ) {
    440         ep2mmu_credit = TH3_EP_EP2MMU_CRED_LBK; /* LBK credits for >100G */
    441     }
    442 
    443     return ep2mmu_credit;
    444 }
    445 
    446 /*! @fn int soc_tomahawk3_ep_get_ep2mmu_credit_per_speed(int unit,
    447  *              soc_port_schedule_state_t *port_schedule_state,
    448  *              int speed, int *credit)
    449  */
    450 int
    451 soc_tomahawk3_ep_get_ep2mmu_credit_per_speed(
    452     int unit,
    453     soc_port_schedule_state_t *port_schedule_state,
    454     int speed,
    455     int *credit)
    456 {
    457     int speed_encoding;
    458     int core_clock_freq, dpp_clock_freq;
    459 
    460     core_clock_freq = port_schedule_state->frequency;
    461     dpp_clock_freq = port_schedule_state->in_port_map.port_p2PBLK_inst_mapping[0];
    462 
    463     SOC_IF_ERROR_RETURN(
    464         soc_tomahawk3_get_speed_encoding(speed, &speed_encoding));
    465 
    466     if ((core_clock_freq == 1325) &&
    467         (dpp_clock_freq  == 1000)) {  /* PFC optimized for 1325/1000 */
    468         *credit = soc_th3_ep_core_cfg_tbl[speed_encoding].egr_mmu_credit_pfc_opt;
    469     } else {
    470         *credit = soc_th3_ep_core_cfg_tbl[speed_encoding].egr_mmu_credit;
    471     }
    472 
    473     return SOC_E_NONE;
    474 }
    475 
    476 
    477 /*! @fn int soc_tomahawk3_ep_set_ct_class(
    478  *    int unit,
    479  *    soc_port_schedule_state_t *port_schedule_state,
    480  *    int pipe,
    481  *    int phy_port,
    482  *    int is_port_down)
    483  *  @param unit Chip unit number.
    484  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    485  *             struct variable.
    486  *  @param pipe pipe number.
    487  *  @param phy_port phy_port to configure.
    488  *  @param phy_port is_port_down. boolean to indicate if port goes down
    489  *  @brief API to initialize/clear per port EGR_MMU_CELL_CREDIT
    490  * Description:
    491  *      API to initialize/clear per port EGR_MMU_CELL_CREDIT
    492  *      Regs/Mems configured: EDB
    493  * Parameters:
    494  *      unit - Device number
    495  *      *port_schedule_state_t - Agreed structure between SDK and DV
    496  * Return Value:
    497  *      SOC_E_*
    498  */
    499 int soc_tomahawk3_ep_set_ct_class(
    500     int unit,
    501     soc_port_schedule_state_t *port_schedule_state,
    502     int pipe_num,
    503     int phy_port,
    504     int is_port_down)
    505 {
    506     soc_mem_t mem;
    507     uint32 memfld;
    508     uint32 entry[SOC_MAX_MEM_WORDS];
    509     int logical_port, speed;
    510 
    511     /* Only Front Panel ports have CT configured */
    512     if (!_TH3_PHY_IS_FRONT_PANEL_PORT(phy_port)) { return SOC_E_NONE; }
    513 
    514     mem = EDB_IP_CUT_THRU_CLASSm;
    515     logical_port =
    516         port_schedule_state->out_port_map.port_p2l_mapping[phy_port];
    517     if (0 == is_port_down) {
    518         speed = port_schedule_state->out_port_map.log_port_speed[logical_port];
    519         memfld = soc_tomahawk3_get_ct_class(speed);
    520     } else {
    521         /* FlexPort doesn't need to reset the entry when port goes down;
    522          * needs to be touched when port goes up */
    523         memfld = 0;
    524     }
    525     sal_memset(entry, 0, sizeof(uint32) *
    526            soc_mem_entry_words(unit, EDB_IP_CUT_THRU_CLASSm));
    527     soc_mem_field_set(unit, mem, entry, CUT_THRU_CLASSf, &memfld);
    528 
    529     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, logical_port,
    530                                   entry));
    531     return SOC_E_NONE;
    532 }
    533 
    534 
    535 /*! @fn int soc_tomahawk3_ep_set_xmit_start_cnt(
    536  *    int unit,
    537  *    soc_port_schedule_state_t *port_schedule_state,
    538  *    int pipe,
    539  *    int phy_port,
    540  *    int is_port_down)
    541  *  @param unit Chip unit number.
    542  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    543  *             struct variable.
    544  *  @param pipe pipe number.
    545  *  @param phy_port phy_port to configure.
    546  *  @param phy_port is_port_down. boolean to indicate if port goes down
    547  *  @brief API to initialize/clear per port EDB_XMIT_START_COUNT
    548  * Description:
    549  *      API to initialize/clear per port EDB_XMIT_START_COUNT
    550  *      Regs/Mems configured: EDB
    551  * Parameters:
    552  *      unit - Device number
    553  *      *port_schedule_state_t - Agreed structure between SDK and DV
    554  * Return Value:
    555  *      SOC_E_*
    556  */
    557 int soc_tomahawk3_ep_set_xmit_start_cnt(
    558     int unit,
    559     soc_port_schedule_state_t *port_schedule_state,
    560     int pipe_num,
    561     int phy_port,
    562     int is_port_down)
    563 {
    564     soc_mem_t mem;
    565     int pipe, class, mem_index;
    566     uint32 memfld;
    567     uint32 entry[SOC_MAX_MEM_WORDS];
    568     int xmit_start_cnt[TH3_EP_MAX_CT_CLASSES];
    569     soc_port_map_type_t *port_map;
    570     int logical_port;
    571     static const soc_mem_t ep_xmit_cnt_mems[_TH3_PIPES_PER_DEV] = {
    572         EDB_XMIT_START_COUNT_PIPE0m, EDB_XMIT_START_COUNT_PIPE1m,
    573         EDB_XMIT_START_COUNT_PIPE2m, EDB_XMIT_START_COUNT_PIPE3m,
    574         EDB_XMIT_START_COUNT_PIPE4m, EDB_XMIT_START_COUNT_PIPE5m,
    575         EDB_XMIT_START_COUNT_PIPE6m, EDB_XMIT_START_COUNT_PIPE7m
    576     };
    577 
    578     /* Set reg's variables */
    579     if (1 == is_port_down) { /* in_port_map used at port down */
    580         port_map = &port_schedule_state->in_port_map;
    581     } else {                 /* out_port_map used at port up */
    582         port_map = &port_schedule_state->out_port_map;
    583     }
    584 
    585     logical_port = port_map->port_p2l_mapping[phy_port];
    586     pipe = logical_port / _TH3_DEV_PORTS_PER_PIPE;
    587 
    588     /* Set all XMIT START CNT values for a port; 0-SAF; 1-12 CT classes;
    589      * 13-15 reserved
    590      */
    591     mem = ep_xmit_cnt_mems[pipe];
    592 
    593     if (1 == is_port_down) {
    594         for (class = 0; class < TH3_EP_MAX_CT_CLASSES; class++) {
    595             xmit_start_cnt[class] = 0;
    596         }
    597     } else {
    598         soc_tomahawk3_ep_get_xmit_start_count(unit, port_schedule_state,
    599                                           logical_port,
    600                                           xmit_start_cnt);
    601     }
    602 
    603     for (class = 0; class < TH3_EP_NUM_CT_CLASSES; class++) {
    604         sal_memset(entry, 0, sizeof(uint32) *
    605                    soc_mem_entry_words(unit, EDB_XMIT_START_COUNT_PIPE0m));
    606         mem_index = (logical_port % _TH3_DEV_PORTS_PER_PIPE) * TH3_EP_MAX_CT_CLASSES + class;
    607         memfld = xmit_start_cnt[class];
    608         soc_mem_field_set(unit, mem, entry, THRESHOLDf, &memfld);
    609         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_index,
    610                                           entry));
    611     }
    612 
    613     return SOC_E_NONE;
    614 }
    615 
    616 
    617 /*! @fn int soc_tomahawk3_ep_get_xmit_start_count(int unit,
    618  *              soc_port_schedule_state_t *port_schedule_state,
    619  *              int logical_port, int *xmit_start_cnt)
    620  *  @param unit Chip unit number.
    621  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t struct
    622  *             variable
    623  *  @param logical_port Dev port num
    624  *  @param xmit_start_cnt array of 16 entries 0-SAF; 1-12 CT; 13-15 Unused
    625  *  @brief Helper function to get XMIT_START_CNT array for a port;
    626  * This API assumes that credits were retrieved for active ports after FlexPort
    627  */
    628 int
    629 soc_tomahawk3_ep_get_xmit_start_count(
    630     int  unit, soc_port_schedule_state_t *port_schedule_state,
    631     int  logical_port, int *xmit_start_cnt)
    632 {
    633     int dst_ct_class, src_ct_class;
    634     int speed, speed_encoding, freq_encoding;
    635     int saf_xmit_start_cnt, dst_ct_xmit_start_cnt;
    636     int phy_port;
    637 
    638     phy_port = port_schedule_state->out_port_map.port_l2p_mapping[logical_port];
    639 
    640     for (src_ct_class=0; src_ct_class < TH3_EP_MAX_CT_CLASSES; src_ct_class++) {
    641         xmit_start_cnt[src_ct_class] = 0;
    642     }
    643 
    644     SOC_IF_ERROR_RETURN(
    645         soc_tomahawk3_get_freq_encoding(unit, port_schedule_state, &freq_encoding));
    646 
    647     /* Front Panel ports have SAF & CT settings */
    648     if (_TH3_PHY_IS_FRONT_PANEL_PORT(phy_port)) {
    649         speed = port_schedule_state->out_port_map.log_port_speed[logical_port];
    650         dst_ct_class = soc_tomahawk3_get_ct_class(speed);
    651 
    652         SOC_IF_ERROR_RETURN(
    653             soc_tomahawk3_get_speed_encoding(speed, &speed_encoding));
    654 
    655         saf_xmit_start_cnt =
    656             soc_th3_ep_core_cfg_tbl[speed_encoding].xmit_cnt_per_freq[freq_encoding].saf;
    657         dst_ct_xmit_start_cnt =
    658             soc_th3_ep_core_cfg_tbl[speed_encoding].xmit_cnt_per_freq[freq_encoding].ct;
    659 
    660         /* Populate xmit_start_cnt array */
    661         for (src_ct_class = 0; src_ct_class < TH3_EP_NUM_CT_CLASSES; src_ct_class++) {
    662             if (src_ct_class < dst_ct_class) {
    663                 xmit_start_cnt[src_ct_class] = saf_xmit_start_cnt;
    664             } else {
    665                 xmit_start_cnt[src_ct_class] = dst_ct_xmit_start_cnt;
    666             }
    667         }
    668     } else if ((phy_port == _TH3_PHY_PORT_MNG0) ||
    669                (phy_port == _TH3_PHY_PORT_MNG1) ) { /* 10G SAF */
    670         xmit_start_cnt[0] =
    671             TH3_EP_XMIT_START_CNT_MGM;
    672     } else { /* CMIC & LOOPBACK */
    673         xmit_start_cnt[0] = 1; /* Low threshold */
    674     }
    675 
    676     return SOC_E_NONE;
    677 }
    678 
    679 
    680 /*! @fn int soc_tomahawk3_ep_set_egr_enable(
    681  *    int unit,
    682  *    soc_port_schedule_state_t *port_schedule_state,
    683  *    int pipe,
    684  *    int phy_port,
    685  *    int is_port_down)
    686  *  @param unit Chip unit number.
    687  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    688  *             struct variable.
    689  *  @param pipe pipe number.
    690  *  @param phy_port phy_port to configure.
    691  *  @param phy_port is_port_down. boolean to indicate if port goes down
    692  *  @brief API to initialize/clear per port EGR_ENABLE
    693  * Description:
    694  *      API to initialize/clear per port EGR_ENABLE
    695  *      Regs/Mems configured: EDB
    696  * Parameters:
    697  *      unit - Device number
    698  *      *port_schedule_state_t - Agreed structure between SDK and DV
    699  * Return Value:
    700  *      SOC_E_*
    701  */
    702 int soc_tomahawk3_ep_set_egr_enable(
    703     int unit,
    704     soc_port_schedule_state_t *port_schedule_state,
    705     int pipe_num,
    706     int phy_port,
    707     int is_port_down)
    708 {
    709     uint32 entry[SOC_MAX_MEM_WORDS];
    710     uint32 memfld;
    711     soc_mem_t mem;
    712 
    713     if (0 == is_port_down ) {
    714         memfld = 1;
    715     } else {
    716         memfld = 0;
    717     }
    718     mem = EGR_ENABLEm;
    719     sal_memset(entry, 0, sizeof(uint32) * soc_mem_entry_words(unit, EGR_ENABLEm));
    720     soc_mem_field_set(unit, mem, entry, PRT_ENABLEf, &memfld);
    721     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, phy_port,
    722                                       entry));
    723     return SOC_E_NONE;
    724 }
    725 
    726 
    727 
    728 /*! @fn int soc_tomahawk3_ep_init_egr_enable(
    729  *    int unit,
    730  *    soc_port_schedule_state_t *port_schedule_state)
    731  *  @param unit Chip unit number.
    732  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    733  *             struct variable.
    734  *  @param pipe pipe number.
    735  *  @param phy_port phy_port to configure.
    736  *  @param phy_port is_port_down. boolean to indicate if port goes down
    737  *  @brief API to initialize per CHIP EGR_ENABLE
    738  * Description:
    739  *      API to initialize per CHIP EGR_ENABLE
    740  *      Regs/Mems configured: EDB
    741  * Parameters:
    742  *      unit - Device number
    743  *      *port_schedule_state_t - Agreed structure between SDK and DV
    744  * Return Value:
    745  *      SOC_E_*
    746  */
    747 int soc_tomahawk3_ep_init_egr_enable(
    748     int unit,
    749     soc_port_schedule_state_t *port_schedule_state)
    750 {
    751     uint32 port, pipe;
    752     int phy_port;
    753     int is_port_down;
    754 
    755     is_port_down = 0;
    756 
    757     /* Configure per port registers: Front Panel ports; CPU; Loopback*/
    758     for (port = 0; port < _TH3_DEV_PORTS_PER_DEV; port++) {
    759         if (port_schedule_state->out_port_map.log_port_speed[port] > 0 ) {
    760             pipe = port / _TH3_DEV_PORTS_PER_PIPE;
    761             phy_port = port_schedule_state->out_port_map.port_l2p_mapping[port];
    762             soc_tomahawk3_ep_set_egr_enable(unit, port_schedule_state,
    763                    pipe, phy_port, is_port_down);
    764         }
    765     }
    766 
    767     return SOC_E_NONE;
    768 }
    769 
    770 
    771 
    772 /*! @fn int soc_tomahawk3_ep_edb_init(
    773  *    int unit,
    774  *    soc_port_schedule_state_t *port_schedule_state)
    775  *  @param unit Chip unit number.
    776  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    777  *             struct variable.
    778  *  @param pipe pipe number.
    779  *  @param phy_port phy_port to configure.
    780  *  @param phy_port is_port_down. boolean to indicate if port goes down
    781  *  @brief API to initialize/clear per port EGR_ENABLE
    782  * Description:
    783  *      API to initialize/clear per port EGR_ENABLE
    784  *      Regs/Mems configured: EDB
    785  * Parameters:
    786  *      unit - Device number
    787  *      *port_schedule_state_t - Agreed structure between SDK and DV
    788  * Return Value:
    789  *      SOC_E_*
    790  */
    791 int soc_tomahawk3_ep_edb_init(
    792     int unit,
    793     soc_port_schedule_state_t *port_schedule_state)
    794 {
    795     uint32 port, pipe;
    796     int phy_port;
    797     int is_port_down;
    798     int rst_on;
    799 
    800     /* Toggle per port sft reset first on FP ports that are enabled */
    801     rst_on = 1; /* assert reset */
    802     for (port = 0; port < _TH3_DEV_PORTS_PER_DEV; port++) {
    803         if (port_schedule_state->out_port_map.log_port_speed[port] > 0) {
    804             pipe = port / _TH3_DEV_PORTS_PER_PIPE;
    805             phy_port = port_schedule_state->out_port_map.port_l2p_mapping[port];
    806             if (_TH3_PHY_IS_FRONT_PANEL_PORT(phy_port)) {
    807                 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_sft_rst_port(unit,
    808                                     port_schedule_state, pipe,
    809                                     phy_port, rst_on));
    810             }
    811         }
    812     }
    813 
    814     rst_on = 0; /* de-assert reset */
    815     for (port = 0; port < _TH3_DEV_PORTS_PER_DEV; port++) {
    816         if (port_schedule_state->out_port_map.log_port_speed[port] > 0) {
    817             pipe = port / _TH3_DEV_PORTS_PER_PIPE;
    818             phy_port = port_schedule_state->out_port_map.port_l2p_mapping[port];
    819             if (_TH3_PHY_IS_FRONT_PANEL_PORT(phy_port)) {
    820                 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_sft_rst_port(unit,
    821                                     port_schedule_state, pipe,
    822                                     phy_port, rst_on));
    823             }
    824         }
    825     }
    826 
    827     is_port_down = 0;
    828     /* Configure per port registers: Front Panel ports; CPU; Loopback*/
    829     for (port = 0; port < _TH3_DEV_PORTS_PER_DEV; port++) {
    830         if (port_schedule_state->out_port_map.log_port_speed[port] > 0 ) {
    831             pipe = port / _TH3_DEV_PORTS_PER_PIPE;
    832             phy_port = port_schedule_state->out_port_map.port_l2p_mapping[port];
    833             soc_tomahawk3_ep_set_dev_to_phy(unit, port_schedule_state,
    834                    pipe, phy_port, is_port_down);
    835             soc_tomahawk3_ep_set_mmu_cell_credit(unit, port_schedule_state,
    836                    pipe, phy_port, is_port_down);
    837             soc_tomahawk3_ep_set_ct_class(unit, port_schedule_state,
    838                    pipe, phy_port, is_port_down);
    839             soc_tomahawk3_ep_set_xmit_start_cnt(unit, port_schedule_state,
    840                    pipe, phy_port, is_port_down);
    841         }
    842     }
    843 
    844     return SOC_E_NONE;
    845 }
    846 
    847 
    848 
    849 /*! @fn int soc_tomahawk3_ep_init(
    850  *    int unit,
    851  *    soc_port_schedule_state_t *port_schedule_state)
    852  *  @param unit Chip unit number.
    853  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    854  *             struct variable.
    855  *  @brief API to initialize EPIPE
    856  * Description:
    857  *      API to initialize EPIPE
    858  *      Regs/Mems configured: EDB
    859  * Parameters:
    860  *      unit - Device number
    861  *      *port_schedule_state_t - Agreed structure between SDK and DV
    862  * Return Value:
    863  *      SOC_E_*
    864  */
    865 int soc_tomahawk3_ep_init(
    866     int unit,
    867     soc_port_schedule_state_t *port_schedule_state)
    868 {
    869     /* Init EDB; per port config */
    870     soc_tomahawk3_ep_edb_init(unit, port_schedule_state);
    871 
    872     /* Enable EGR ports */
    873     soc_tomahawk3_ep_init_egr_enable(unit, port_schedule_state);
    874 
    875     return SOC_E_NONE;
    876 }
    877 
    878 
    879 /*! @fn int soc_tomahawk3_ep_drain_port(
    880  *    int unit,
    881  *    soc_port_schedule_state_t *port_schedule_state)
    882  *  @param unit Chip unit number.
    883  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    884  *             struct variable.
    885  *  @param pipe_num pipe number.
    886  *  @param phy_port phy_port to configure.
    887  *  @brief API to drain phy_port
    888  * Description:
    889  *      API to drain phy_port
    890  *      Regs/Mems configured: EDB
    891  * Parameters:
    892  *      unit - Device number
    893  *      *port_schedule_state_t - Agreed structure between SDK and DV
    894  * Return Value:
    895  *      SOC_E_*
    896  */
    897 int soc_tomahawk3_ep_drain_port(
    898     int unit,
    899     soc_port_schedule_state_t *port_schedule_state,
    900     int pipe_num,
    901     int phy_port)
    902 {
    903     uint32 rval_save, rval;
    904     soc_reg_t reg;
    905     uint32 entry[SOC_MAX_MEM_WORDS];
    906     uint32 util;
    907     soc_mem_t mem;
    908     int timeout_in_us, iter_in_us;
    909 
    910     static const soc_reg_t misc_ctrl_regs[_TH3_PIPES_PER_DEV] = {
    911         EDB_MISC_CTRL_PIPE0r, EDB_MISC_CTRL_PIPE1r,
    912         EDB_MISC_CTRL_PIPE2r, EDB_MISC_CTRL_PIPE3r,
    913         EDB_MISC_CTRL_PIPE4r, EDB_MISC_CTRL_PIPE5r,
    914         EDB_MISC_CTRL_PIPE6r, EDB_MISC_CTRL_PIPE7r
    915     };
    916 
    917     /* Configure EGR_EDB_MISC_CTRL such that EGR_MAX_USED_ENTRIES returns
    918      * current buffer utilization
    919      */
    920     reg = misc_ctrl_regs[pipe_num];
    921     rval_save = 0;
    922     rval = 0;
    923     SOC_IF_ERROR_RETURN(soc_reg32_rawport_get(unit, reg, REG_PORT_ANY, 0,
    924                                               &rval_save));
    925     rval = rval_save;
    926     soc_reg_field_set(unit, reg, &rval, SELECT_CURRENT_USED_ENTRIESf, 1);
    927     SOC_IF_ERROR_RETURN(soc_reg32_rawport_set(unit, reg, REG_PORT_ANY, 0, rval));
    928 
    929     /* polling port's buffer utilization until is 0 */
    930     timeout_in_us = 70; /* account for IDB, MMU, EDB draining */
    931     iter_in_us = 0;
    932     sal_memset(entry, 0, sizeof(entry));
    933     mem = EGR_MAX_USED_ENTRIESm;
    934     do {
    935         SOC_IF_ERROR_RETURN
    936             (soc_mem_read(unit, mem, MEM_BLOCK_ALL,
    937                           phy_port, entry));
    938         /* coverity[callee_ptr_arith : FALSE] */
    939         soc_mem_field_get(unit, mem, entry, LEVELf, &util);
    940         if (0 == util) { break; }
    941 
    942         sal_usleep(1 + (SAL_BOOT_QUICKTURN ? 1 : 0) * EMULATION_FACTOR);
    943         iter_in_us++;
    944         if (iter_in_us >= timeout_in_us) {
    945             LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit,
    946                 "soc_tomahawk3_ep_drain_port()"
    947                 "TIMEOUT of %0d us reached when draining phy_port=%0d\n"), 
    948                 timeout_in_us, phy_port));
    949             return SOC_E_FAIL;
    950         }
    951     } while (0 != util);
    952 
    953     /* Configure EDB_MISC_CTRL back to previous value */
    954     SOC_IF_ERROR_RETURN(soc_reg32_rawport_set(unit, reg, REG_PORT_ANY, 0,
    955                                               rval_save));
    956 
    957     return SOC_E_NONE;
    958 }
    959 
    960 /*! @fn int soc_tomahawk3_ep_credit_rst_port(
    961  *    int unit,
    962  *    soc_port_schedule_state_t *port_schedule_state)
    963  *  @param unit Chip unit number.
    964  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
    965  *             struct variable.
    966  *  @param pipe_num pipe number.
    967  *  @param phy_port phy_port to configure.
    968  *  @brief API to sft_rst the phy_port
    969  * Description:
    970  *      API to reset  EDB credit the phy_port
    971  *      Regs/Mems configured: EDB
    972  * Parameters:
    973  *      unit - Device number
    974  *      *port_schedule_state_t - Agreed structure between SDK and DV
    975  * Return Value:
    976  *      SOC_E_*
    977  */
    978 int soc_tomahawk3_ep_credit_rst_port(
    979     int unit,
    980     int phy_port)
    981 {
    982     uint32 entry[SOC_MAX_MEM_WORDS];
    983     uint32 memfld;
    984     soc_mem_t mem;
    985 
    986     mem = EGR_PORT_CREDIT_RESETm;
    987 
    988     sal_memset(entry, 0, sizeof(entry));
    989     memfld = 1;
    990     soc_mem_field_set(unit, mem, entry, VALUEf, &memfld);
    991     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
    992                                       phy_port, entry));
    993 
    994     memfld = 0;
    995     soc_mem_field_set(unit, mem, entry, VALUEf, &memfld);
    996     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
    997                                       phy_port, entry));
    998 
    999     return SOC_E_NONE;
   1000 }
   1001 
   1002 
   1003 
   1004 /*! @fn int soc_tomahawk3_ep_sft_rst_port(
   1005  *    int unit,
   1006  *    soc_port_schedule_state_t *port_schedule_state)
   1007  *  @param unit Chip unit number.
   1008  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t
   1009  *             struct variable.
   1010  *  @param pipe_num pipe number.
   1011  *  @param phy_port phy_port to configure.
   1012  *  @param rst_on if (rst_on==1) then sft rst the port
   1013  *  @brief API to sft_rst the phy_port
   1014  * Description:
   1015  *      API to sft_rst the phy_port
   1016  *      Regs/Mems configured: EDB
   1017  * Parameters:
   1018  *      unit - Device number
   1019  *      *port_schedule_state_t - Agreed structure between SDK and DV
   1020  * Return Value:
   1021  *      SOC_E_*
   1022  */
   1023 int soc_tomahawk3_ep_sft_rst_port(
   1024     int unit,
   1025     soc_port_schedule_state_t *port_schedule_state,
   1026     int pipe_num,
   1027     int phy_port,
   1028     int rst_on)
   1029 {
   1030     uint32 entry[SOC_MAX_MEM_WORDS];
   1031     uint32 memfld;
   1032     soc_mem_t mem;
   1033 
   1034     mem = EGR_PER_PORT_BUFFER_SFT_RESETm;
   1035 
   1036     if (rst_on == 1) {
   1037         memfld = 1;
   1038     } else {
   1039         memfld = 0;
   1040     }
   1041 
   1042     sal_memset(entry, 0, sizeof(entry));
   1043     soc_mem_field_set(unit, mem, entry, ENABLEf, &memfld);
   1044     SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   1045                                       phy_port, entry));
   1046 
   1047     return SOC_E_NONE;
   1048 }
   1049 
   1050 /*! @fn int soc_tomahawk3_ep_port_down(int unit,
   1051  *              soc_port_schedule_state_t *port_schedule_state)
   1052  *  @param unit Chip unit number.
   1053  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t struct
   1054  *         variable
   1055  *  @brief Helper function to follow EDB port down sequence for flexport operation.
   1056  *         Does:
   1057  *            (1) Poll until EDB buffer is empty for ports going down
   1058  *            (2) Disables EDB for ports going down
   1059  *            (3) Asserts sft_rst EDB for ports going down
   1060  *
   1061  *  @returns SOC_E_NONE
   1062  */
   1063 int
   1064 soc_tomahawk3_ep_port_down(int unit,
   1065                            soc_port_schedule_state_t *port_schedule_state)
   1066 {
   1067     int i, rst_on, is_port_down;
   1068     int logical_port, physical_port;
   1069     int pipe_num;
   1070 
   1071     /*
   1072      * Poll until EDB buffer is empty:
   1073      * Set EGR_EDB_MISC_CTRL.SELECT_CURRENT_USED_ENTRIES to 1.
   1074      * Poll until EGR_MAX_USED_ENTRIES[physical_port] is equal to 0.
   1075      */
   1076     for (i = 0; i < port_schedule_state->nport; i++) {
   1077         if (port_schedule_state->resource[i].physical_port == -1) {
   1078             logical_port = port_schedule_state->resource[i].logical_port;
   1079             pipe_num = logical_port / _TH3_DEV_PORTS_PER_PIPE;
   1080             /* assumes drain is done before FlexPort */
   1081             physical_port =
   1082                 port_schedule_state->in_port_map.port_l2p_mapping[logical_port];
   1083             SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_drain_port(unit,
   1084                                     port_schedule_state, pipe_num, physical_port));
   1085         }
   1086     }
   1087 
   1088     /*
   1089      * Disables EDB to MMU cell request generation
   1090      * Set EGR_ENABLE[device_port].PRT_ENABLE to 0.
   1091      * Set EGR_PER_PORT_BUFFER_SFT_RESET[device_port] to 1.
   1092      */
   1093 
   1094     is_port_down = 1; /* that is, disable port */
   1095     rst_on = 1;       /* that is, assert sft_rst */
   1096     for (i = 0; i < port_schedule_state->nport; i++) {
   1097         if (port_schedule_state->resource[i].physical_port == -1) { /* port DOWN */
   1098             logical_port = port_schedule_state->resource[i].logical_port;
   1099             pipe_num = logical_port / _TH3_DEV_PORTS_PER_PIPE;
   1100             /* assumes drain is done before FlexPort */
   1101             physical_port =
   1102                 port_schedule_state->in_port_map.port_l2p_mapping[logical_port];
   1103 
   1104             /* Disable port : write EGR_ENABLEm */
   1105             SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_set_egr_enable(unit, port_schedule_state,
   1106                                             pipe_num, physical_port, is_port_down));
   1107             /* Assert sft_rst per port */
   1108             SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_sft_rst_port(unit, port_schedule_state,
   1109                                             pipe_num, physical_port, rst_on));
   1110         }
   1111     }
   1112 
   1113     return SOC_E_NONE;
   1114 }
   1115 
   1116 
   1117 /*! @fn int soc_tomahawk3_ep_port_up(int unit,
   1118  *              soc_port_schedule_state_t *port_schedule_state)
   1119  *  @param unit Chip unit number.
   1120  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t struct
   1121  *         variable
   1122  *  @brief Main API that brings up all added ports in EGR pipe
   1123  * Return Value:
   1124  *      SOC_E_*
   1125  */
   1126 int
   1127 soc_tomahawk3_ep_port_up(int unit,
   1128                          soc_port_schedule_state_t *port_schedule_state)
   1129 {
   1130     int i, rst_on, is_port_down;
   1131     int logical_port, physical_port;
   1132     int pipe_num;
   1133 
   1134     /*
   1135      * Toggle port rst: Set EGR_PER_PORT_BUFFER_SFT_RESET[device_port] to 1
   1136      *                  Set EGR_PER_PORT_BUFFER_SFT_RESET[device_port] to 0
   1137      * Set EGR_ENABLE[device_port].PRT_ENABLE to 1
   1138      */
   1139 
   1140     rst_on = 1; /* assert reset */
   1141     for (i = 0; i < port_schedule_state->nport; i++) {
   1142         physical_port = port_schedule_state->resource[i].physical_port;
   1143         if (-1 != physical_port) { /* that is, port UP */
   1144             logical_port = port_schedule_state->resource[i].logical_port;
   1145             pipe_num = logical_port / _TH3_DEV_PORTS_PER_PIPE;
   1146             /* De-assert sft_rst*/
   1147             SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_sft_rst_port(unit, port_schedule_state,
   1148                                             pipe_num, physical_port, rst_on));
   1149         }
   1150     }
   1151 
   1152     rst_on = 0; /* de-assert reset */
   1153     for (i = 0; i < port_schedule_state->nport; i++) {
   1154         physical_port = port_schedule_state->resource[i].physical_port;
   1155         if (-1 != physical_port) { /* that is, port UP */
   1156             logical_port = port_schedule_state->resource[i].logical_port;
   1157             pipe_num = logical_port / _TH3_DEV_PORTS_PER_PIPE;
   1158             /* De-assert sft_rst*/
   1159             SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_sft_rst_port(unit, port_schedule_state,
   1160                                             pipe_num, physical_port, rst_on));
   1161         }
   1162     }
   1163 
   1164     /* Enable Ports going up after PM sft_rst is de-asserted */
   1165     /* For ports going UP do:
   1166      * 1. Enable port; write EGR_ENABLEm
   1167      */
   1168     is_port_down = 0; /* that is, port UP */
   1169     for (i = 0; i < port_schedule_state->nport; i++) {
   1170         physical_port = port_schedule_state->resource[i].physical_port;
   1171         if (-1 != physical_port) { /* that is, port UP */
   1172             logical_port = port_schedule_state->resource[i].logical_port;
   1173             pipe_num = logical_port / _TH3_DEV_PORTS_PER_PIPE;
   1174             /* Enable port; write EGR_ENABLEm */
   1175             SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_set_egr_enable(unit, port_schedule_state,
   1176                                             pipe_num, physical_port, is_port_down));
   1177         }
   1178     }
   1179 
   1180     return SOC_E_NONE;
   1181 }
   1182 
   1183 /*! @fn int soc_tomahawk3_flex_ep_reconfigure_remove(int unit,
   1184  *              soc_port_schedule_state_t *port_schedule_state)
   1185  *  @param unit Chip unit number.
   1186  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t struct
   1187  *         variable
   1188  *  @brief Main API that reconfigures all ports from EGR pipe - remove ports
   1189  * Return Value:
   1190  *      SOC_E_*
   1191  */
   1192 int
   1193 soc_tomahawk3_flex_ep_reconfigure_remove(int unit,
   1194     soc_port_schedule_state_t *port_schedule_state)
   1195 {
   1196     int i, is_port_down;
   1197     int log_port, phy_port, pipe;
   1198 
   1199     /* For ports going DOWN do:
   1200      * 1. Delete Dev 2 Phy mapping.
   1201      * 2. Reset max Ep2MMU credits to 0.
   1202      */
   1203     is_port_down = 1; /* that is, port DOWN */
   1204     for (i = 0; i < port_schedule_state->nport; i++) {
   1205         phy_port = port_schedule_state->resource[i].physical_port;
   1206         if (phy_port == -1) { /* that is, port DOWN */
   1207             log_port = port_schedule_state->resource[i].logical_port;
   1208             phy_port = port_schedule_state->in_port_map.port_l2p_mapping[log_port];
   1209             pipe = log_port / _TH3_DEV_PORTS_PER_PIPE;
   1210             soc_tomahawk3_ep_set_dev_to_phy(unit, port_schedule_state,
   1211                    pipe, phy_port, is_port_down);
   1212             soc_tomahawk3_ep_set_mmu_cell_credit(unit, port_schedule_state,
   1213                    pipe, phy_port, is_port_down);
   1214         }
   1215     }
   1216 
   1217     return SOC_E_NONE;
   1218 }
   1219 
   1220 
   1221 /*! @fn int soc_tomahawk3_flex_ep_reconfigure_add(int unit,
   1222  *              soc_port_schedule_state_t *port_schedule_state)
   1223  *  @param unit Chip unit number.
   1224  *  @param port_schedule_state Pointer to a soc_port_schedule_state_t struct
   1225  *         variable
   1226  *  @brief Main API that reconfigures all ports from EGR pipe - add ports
   1227  * Return Value:
   1228  *      SOC_E_*
   1229  */
   1230 int
   1231 soc_tomahawk3_flex_ep_reconfigure_add(int unit,
   1232     soc_port_schedule_state_t *port_schedule_state)
   1233 {
   1234     int i, is_port_down;
   1235     int log_port, phy_port, pipe;
   1236 
   1237 
   1238     /* For ports going UP do:
   1239      * 1. Map Dev 2 Phy for added port.
   1240      * 2. Configure max Ep2MMU credits to proper value.
   1241      * 3. Configure CT_class for added port.
   1242      * 4. Configure XMIT_START_CNT entries for added port.
   1243      */
   1244     is_port_down = 0; /* that is, port UP */
   1245     for (i = 0; i < port_schedule_state->nport; i++) {
   1246         phy_port = port_schedule_state->resource[i].physical_port;
   1247         if (phy_port != -1) { /* that is, port UP */
   1248             log_port = port_schedule_state->resource[i].logical_port;
   1249             pipe = log_port / _TH3_DEV_PORTS_PER_PIPE;
   1250             soc_tomahawk3_ep_set_dev_to_phy(unit, port_schedule_state,
   1251                    pipe, phy_port, is_port_down);
   1252             soc_tomahawk3_ep_set_mmu_cell_credit(unit, port_schedule_state,
   1253                    pipe, phy_port, is_port_down);
   1254             soc_tomahawk3_ep_set_ct_class(unit, port_schedule_state,
   1255                    pipe, phy_port, is_port_down);
   1256             soc_tomahawk3_ep_set_xmit_start_cnt(unit, port_schedule_state,
   1257                    pipe, phy_port, is_port_down);
   1258         }
   1259     }
   1260 
   1261     return SOC_E_NONE;
   1262 }
   1263 
   1264 /*** END SDK API COMMON CODE ***/
   1265 
   1266 #endif /* BCM_TOMAHAWK3_SUPPORT */
   1267