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

xlmac.c (96517B)


      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  * XLMAC driver
      8  */
      9 
     10 #include <shared/bsl.h>
     11 #include <bcm/types.h> 
     12 #include <sal/core/libc.h>
     13 #include <shared/alloc.h>
     14 #include <sal/core/spl.h>
     15 #include <sal/core/boot.h>
     16 #include <soc/drv.h>
     17 #include <soc/error.h>
     18 #include <soc/cmic.h>
     19 #include <soc/portmode.h>
     20 #include <soc/ll.h>
     21 #include <soc/counter.h>
     22 #include <soc/macutil.h>
     23 #include <soc/phyctrl.h>
     24 #ifdef BCM_GREYHOUND_SUPPORT
     25 #include <soc/greyhound.h>
     26 #endif
     27 #ifdef BCM_SABER2_SUPPORT
     28 #include <soc/saber2.h>
     29 #endif
     30 #ifdef BCM_GREYHOUND2_SUPPORT
     31 #include <soc/greyhound2.h>
     32 #endif
     33 
     34 #ifdef BCM_XLMAC_SUPPORT
     35 
     36 #define XLMAC_RUNT_THRESHOLD_IEEE  0x40   /* Runt threshold value for IEEE ports */
     37 #define XLMAC_RUNT_THRESHOLD_HG1   0x48   /* Runt threshold value for HG1 ports */
     38 #define XLMAC_RUNT_THRESHOLD_HG2   0x4c   /* Runt threshold value for HG2 ports */
     39 
     40 /*
     41  * XLMAC Register field definitions.
     42  */
     43 
     44 #define JUMBO_MAXSZ              0x3fe8 /* Max legal value (per regsfile) */
     45 
     46 mac_driver_t soc_mac_xl;
     47 
     48 #ifdef BROADCOM_DEBUG
     49 static char *mac_xl_encap_mode[] = SOC_ENCAP_MODE_NAMES_INITIALIZER;
     50 static char *mac_xl_port_if_names[] = SOC_PORT_IF_NAMES_INITIALIZER;
     51 #endif /* BROADCOM_DEBUG */
     52 
     53 #define SOC_XLMAC_SPEED_10     0x0
     54 #define SOC_XLMAC_SPEED_100    0x1
     55 #define SOC_XLMAC_SPEED_1000   0x2
     56 #define SOC_XLMAC_SPEED_2500   0x3
     57 #define SOC_XLMAC_SPEED_10000  0x4
     58 
     59 #define SOC_XLMAC_XLPORT_MODE_SINGLE    4
     60 #define SOC_XLMAC_XLPORT_MODE_QUAD      0
     61 
     62 /* Transmit CRC Modes */
     63 #define XLMAC_CRC_APPEND        0x0
     64 #define XLMAC_CRC_KEEP          0x1
     65 #define XLMAC_CRC_REPLACE       0x2
     66 #define XLMAC_CRC_PER_PKT_MODE  0x3
     67 
     68 #ifdef BCM_SABER2_SUPPORT
     69 typedef struct {
     70     uint64 mac_ctrl;
     71     uint64 rx_ctrl;
     72     uint64 tx_ctrl;
     73     uint64 pfc_ctrl;
     74     uint64 pfc_type;
     75     uint64 pfc_opcode;
     76     uint64 pfc_da;
     77     uint64 rx_max_size;
     78     uint64 mac_mode;
     79     uint64 pause_ctrl;
     80     uint64 rx_mac_sa;
     81     uint64 tx_mac_sa;
     82     uint64 llfc_ctrl;
     83     uint64 eee_ctrl;
     84     uint64 eee_timers;
     85     uint64 rx_lss_ctrl;
     86     uint64 rx_vlan_tag;
     87     uint64 e2e_ctrl;
     88 } _xlmac_x_cfg_t;
     89 #endif
     90 
     91 struct {
     92     int speed;
     93     uint32 clock_rate;
     94 }_mac_xl_clock_rate[] = {
     95     { 40000, 312 },
     96     { 20000, 156 },
     97     { 10000, 78  },
     98     { 5000,  78  },
     99     { 2500,  312 },
    100     { 1000,  125 },
    101     { 0,     25  },
    102 };
    103 
    104 /*
    105  *  WAN mode throttling
    106  *  THROT_10G_TO_5G: throt_num=21 throt_denom=21
    107  *  THROT_10G_TO_2P5G: throt_num=63 throt_denom=21
    108  */
    109 #define XLMAC_THROT_10G_TO_5G    256
    110 #define XLMAC_THROT_10G_TO_2P5G  257
    111 
    112 STATIC int
    113 _mac_xl_timestamp_delay_set(int unit, soc_port_t port, int speed);
    114 STATIC int
    115 mac_xl_speed_get(int unit, soc_port_t port, int *speed);
    116 STATIC int
    117 mac_xl_encap_get(int unit, soc_port_t port, int *mode);
    118 void
    119 _mac_xl_speed_to_clock_rate(int unit, soc_port_t port, int speed,
    120                             uint32 *clock_rate)
    121 {
    122     int idx;
    123 
    124 
    125     for (idx = 0;
    126          idx < sizeof(_mac_xl_clock_rate) / sizeof(_mac_xl_clock_rate[0]);
    127          idx++) {
    128         if (speed >=_mac_xl_clock_rate[idx].speed) {
    129             *clock_rate = _mac_xl_clock_rate[idx].clock_rate;
    130             return;
    131         }
    132     }
    133     *clock_rate = 0;
    134 }
    135 
    136 STATIC int
    137 _mac_xl_drain_cells(int unit, soc_port_t port, int notify_phy, int queue_enable)
    138 {
    139     int         rv;
    140     int         pause_tx, pause_rx, pfc_rx, llfc_rx;
    141     soc_field_t fields[2];
    142     uint32      values[2], fval;
    143     uint64      mac_ctrl, rval64;
    144     soc_timeout_t to;
    145 #ifdef BCM_GREYHOUND_SUPPORT
    146     uint32      mmu_fc = 0;
    147 #endif
    148 
    149     rv  = SOC_E_NONE;
    150 
    151     if (SOC_IS_RELOADING(unit)) {
    152         return rv;
    153     }
    154 
    155 #ifdef BCM_GREYHOUND_SUPPORT
    156     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) {
    157         SOC_IF_ERROR_RETURN
    158             (soc_mmu_flush_enable(unit, port, TRUE));
    159         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    160                     (BSL_META_U(unit,
    161                                 "port %d xlmac mmu flush enable completed\n"),
    162                      port));
    163         /* clear the MMU pause state*/
    164         SOC_IF_ERROR_RETURN(
    165             READ_MMU_FC_RX_ENr(unit, port, &mmu_fc));
    166         SOC_IF_ERROR_RETURN(
    167             WRITE_MMU_FC_RX_ENr(unit, port, 0));
    168     }
    169 #endif
    170 
    171 #if defined(BCM_SABER2_SUPPORT)
    172     if(SOC_IS_SABER2(unit)) {
    173         SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, TRUE));
    174         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    175                     (BSL_META_U(unit,
    176                                 "port %d xlmac mmu flush enable completed\n"),
    177                      port));
    178     }
    179 #endif
    180 
    181     /* Disable pause/pfc function */
    182     SOC_IF_ERROR_RETURN
    183         (soc_mac_xl.md_pause_get(unit, port, &pause_tx, &pause_rx));
    184     SOC_IF_ERROR_RETURN
    185         (soc_mac_xl.md_pause_set(unit, port, pause_tx, 0));
    186 
    187     SOC_IF_ERROR_RETURN
    188         (soc_mac_xl.md_control_get(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE,
    189                                    &pfc_rx));
    190     SOC_IF_ERROR_RETURN
    191         (soc_mac_xl.md_control_set(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE,
    192                                    0));
    193 
    194     SOC_IF_ERROR_RETURN
    195         (soc_mac_xl.md_control_get(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE,
    196                                    &llfc_rx));
    197     SOC_IF_ERROR_RETURN
    198         (soc_mac_xl.md_control_set(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE,
    199                                    0));
    200 
    201     /* Assert SOFT_RESET before DISCARD just in case there is no credit left */
    202     SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &mac_ctrl));
    203     soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 1);
    204 
    205     /* Drain data in TX FIFO without egressing at packet boundary */
    206     SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, mac_ctrl));
    207     fields[0] = DISCARDf;
    208     values[0] = 1;
    209     fields[1] = EP_DISCARDf;
    210     values[1] = 1;
    211     SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, XLMAC_TX_CTRLr, port, 2,
    212                                                 fields, values));
    213 
    214     /* Reset EP credit before de-assert SOFT_RESET */
    215     if (!SOC_IS_HURRICANE2(unit)) {
    216         SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port));
    217     }
    218 
    219     /* De-assert SOFT_RESET to let the drain start */
    220     soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0);
    221     SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, mac_ctrl));
    222 
    223     if (notify_phy == 1)
    224     {
    225     /* Notify PHY driver */
    226        SOC_IF_ERROR_RETURN
    227            (soc_phyctrl_notify(unit, port, phyEventStop, PHY_STOP_DRAIN));
    228     }
    229 
    230     /* Wait until mmu cell count is 0 */
    231     rv = soc_egress_drain_cells(unit, port, 250000);
    232     if (SOC_E_NONE == rv) {
    233         /* Wait until TX fifo cell count is 0 */
    234         soc_timeout_init(&to, 250000, 0);
    235         for (;;) {
    236             rv = READ_XLMAC_TXFIFO_CELL_CNTr(unit, port, &rval64);
    237             if (SOC_E_NONE != rv) {
    238                 break;
    239             }
    240             fval = soc_reg64_field32_get(unit, XLMAC_TXFIFO_CELL_CNTr, rval64,
    241                                          CELL_CNTf);
    242             if (fval == 0) {
    243                 break;
    244             }
    245             if (soc_timeout_check(&to)) {
    246                 LOG_ERROR(BSL_LS_SOC_XLMAC,
    247                           (BSL_META_U(unit,
    248                                 "ERROR: port %d:%s: "
    249                                 "timeout draining TX FIFO (%d cells remain)\n"),
    250                                 unit, SOC_PORT_NAME(unit, port), fval));
    251                 rv = SOC_E_INTERNAL;
    252                 break;
    253             }
    254         }
    255     }
    256 
    257     if (notify_phy == 1)
    258     { /* Notify PHY driver */
    259         SOC_IF_ERROR_RETURN
    260             (soc_phyctrl_notify(unit, port, phyEventResume, PHY_STOP_DRAIN));
    261     }
    262    
    263     /* Stop TX FIFO drainging */
    264     values[0] = 0;
    265     values[1] = 0;
    266     SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, XLMAC_TX_CTRLr, port, 2,
    267                                                 fields, values));
    268 
    269 #ifdef BCM_GREYHOUND_SUPPORT
    270     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) {
    271         SOC_IF_ERROR_RETURN
    272             (soc_mmu_flush_enable(unit, port, FALSE));
    273         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    274                     (BSL_META_U(unit,
    275                                 "port %d xlmac mmu flush disabled\n"),
    276                      port));
    277         /* restore the MMU pause state*/
    278         SOC_IF_ERROR_RETURN(
    279             WRITE_MMU_FC_RX_ENr(unit, port, mmu_fc));
    280     }
    281 #endif
    282 
    283 #if defined(BCM_SABER2_SUPPORT)
    284     if (SOC_IS_SABER2(unit) && queue_enable) {
    285         SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, FALSE));
    286         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    287                     (BSL_META_U(unit,
    288                                 "port %d xlmac mmu flush disabled\n"),
    289                      port));
    290     }
    291 #endif
    292 
    293     /* Restore original pause/pfc/llfc configuration */
    294     SOC_IF_ERROR_RETURN
    295         (soc_mac_xl.md_pause_set(unit, port, pause_tx, pause_rx));
    296     SOC_IF_ERROR_RETURN
    297         (soc_mac_xl.md_control_set(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE,
    298                                    pfc_rx));
    299     SOC_IF_ERROR_RETURN
    300         (soc_mac_xl.md_control_set(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE,
    301                                    llfc_rx));
    302 
    303     return rv;
    304 }
    305 
    306 /*
    307  * Function:
    308  *      _mac_xl_timestamp_byte_adjust_set
    309  * Purpose:
    310  *      Set timestamp byte adjust values.
    311  * Parameters:
    312  *      unit - XGS unit #.
    313  *      port - Port number on unit.
    314  * Returns:
    315  *      SOC_E_XXX
    316  */
    317 STATIC int
    318 _mac_xl_timestamp_byte_adjust_set(int unit, soc_port_t port)
    319 {
    320     uint64 ctrl;
    321     uint32 ctrl32;
    322 
    323     if (SOC_REG_PORT_VALID(unit, MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr, port) &&
    324         (IS_GE_PORT(unit, port)) ) {
    325         /* for viper ports on SB2 A0 */
    326         SOC_IF_ERROR_RETURN(READ_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl32));
    327         soc_reg_field_set(unit, MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl32,
    328                           TX_TIMER_BYTE_ADJUSTf, 8);
    329         SOC_IF_ERROR_RETURN(WRITE_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl32));
    330 
    331         SOC_IF_ERROR_RETURN(READ_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl32));
    332         soc_reg_field_set(unit, MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl32,
    333                           TX_TIMER_BYTE_ADJUST_ENf, 1);
    334         SOC_IF_ERROR_RETURN(WRITE_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl32));
    335 
    336         SOC_IF_ERROR_RETURN(READ_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl32));
    337         soc_reg_field_set(unit, MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl32,
    338                           RX_TIMER_BYTE_ADJUSTf, 8);
    339         SOC_IF_ERROR_RETURN(WRITE_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl32));
    340 
    341         SOC_IF_ERROR_RETURN(READ_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl32));
    342         soc_reg_field_set(unit, MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl32,
    343                           RX_TIMER_BYTE_ADJUST_ENf, 1);
    344         SOC_IF_ERROR_RETURN(WRITE_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl32));
    345     }
    346 
    347     if (SOC_REG_PORT_VALID(unit, XLMAC_TIMESTAMP_BYTE_ADJUSTr, port) && 
    348         (IS_GE_PORT(unit, port)) ) {
    349         /* for viper and eagle ports on SB2 B0 */
    350         SOC_IF_ERROR_RETURN(READ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl));
    351         soc_reg64_field32_set(unit, XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl,
    352                           TX_TIMER_BYTE_ADJUSTf, 8);
    353         SOC_IF_ERROR_RETURN(WRITE_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl));
    354 
    355         SOC_IF_ERROR_RETURN(READ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl));
    356         soc_reg64_field32_set(unit, XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl,
    357                           TX_TIMER_BYTE_ADJUST_ENf, 1);
    358         SOC_IF_ERROR_RETURN(WRITE_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl));
    359 
    360         SOC_IF_ERROR_RETURN(READ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl));
    361         soc_reg64_field32_set(unit, XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl,
    362                           RX_TIMER_BYTE_ADJUSTf, 8);
    363         SOC_IF_ERROR_RETURN(WRITE_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl));
    364 
    365         SOC_IF_ERROR_RETURN(READ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl));
    366         soc_reg64_field32_set(unit, XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl,
    367                           RX_TIMER_BYTE_ADJUST_ENf, 1);
    368         SOC_IF_ERROR_RETURN(WRITE_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl));
    369     }
    370 
    371     return SOC_E_NONE;
    372 }
    373 
    374 /*
    375  * Function:
    376  *      mac_xl_init
    377  * Purpose:
    378  *      Initialize Xlmac into a known good state.
    379  * Parameters:
    380  *      unit - XGS unit #.
    381  *      port - Port number on unit.
    382  * Returns:
    383  *      SOC_E_XXX
    384  * Notes:
    385  */
    386 STATIC int
    387 mac_xl_init(int unit, soc_port_t port)
    388 {
    389     soc_info_t *si;
    390     uint64 mac_ctrl, rx_ctrl, tx_ctrl, rval;
    391     uint32 ipg;
    392     int mode;
    393     int encap = 0;
    394     int runt;
    395 #if defined(BCM_SABER2_SUPPORT)
    396     int                 sgn_det = 0;
    397     uint32              sgn_crs;
    398 #endif
    399 
    400 
    401 
    402     LOG_VERBOSE(BSL_LS_SOC_10G,
    403                 (BSL_META_U(unit,
    404                             "mac_xl_init: unit %d port %s\n"),
    405                  unit, SOC_PORT_NAME(unit, port)));
    406 
    407     si = &SOC_INFO(unit);
    408 
    409     /* Disable Tx/Rx, assume that MAC is stable (or out of reset) */
    410     SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &mac_ctrl));
    411 
    412     /* Reset EP credit before de-assert SOFT_RESET */
    413     if (soc_reg64_field32_get(unit, XLMAC_CTRLr, mac_ctrl, SOFT_RESETf)) {
    414         SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port));
    415     }
    416 
    417     soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0);
    418     soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, RX_ENf, 0);
    419     soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, TX_ENf, 0);
    420     soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl,
    421                           XGMII_IPG_CHECK_DISABLEf,
    422                           IS_HG_PORT(unit, port) ? 1 : 0);
    423     SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, mac_ctrl));
    424 
    425     if (IS_ST_PORT(unit, port)) {
    426         soc_mac_xl.md_pause_set(unit, port, FALSE, FALSE);
    427     } else {
    428         soc_mac_xl.md_pause_set(unit, port, TRUE, TRUE);
    429     }
    430 
    431     SOC_IF_ERROR_RETURN
    432         (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, PFC_REFRESH_ENf,
    433                                 1));
    434 
    435     if (soc_property_port_get(unit, port, spn_PHY_WAN_MODE, FALSE)) {
    436         SOC_IF_ERROR_RETURN
    437             (soc_mac_xl.md_control_set(unit, port,
    438                                        SOC_MAC_CONTROL_FRAME_SPACING_STRETCH,
    439                                        13));
    440     }
    441 
    442     /* Set jumbo max size (8000 byte payload) */
    443     COMPILER_64_ZERO(rval);
    444 #ifdef BCM_XGS_SUPPORT
    445     if (SOC_IS_XGS3_SWITCH(unit)) {
    446         uint32 rval;
    447         soc_reg_t reg;
    448         reg = SOC_REG_IS_VALID(unit, EGR_MTUr) ? EGR_MTUr : EGR_MTU_SIZEr;
    449         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    450         soc_reg_field_set(unit, reg, &rval, MTU_SIZEf, SOC_INFO(unit).max_mtu);
    451         if (soc_reg_field_valid(unit, reg, MTU_ENABLEf)) {
    452             soc_reg_field_set(unit, reg, &rval, MTU_ENABLEf, 1);
    453         }
    454         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
    455     }
    456 
    457     if (SOC_IS_XGS(unit)) {
    458         soc_reg64_field32_set(unit, XLMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf,
    459                           SOC_INFO(unit).max_mtu);
    460     } else
    461 #endif
    462     {
    463         soc_reg64_field32_set(unit, XLMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf,
    464                           JUMBO_MAXSZ);
    465     }
    466     SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_MAX_SIZEr(unit, port, rval));
    467 
    468     /* Setup header mode, check for property for higig2 mode */
    469     COMPILER_64_ZERO(rval);
    470     if (!IS_XE_PORT(unit, port) && !IS_GE_PORT(unit, port)) {
    471         mode = soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE,
    472                soc_feature(unit, soc_feature_no_higig_plus) ? 1 : 0) ? 2 : 1;
    473         soc_reg64_field32_set(unit, XLMAC_MODEr, &rval, HDR_MODEf, mode);
    474         encap = mode;
    475     }
    476     switch (si->port_speed_max[port]) {
    477     case 10:
    478         mode = SOC_XLMAC_SPEED_10;
    479         break;
    480     case 100:
    481         mode = SOC_XLMAC_SPEED_100;
    482         break;
    483     case 1000:
    484         mode = SOC_XLMAC_SPEED_1000;
    485         break;
    486     case 2500:
    487         mode = SOC_XLMAC_SPEED_2500;
    488         break;
    489     default:
    490         mode = SOC_XLMAC_SPEED_10000;
    491         break;
    492     }
    493     soc_reg64_field32_set(unit, XLMAC_MODEr, &rval, SPEED_MODEf, mode);
    494     SOC_IF_ERROR_RETURN(WRITE_XLMAC_MODEr(unit, port, rval));
    495 
    496     /* init IPG and RUNT_THRESHOLD after port encap mode been established. */
    497     if (encap == 1) {
    498         ipg = SOC_PERSIST(unit)->ipg[port].fd_hg;
    499         runt = XLMAC_RUNT_THRESHOLD_HG1;
    500     } else if (encap == 2) {
    501         ipg = SOC_PERSIST(unit)->ipg[port].fd_hg2;
    502         runt = XLMAC_RUNT_THRESHOLD_HG2;
    503     } else {
    504         ipg = SOC_PERSIST(unit)->ipg[port].fd_xe;
    505         runt = XLMAC_RUNT_THRESHOLD_IEEE;
    506     }
    507 
    508     SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &tx_ctrl));
    509     soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &tx_ctrl, AVERAGE_IPGf,
    510                           (ipg / 8) & 0x1f);
    511     soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf,
    512                           XLMAC_CRC_PER_PKT_MODE);
    513     SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, tx_ctrl));
    514 
    515     SOC_IF_ERROR_RETURN(READ_XLMAC_RX_CTRLr(unit, port, &rx_ctrl));
    516     soc_reg64_field32_set(unit, XLMAC_RX_CTRLr, &rx_ctrl, STRIP_CRCf, 0);
    517     soc_reg64_field32_set(unit, XLMAC_RX_CTRLr, &rx_ctrl, STRICT_PREAMBLEf,
    518                           si->port_speed_max[port] >= 10000 &&
    519                           IS_XE_PORT(unit, port) ? 1 : 0);
    520 
    521     /* assigning RUNT_THRESHOLD (per encap mode) */
    522     soc_reg64_field32_set(unit, XLMAC_RX_CTRLr, &rx_ctrl, RUNT_THRESHOLDf,
    523                           runt);
    524     SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_CTRLr(unit, port, rx_ctrl));
    525 
    526     /* assigning proper init setting for EEE feature per speed */
    527     if (soc_feature(unit, soc_feature_eee)) {
    528         SOC_IF_ERROR_RETURN(soc_port_eee_timers_init(unit,
    529                 port, si->port_speed_max[port]));
    530     }
    531 
    532     SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &rval));
    533     soc_reg64_field32_set(unit, XLMAC_RX_LSS_CTRLr, &rval,
    534                           DROP_TX_DATA_ON_LOCAL_FAULTf, 1);
    535     soc_reg64_field32_set(unit, XLMAC_RX_LSS_CTRLr, &rval,
    536                           DROP_TX_DATA_ON_REMOTE_FAULTf, 1);
    537     soc_reg64_field32_set(unit, XLMAC_RX_LSS_CTRLr, &rval,
    538                           DROP_TX_DATA_ON_LINK_INTERRUPTf, 1);    
    539     SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_LSS_CTRLr(unit, port, rval));
    540 
    541     if (SOC_REG_IS_VALID(unit, XLMAC_MACSEC_CTRLr)) {
    542         /* Enable Tx CRC corruption */
    543         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_MACSEC_CTRLr, port,
    544                                                    MACSEC_TX_CRC_CORRUPT_ENf, 1));
    545     }
    546 #if defined(BCM_SABER2_SUPPORT)
    547     if (SOC_IS_SABER2(unit)){
    548         SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &mac_ctrl));
    549         soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, EXTENDED_HIG2_ENf, 1);
    550         soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, SW_LINK_STATUSf, 1);
    551         SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, mac_ctrl));
    552 
    553         sgn_det = soc_property_port_get(unit, port,  spn_SERDES_RX_LOS, 0);
    554         SOC_IF_ERROR_RETURN(READ_X_GPORT_SGNDET_EARLYCRSr(unit, port, &sgn_crs));
    555         soc_reg_field_set(unit, X_GPORT_SGNDET_EARLYCRSr, &sgn_crs, SGN_DETf, sgn_det);
    556         SOC_IF_ERROR_RETURN(WRITE_X_GPORT_SGNDET_EARLYCRSr(unit, port, sgn_crs));
    557     }
    558 
    559 #endif
    560 
    561     /* Disable loopback and bring XLMAC out of reset */
    562     SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &mac_ctrl));
    563     soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, LOCAL_LPBKf, 0);
    564     soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, RX_ENf, 1);
    565     soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, TX_ENf, 1);
    566     SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, mac_ctrl));
    567 
    568     SOC_IF_ERROR_RETURN(_mac_xl_timestamp_byte_adjust_set(unit, port));
    569     return SOC_E_NONE;
    570 }
    571 
    572 /*
    573  * Function:
    574  *      mac_xl_egress_queue_drain
    575  * Purpose:
    576  *      Drain the egress queues with out bringing down the port
    577  * Parameters:
    578  *      unit - XGS unit #.
    579  *      port - Port number on unit.
    580  * Returns:
    581  *      SOC_E_XXX
    582  */
    583 STATIC int
    584 mac_xl_egress_queue_drain(int unit, soc_port_t port)
    585 {
    586     uint64 ctrl, octrl;
    587     pbmp_t mask;
    588     int rx_enable = 0;
    589     int is_active = 0;
    590 
    591     LOG_VERBOSE(BSL_LS_SOC_10G,
    592                 (BSL_META_U(unit,
    593                             "mac_xl_egress_queue_drain: unit %d port %s \n"),
    594                  unit, SOC_PORT_NAME(unit, port)));
    595 
    596     SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &ctrl));
    597     octrl = ctrl;
    598 
    599     rx_enable = soc_reg64_field32_get(unit, XLMAC_CTRLr, ctrl, RX_ENf);
    600     /* Don't disable TX since it stops egress and hangs if CPU sends */
    601     soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, TX_ENf, 1);
    602     soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, RX_ENf, 0);
    603         /* Disable RX */
    604     SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl));
    605 
    606         /* Remove port from EPC_LINK */
    607     soc_link_mask2_get(unit, &mask);
    608     if (SOC_PBMP_MEMBER(mask, port)) {
    609         is_active = 1;
    610         SOC_PBMP_PORT_REMOVE(mask, port);
    611         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    612     }
    613 
    614         /* Drain cells */
    615     SOC_IF_ERROR_RETURN(_mac_xl_drain_cells(unit, port, 0, TRUE));
    616 
    617         /* Reset port FIFO */
    618     SOC_IF_ERROR_RETURN(soc_port_fifo_reset(unit, port));
    619 
    620         /* Put port into SOFT_RESET */
    621     soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, SOFT_RESETf, 1);
    622     SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl));
    623 
    624         /* Reset EP credit before de-assert SOFT_RESET */
    625     SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port));
    626     SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &ctrl));
    627     soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, RX_ENf, rx_enable ? 1 : 0);
    628 
    629       /* Enable both TX and RX, deassert SOFT_RESET */
    630     soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, SOFT_RESETf, 0);
    631     SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl));
    632 
    633         /* Restore XLMAC_CTRL to original value */
    634     SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, octrl));        
    635 
    636         /* Add port to EPC_LINK */
    637     if(is_active) {
    638         soc_link_mask2_get(unit, &mask);
    639         SOC_PBMP_PORT_ADD(mask, port);
    640         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    641     }
    642  
    643     return SOC_E_NONE;
    644 }
    645 
    646 #if defined(BCM_SABER2_SUPPORT)
    647 
    648 STATIC int _xlmac_x_register_store(int unit, soc_port_t port, _xlmac_x_cfg_t *port_cfg)
    649 {
    650     SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &port_cfg->mac_ctrl));
    651     SOC_IF_ERROR_RETURN(READ_XLMAC_RX_CTRLr(unit, port, &port_cfg->rx_ctrl));
    652     SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &port_cfg->tx_ctrl));
    653     SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &port_cfg->pfc_ctrl));
    654     SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_TYPEr(unit, port, &port_cfg->pfc_type));
    655     SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_OPCODEr(unit, port, &port_cfg->pfc_opcode));
    656     SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_DAr(unit, port, &port_cfg->pfc_da));
    657     SOC_IF_ERROR_RETURN(READ_XLMAC_RX_MAX_SIZEr(unit, port, &port_cfg->rx_max_size));
    658     SOC_IF_ERROR_RETURN(READ_XLMAC_MODEr(unit, port, &port_cfg->mac_mode));
    659     SOC_IF_ERROR_RETURN(READ_XLMAC_PAUSE_CTRLr(unit, port, &port_cfg->pause_ctrl));
    660     SOC_IF_ERROR_RETURN(READ_XLMAC_RX_MAC_SAr(unit, port, &port_cfg->rx_mac_sa));
    661     SOC_IF_ERROR_RETURN(READ_XLMAC_TX_MAC_SAr(unit, port, &port_cfg->tx_mac_sa));
    662     SOC_IF_ERROR_RETURN(READ_XLMAC_LLFC_CTRLr(unit, port, &port_cfg->llfc_ctrl));
    663     SOC_IF_ERROR_RETURN(READ_XLMAC_EEE_CTRLr(unit, port, &port_cfg->eee_ctrl));
    664     SOC_IF_ERROR_RETURN(READ_XLMAC_EEE_TIMERSr(unit, port, &port_cfg->eee_timers));
    665     SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &port_cfg->rx_lss_ctrl));
    666     SOC_IF_ERROR_RETURN(READ_XLMAC_RX_VLAN_TAGr(unit, port, &port_cfg->rx_vlan_tag));
    667     SOC_IF_ERROR_RETURN(READ_XLMAC_E2E_CTRLr(unit, port, &port_cfg->e2e_ctrl));
    668     return SOC_E_NONE;
    669 }
    670 
    671 STATIC int _xlmac_x_register_restore(int unit, soc_port_t port, _xlmac_x_cfg_t *port_cfg)
    672 {
    673     SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, port_cfg->mac_ctrl));
    674     SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_CTRLr(unit, port, port_cfg->rx_ctrl));
    675     SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, port_cfg->tx_ctrl));
    676     SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_CTRLr(unit, port, port_cfg->pfc_ctrl));
    677     SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_TYPEr(unit, port, port_cfg->pfc_type));
    678     SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_OPCODEr(unit, port, port_cfg->pfc_opcode));
    679     SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_DAr(unit, port, port_cfg->pfc_da));
    680     SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_MAX_SIZEr(unit, port, port_cfg->rx_max_size));
    681     SOC_IF_ERROR_RETURN(WRITE_XLMAC_MODEr(unit, port, port_cfg->mac_mode));
    682     SOC_IF_ERROR_RETURN(WRITE_XLMAC_PAUSE_CTRLr(unit, port, port_cfg->pause_ctrl));
    683     SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_MAC_SAr(unit, port, port_cfg->rx_mac_sa));
    684     SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_MAC_SAr(unit, port, port_cfg->tx_mac_sa));
    685     SOC_IF_ERROR_RETURN(WRITE_XLMAC_LLFC_CTRLr(unit, port, port_cfg->llfc_ctrl));
    686     SOC_IF_ERROR_RETURN(WRITE_XLMAC_EEE_CTRLr(unit, port, port_cfg->eee_ctrl));
    687     SOC_IF_ERROR_RETURN(WRITE_XLMAC_EEE_TIMERSr(unit, port, port_cfg->eee_timers));
    688     SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_LSS_CTRLr(unit, port, port_cfg->rx_lss_ctrl));
    689     SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_VLAN_TAGr(unit, port, port_cfg->rx_vlan_tag));
    690     SOC_IF_ERROR_RETURN(WRITE_XLMAC_E2E_CTRLr(unit, port, port_cfg->e2e_ctrl));
    691     return SOC_E_NONE;
    692 }
    693 
    694 int _xlmac_sb2_shim_war(int unit, soc_port_t port)
    695 {
    696     uint32 soft_reset;
    697     uint32 rval;
    698     int p, index;
    699     uint64 ctrl;
    700     pbmp_t block_pbmp;
    701     _xlmac_x_cfg_t *pcfg;
    702     int speed = 1000;
    703     
    704     BCM_PBMP_ASSIGN(block_pbmp, SOC_BLOCK_BITMAP(unit, SOC_PORT_BLOCK(unit, port)));
    705 
    706     SOC_PBMP_ITER(block_pbmp, p) {
    707         if (SOC_PBMP_MEMBER((PBMP_ALL(unit)), p)) {
    708             SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, p, &ctrl));
    709             soft_reset = soc_reg64_field32_get(unit, 
    710                     XLMAC_CTRLr, ctrl, SOFT_RESETf);
    711             /* If any of the port in block is active, dont apply war */
    712             if(soft_reset != 1) {
    713                 return SOC_E_NONE;
    714             }
    715         }
    716     }
    717     /* Come here only when there is active war */
    718     pcfg = (_xlmac_x_cfg_t *) sal_alloc(
    719             sizeof(_xlmac_x_cfg_t) * SB2_MAX_PORTS_PER_BLOCK,"XLMAC config");
    720     if (pcfg == NULL) {
    721         return SOC_E_MEMORY;
    722     }
    723 
    724     index = 0;
    725     SOC_PBMP_ITER(block_pbmp, p) {
    726         if (SOC_PBMP_MEMBER((PBMP_ALL(unit)), p)) {
    727             if(index >= SB2_MAX_PORTS_PER_BLOCK) {
    728                 sal_free(pcfg);
    729                 return SOC_E_INTERNAL;
    730             }
    731             SOC_IF_ERROR_CLEAN_RETURN
    732                 (_xlmac_x_register_store(unit, p, &pcfg[index]),sal_free(pcfg));
    733             index++;     
    734         }
    735     }
    736     p = SOC_BLOCK_PORT(unit, SOC_PORT_BLOCK(unit, port));
    737     SOC_IF_ERROR_CLEAN_RETURN(READ_XPORT_XMAC_CONTROLr(unit, p, &rval), sal_free(pcfg));
    738     soc_reg_field_set(unit, XPORT_XMAC_CONTROLr, &rval, XMAC_RESETf, 1);
    739     SOC_IF_ERROR_CLEAN_RETURN(WRITE_XPORT_XMAC_CONTROLr(unit, p, rval), sal_free(pcfg));
    740     soc_reg_field_set(unit, XPORT_XMAC_CONTROLr, &rval, XMAC_RESETf, 0);
    741     SOC_IF_ERROR_CLEAN_RETURN(WRITE_XPORT_XMAC_CONTROLr(unit, p, rval), sal_free(pcfg));
    742     
    743     index = 0;
    744     SOC_PBMP_ITER(block_pbmp, p) {
    745         if (SOC_PBMP_MEMBER((PBMP_ALL(unit)), p)) {
    746             SOC_IF_ERROR_CLEAN_RETURN
    747                 (_xlmac_x_register_restore(unit, p, &pcfg[index]),
    748                  sal_free(pcfg));
    749             index++;
    750         }
    751     }
    752     sal_free(pcfg);
    753 
    754     /* reconfigure timestamp adjust after port block reset */
    755     index = 0;
    756     SOC_PBMP_ITER(block_pbmp, p) {
    757         if (SOC_PBMP_MEMBER((PBMP_ALL(unit)), p)) {
    758             mac_xl_speed_get(unit, p, &speed);
    759             _mac_xl_timestamp_delay_set(unit, p, speed);
    760             index++;
    761         }
    762     }
    763     return SOC_E_NONE;
    764 }
    765 #endif
    766 
    767 /*
    768  * Function:
    769  *      mac_xl_enable_set
    770  * Purpose:
    771  *      Enable or disable MAC
    772  * Parameters:
    773  *      unit - XGS unit #.
    774  *      port - Port number on unit.
    775  *      enable - TRUE to enable, FALSE to disable
    776  * Returns:
    777  *      SOC_E_XXX
    778  */
    779 STATIC int
    780 mac_xl_enable_set(int unit, soc_port_t port, int enable)
    781 {
    782     uint64 ctrl, octrl;
    783     pbmp_t mask;
    784     uint32 soft_reset = 0;
    785     int speed = 1000;
    786     uint64 version, merge_config;
    787     int xlmac_version;
    788 
    789     LOG_VERBOSE(BSL_LS_SOC_10G,
    790                 (BSL_META_U(unit,
    791                         "mac_xl_enable_set: unit %d port %s enable=%s\n"),
    792                  unit, SOC_PORT_NAME(unit, port),
    793                  enable ? "True" : "False"));
    794 
    795     SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &ctrl));
    796     octrl = ctrl;
    797     /* Don't disable TX since it stops egress and hangs if CPU sends */
    798     soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, TX_ENf, 1);
    799     soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, RX_ENf, enable ? 1 : 0);
    800 
    801     if (COMPILER_64_EQ(ctrl, octrl)) {
    802         /* SDK-49952 fix soluition :
    803          *  >> to avoid the unexpected early return to prevent this problem.
    804          *  1. Problem occurred for disabling process only.
    805          *  2. To comply origianl designing senario, XLMAC_CTRLr.SOFT_RESETf is 
    806          *      used to early check to see if this port is at disabled state 
    807          *      already.
    808          */
    809         soft_reset = soc_reg64_field32_get(unit, 
    810                 XLMAC_CTRLr, ctrl, SOFT_RESETf);
    811         if ((enable) || (!enable && soft_reset)){
    812             return SOC_E_NONE;
    813         }
    814     }
    815 
    816     if (enable) {
    817         /* Reset EP credit before de-assert SOFT_RESET */
    818         SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port));
    819 
    820 #if defined(BCM_SABER2_SUPPORT)
    821         if (SOC_IS_SABER2(unit)) {
    822             SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, FALSE));
    823         }
    824 #endif
    825 
    826         /* Deassert SOFT_RESET */
    827         soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, SOFT_RESETf, 0);
    828 
    829         /* Deassert EGR_XLPORT_BUFFER_SFT_RESET */
    830         SOC_IF_ERROR_RETURN(soc_port_egress_buffer_sft_reset(unit, port, 0));
    831 
    832         /* Enable both TX and RX */
    833         SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl));
    834 
    835         /* Enable MMU port */
    836         SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, TRUE));
    837 
    838         /* Add port to EPC_LINK */
    839         soc_link_mask2_get(unit, &mask);
    840         SOC_PBMP_PORT_ADD(mask, port);
    841         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    842 
    843         /* Enable output threshold RX */
    844         SOC_IF_ERROR_RETURN
    845             (soc_port_thdo_rx_enable_set(unit, port, 1));        
    846 
    847         /* set timestamp adjust delay */
    848         mac_xl_speed_get(unit, port, &speed);
    849         _mac_xl_timestamp_delay_set(unit, port, speed);
    850     } else {
    851         /* Disable RX */
    852         SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl));
    853 
    854         /* Remove port from EPC_LINK */
    855         soc_link_mask2_get(unit, &mask);
    856         SOC_PBMP_PORT_REMOVE(mask, port);
    857         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    858         sal_udelay(1000);
    859 
    860         /*
    861          * Disable MMU port
    862          * for some devices where EPC_LINK can not block the SOBMH from cpu and
    863          * no mechanism is avalible to reset EDATABUF.
    864          */
    865         SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, FALSE));
    866 
    867         /* Drain cells */
    868         SOC_IF_ERROR_RETURN(_mac_xl_drain_cells(unit, port, 1, FALSE));
    869         /* Reset egress_buffer */
    870         SOC_IF_ERROR_RETURN(soc_port_egress_buffer_sft_reset(unit, port, 1));
    871 
    872         /* Reset port FIFO */
    873         SOC_IF_ERROR_RETURN(soc_port_fifo_reset(unit, port));
    874 
    875         /* Put port into SOFT_RESET */
    876         soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, SOFT_RESETf, 1);
    877         SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl));
    878 #if defined(BCM_SABER2_SUPPORT) 
    879         if(SOC_IS_SABER2(unit) && IS_MXQ_PORT(unit, port)) {
    880             SOC_IF_ERROR_RETURN(_xlmac_sb2_shim_war(unit, port));
    881         }
    882 #endif
    883         /* Disable output threshold RX */
    884         SOC_IF_ERROR_RETURN
    885             (soc_port_thdo_rx_enable_set(unit, port, 0));          
    886 
    887         /* Forces rx_lost_eop sequence */
    888         if (SOC_REG_IS_VALID(unit, XLMAC_VERSION_IDr) &&
    889             SOC_REG_IS_VALID(unit, XLMAC_MERGE_CONFIGr)) {
    890 
    891             SOC_IF_ERROR_RETURN(READ_XLMAC_VERSION_IDr(unit, port, &version));
    892             xlmac_version =
    893                 soc_reg64_field32_get(
    894                     unit, XLMAC_VERSION_IDr, version, XLMAC_VERSIONf);
    895             if (xlmac_version >= 0xA043) {
    896                 /* Set SW force */
    897                 SOC_IF_ERROR_RETURN(
    898                     READ_XLMAC_MERGE_CONFIGr(unit, port, &merge_config));
    899                 soc_reg64_field32_set(
    900                     unit, XLMAC_MERGE_CONFIGr, &merge_config,
    901                     SW_FORCE_RX_LOST_EOPf, 1);
    902                 SOC_IF_ERROR_RETURN(
    903                     WRITE_XLMAC_MERGE_CONFIGr(unit, port, merge_config));
    904 
    905                 /* Clear SW force */
    906                 SOC_IF_ERROR_RETURN(
    907                     READ_XLMAC_MERGE_CONFIGr(unit, port, &merge_config));
    908                 soc_reg64_field32_set(
    909                     unit, XLMAC_MERGE_CONFIGr, &merge_config,
    910                     SW_FORCE_RX_LOST_EOPf, 0);
    911                 SOC_IF_ERROR_RETURN(
    912                     WRITE_XLMAC_MERGE_CONFIGr(unit, port, merge_config));
    913             }
    914         }
    915 
    916     }
    917 
    918     return SOC_E_NONE;
    919 }
    920 
    921 /*
    922  * Function:
    923  *      mac_xl_enable_get
    924  * Purpose:
    925  *      Get MAC enable state
    926  * Parameters:
    927  *      unit - XGS unit #.
    928  *      port - Port number on unit.
    929  *      enable - (OUT) TRUE if enabled, FALSE if disabled
    930  * Returns:
    931  *      SOC_E_XXX
    932  */
    933 STATIC int
    934 mac_xl_enable_get(int unit, soc_port_t port, int *enable)
    935 {
    936     uint64 ctrl;
    937 
    938     SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &ctrl));
    939 
    940     *enable = soc_reg64_field32_get(unit, XLMAC_CTRLr, ctrl, RX_ENf);
    941 
    942     LOG_VERBOSE(BSL_LS_SOC_10G,
    943                 (BSL_META_U(unit,
    944                             "mac_xl_enable_get: unit %d port %s enable=%s\n"),
    945                  unit, SOC_PORT_NAME(unit, port),
    946                  *enable ? "True" : "False"));
    947 
    948     return SOC_E_NONE;
    949 }
    950 
    951 
    952 
    953 /*
    954  * Function:
    955  *      _mac_xl_timestamp_delay_set
    956  * Purpose:
    957  *      Set Timestamp delay for one-step to account for lane and pipeline delay.
    958  * Parameters:
    959  *      unit - XGS unit #.
    960  *      port - Port number on unit.
    961  *      speed - Speed
    962  *      phy_mode - single/dual/quad phy mode
    963  * Returns:
    964  *      SOC_E_XXX
    965  */
    966 STATIC int
    967 _mac_xl_timestamp_delay_set(int unit, soc_port_t port, int speed)
    968 {
    969     uint64 ctrl;
    970     uint32 clk_rate, tx_clk_ns;
    971     int osts_delay;
    972     uint32 field;
    973     int divisor;
    974 
    975     LOG_VERBOSE(BSL_LS_SOC_10G,
    976                 (BSL_META_U(unit,
    977                  "mac_xl_timestamp_delay_set: unit %d speed=%dMb port %s\n"),
    978                  unit, speed, SOC_PORT_NAME(unit, port)));
    979 
    980     if (SOC_REG_IS_VALID(unit, XLMAC_TIMESTAMP_ADJUSTr)) {
    981         SOC_IF_ERROR_RETURN(READ_XLMAC_TIMESTAMP_ADJUSTr(unit, port, &ctrl));
    982 
    983         _mac_xl_speed_to_clock_rate(unit, port, speed, &clk_rate);
    984         /* Tx clock rate for single/dual/quad phy mode */
    985         if ((speed >= 5000) && (speed <= 40000)) {
    986             divisor = speed > 20000 ? 1 : speed > 10000 ? 2 : 4;
    987             /* tx clock rate in ns */
    988             tx_clk_ns = ((1000 / clk_rate) / divisor);
    989         } else {
    990             /* Same tx clk rate for < 10G  for all phy modes*/
    991             tx_clk_ns = 1000 / clk_rate;
    992         }
    993 
    994         
    995         
    996         /*
    997          * MAC pipeline delay for XGMII/XGMII mode is:
    998          *          = (5.5 * TX line clock period) + (Timestamp clock period)
    999          */
   1000         /* signed value of pipeline delay in ns */
   1001         osts_delay = soc_property_port_get(unit, port, spn_TIMESTAMP_ADJUST(speed),
   1002                                            SOC_TIMESYNC_PLL_CLOCK_NS(unit) -
   1003                                            ((11 * tx_clk_ns ) / 2));
   1004 
   1005         if (SOC_E_NONE != soc_reg_signed_field_mask(unit, XLMAC_TIMESTAMP_ADJUSTr,
   1006                                                     TS_OSTS_ADJUSTf, osts_delay, &field)) {
   1007             LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit,
   1008                  "%s property out of bounds (is %d)\n"),
   1009                  spn_TIMESTAMP_ADJUST(speed), osts_delay));
   1010             field = 0;
   1011         }
   1012 
   1013         soc_reg64_field32_set(unit, XLMAC_TIMESTAMP_ADJUSTr, &ctrl,
   1014                               TS_OSTS_ADJUSTf, field);
   1015 
   1016 #if 0 
   1017         /*
   1018          * Lane delay for xlmac lanes
   1019          *   Lane_0(0-3)  : 1 * TX line clock period
   1020          *   Lane_1(4-7)  : 2 * TX line clock period
   1021          *   Lane_2(8-11) : 3 * TX line clock period
   1022          *   Lane_3(12-15): 4 * TX line clock period
   1023          */
   1024         /* unsigned value of lane delay in ns */
   1025         delay = 1 * tx_clk_ns;
   1026         soc_reg64_field32_set(unit, XLMAC_OSTS_TIMESTAMP_ADJUSTr, &ctrl,
   1027                               TS_ADJUST_DEMUX_DELAY_0f, delay );
   1028         delay = 2 * tx_clk_ns;
   1029         soc_reg64_field32_set(unit, XLMAC_OSTS_TIMESTAMP_ADJUSTr, &ctrl,
   1030                               TS_ADJUST_DEMUX_DELAY_1f, delay );
   1031         delay = 3 * tx_clk_ns;
   1032         soc_reg64_field32_set(unit, XLMAC_OSTS_TIMESTAMP_ADJUSTr, &ctrl,
   1033                               TS_ADJUST_DEMUX_DELAY_2f, delay );
   1034         delay = 4 * tx_clk_ns;
   1035         soc_reg64_field32_set(unit, XLMAC_OSTS_TIMESTAMP_ADJUSTr, &ctrl,
   1036                               TS_ADJUST_DEMUX_DELAY_3f, delay );
   1037 #endif
   1038         SOC_IF_ERROR_RETURN(WRITE_XLMAC_TIMESTAMP_ADJUSTr(unit, port, ctrl));
   1039     }
   1040 
   1041     /* Set Timestamp byte adjust values */
   1042     SOC_IF_ERROR_RETURN(_mac_xl_timestamp_byte_adjust_set(unit, port));
   1043 
   1044     return SOC_E_NONE;
   1045 }
   1046 
   1047 /*
   1048  * Function:
   1049  *      mac_xl_duplex_set
   1050  * Purpose:
   1051  *      Set XLMAC in the specified duplex mode.
   1052  * Parameters:
   1053  *      unit - XGS unit #.
   1054  *      port - XGS port # on unit.
   1055  *      duplex - Boolean: true --> full duplex, false --> half duplex.
   1056  * Returns:
   1057  *      SOC_E_XXX
   1058  * Notes:
   1059  */
   1060 STATIC int
   1061 mac_xl_duplex_set(int unit, soc_port_t port, int duplex)
   1062 {
   1063     LOG_VERBOSE(BSL_LS_SOC_10G,
   1064                 (BSL_META_U(unit,
   1065                             "mac_xl_duplex_set: unit %d port %s duplex=%s\n"),
   1066                  unit, SOC_PORT_NAME(unit, port),
   1067                  duplex ? "Full" : "Half"));
   1068     return SOC_E_NONE;
   1069 }
   1070 
   1071 /*
   1072  * Function:
   1073  *      mac_xl_duplex_get
   1074  * Purpose:
   1075  *      Get XLMAC duplex mode.
   1076  * Parameters:
   1077  *      unit - XGS unit #.
   1078  *      duplex - (OUT) Boolean: true --> full duplex, false --> half duplex.
   1079  * Returns:
   1080  *      SOC_E_XXX
   1081  */
   1082 STATIC int
   1083 mac_xl_duplex_get(int unit, soc_port_t port, int *duplex)
   1084 {
   1085     *duplex = TRUE; /* Always full duplex */
   1086 
   1087     LOG_VERBOSE(BSL_LS_SOC_10G,
   1088                 (BSL_META_U(unit,
   1089                             "mac_xl_duplex_get: unit %d port %s duplex=%s\n"),
   1090                  unit, SOC_PORT_NAME(unit, port),
   1091                  *duplex ? "Full" : "Half"));
   1092     return SOC_E_NONE;
   1093 }
   1094 
   1095 /*
   1096  * Function:
   1097  *      mac_xl_pause_set
   1098  * Purpose:
   1099  *      Configure XLMAC to transmit/receive pause frames.
   1100  * Parameters:
   1101  *      unit - XGS unit #.
   1102  *      port - XGS port # on unit.
   1103  *      pause_tx - Boolean: transmit pause or -1 (don't change)
   1104  *      pause_rx - Boolean: receive pause or -1 (don't change)
   1105  * Returns:
   1106  *      SOC_E_XXX
   1107  */
   1108 STATIC int
   1109 mac_xl_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx)
   1110 {
   1111     static soc_field_t fields[2] = { TX_PAUSE_ENf, RX_PAUSE_ENf };
   1112     uint32 values[2];
   1113 
   1114     LOG_VERBOSE(BSL_LS_SOC_10G,
   1115                 (BSL_META_U(unit,
   1116                             "mac_xl_pause_set: unit %d port %s TX=%s RX=%s\n"),
   1117                  unit, SOC_PORT_NAME(unit, port),
   1118                  pause_tx != FALSE ? "on" : "off",
   1119                  pause_rx != FALSE ? "on" : "off"));
   1120 
   1121     values[0] = pause_tx != FALSE ? 1 : 0;
   1122     values[1] = pause_rx != FALSE ? 1 : 0;
   1123     return soc_reg_fields32_modify(unit, XLMAC_PAUSE_CTRLr, port, 2,
   1124                                    fields, values);
   1125 }
   1126 
   1127 /*
   1128  * Function:
   1129  *      mac_xl_pause_get
   1130  * Purpose:
   1131  *      Return the pause ability of XLMAC
   1132  * Parameters:
   1133  *      unit - XGS unit #.
   1134  *      port - XGS port # on unit.
   1135  *      pause_tx - Boolean: transmit pause
   1136  *      pause_rx - Boolean: receive pause
   1137  *      pause_mac - MAC address used for pause transmission.
   1138  * Returns:
   1139  *      SOC_E_XXX
   1140  */
   1141 STATIC int
   1142 mac_xl_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx)
   1143 {
   1144     uint64 rval;
   1145 
   1146     SOC_IF_ERROR_RETURN(READ_XLMAC_PAUSE_CTRLr(unit, port, &rval));
   1147     *pause_tx =
   1148         soc_reg64_field32_get(unit, XLMAC_PAUSE_CTRLr, rval, TX_PAUSE_ENf);
   1149     *pause_rx =
   1150         soc_reg64_field32_get(unit, XLMAC_PAUSE_CTRLr, rval, RX_PAUSE_ENf);
   1151     LOG_VERBOSE(BSL_LS_SOC_10G,
   1152                 (BSL_META_U(unit,
   1153                             "mac_xl_pause_get: unit %d port %s TX=%s RX=%s\n"),
   1154                  unit, SOC_PORT_NAME(unit, port),
   1155                  *pause_tx ? "on" : "off",
   1156                  *pause_rx ? "on" : "off"));
   1157     return SOC_E_NONE;
   1158 }
   1159 
   1160 /*
   1161  * Function:
   1162  *      mac_xl_speed_set
   1163  * Purpose:
   1164  *      Set XLMAC in the specified speed.
   1165  * Parameters:
   1166  *      unit - XGS unit #.
   1167  *      port - XGS port # on unit.
   1168  *      speed - 10, 100, 1000, 2500, 10000, ...
   1169  * Returns:
   1170  *      SOC_E_XXX
   1171  */
   1172 STATIC int
   1173 mac_xl_speed_set(int unit, soc_port_t port, int speed)
   1174 {
   1175     uint32 mode;
   1176     int enable;
   1177     static soc_field_t fields[2] = {
   1178         LOCAL_FAULT_DISABLEf, REMOTE_FAULT_DISABLEf
   1179     };
   1180     uint32 values[2];
   1181     uint32 rval = 0;
   1182 
   1183 #ifdef BCM_GREYHOUND2_SUPPORT
   1184     /* SDK-141840 Workaround for TSCE core connecting to Aquantia PHY */
   1185     if (SOC_IS_GREYHOUND2(unit)) {
   1186         SOC_IF_ERROR_RETURN
   1187             (soc_reg_field32_modify(unit, XLMAC_TX_CTRLr, port, TX_ANY_STARTf,
   1188                                     0));
   1189     }
   1190 #endif
   1191 
   1192     LOG_VERBOSE(BSL_LS_SOC_10G,
   1193                 (BSL_META_U(unit,
   1194                             "mac_xl_speed_set: unit %d port %s speed=%dMb\n"),
   1195                  unit, SOC_PORT_NAME(unit, port),
   1196                  speed));
   1197 
   1198     switch (speed) {
   1199     case 10:
   1200         mode = SOC_XLMAC_SPEED_10;
   1201         break;
   1202     case 100:
   1203         mode = SOC_XLMAC_SPEED_100;
   1204         break;
   1205     case 1000:
   1206         mode = SOC_XLMAC_SPEED_1000;
   1207         break;
   1208     case 2500:
   1209 #ifdef BCM_GREYHOUND2_SUPPORT
   1210         /* SDK-141840 Workaround for TSCE core connecting to Aquantia PHY */
   1211         if (SOC_IS_GREYHOUND2(unit)) {
   1212             SOC_IF_ERROR_RETURN
   1213                 (soc_reg_field32_modify(unit, XLMAC_TX_CTRLr, port,
   1214                                         TX_ANY_STARTf, 1));
   1215         }
   1216 #endif
   1217         mode = SOC_XLMAC_SPEED_2500;
   1218         break;
   1219     case 5000:
   1220         mode = SOC_XLMAC_SPEED_10000;
   1221         break;
   1222     case 0:
   1223         return SOC_E_NONE;              /* Support NULL PHY */
   1224     default:
   1225         if (speed < 10000) {
   1226             return SOC_E_PARAM;
   1227         }
   1228         mode = SOC_XLMAC_SPEED_10000;
   1229         break;
   1230     }
   1231 
   1232     SOC_IF_ERROR_RETURN(mac_xl_enable_get(unit, port, &enable));
   1233         
   1234     if (enable) {
   1235         /* Turn off TX/RX enable */
   1236         SOC_IF_ERROR_RETURN(mac_xl_enable_set(unit, port, 0));
   1237     }
   1238 
   1239     /* Update the speed */
   1240     SOC_IF_ERROR_RETURN
   1241         (soc_reg_field32_modify(unit, XLMAC_MODEr, port, SPEED_MODEf, mode));
   1242 
   1243     values[0] = values[1] = speed < 5000 ? 1 : 0;
   1244     if (speed < 5000) {
   1245     SOC_IF_ERROR_RETURN
   1246         (soc_reg_fields32_modify(unit, XLMAC_RX_LSS_CTRLr, port, 2, fields,
   1247                                  values));
   1248     }
   1249 
   1250     /*
   1251      * Not set REMOTE_FAULT/LOCAL_FAULT for 1G ports,
   1252      * else HW Linkscan interrupt would be suppressed.
   1253      */
   1254     if (SOC_IS_SABER2(unit) && IS_MXQ_PORT(unit, port)) {
   1255          /* XLPORT_FAULT_LINK_STATUS is NA for MXQ ports on Saber2*/
   1256     } else {
   1257         values[0] = values[1] = speed <= 1000 ? 0 : 1;
   1258         soc_reg_field_set(unit, XLPORT_FAULT_LINK_STATUSr, &rval,
   1259                       REMOTE_FAULTf, values[0]);
   1260         soc_reg_field_set(unit, XLPORT_FAULT_LINK_STATUSr, &rval,
   1261                       LOCAL_FAULTf, values[1]);
   1262         SOC_IF_ERROR_RETURN(WRITE_XLPORT_FAULT_LINK_STATUSr(unit, port, rval));
   1263     }
   1264 
   1265     /* Update port speed related setting in components other than MAC/SerDes*/
   1266     SOC_IF_ERROR_RETURN(soc_port_speed_update(unit, port, speed));
   1267 
   1268     /* Update port strict preamble */
   1269     SOC_IF_ERROR_RETURN
   1270         (soc_reg_field32_modify(unit, XLMAC_RX_CTRLr, port, STRICT_PREAMBLEf,
   1271                                 speed >= 10000 && IS_XE_PORT(unit, port) ?
   1272                                 1 : 0));
   1273     /*
   1274      * Notify internal PHY driver of speed change in case it is being
   1275      * used as pass-through to an external PHY.
   1276      */
   1277     if (!PHY_REPEATER(unit, port)) {
   1278         SOC_IF_ERROR_RETURN
   1279             (soc_phyctrl_notify(unit, port, phyEventSpeed, speed));
   1280     }
   1281 
   1282     if (enable) {
   1283         /* Re-enable transmitter and receiver */
   1284         SOC_IF_ERROR_RETURN(mac_xl_enable_set(unit, port, 1));
   1285     }
   1286 
   1287     /* Set Timestamp Mac Delays */
   1288     SOC_IF_ERROR_RETURN(_mac_xl_timestamp_delay_set(unit, port, speed));
   1289 
   1290     /* assigning proper setting for Native EEE per speed */
   1291     if (soc_feature(unit, soc_feature_eee)) {
   1292         SOC_IF_ERROR_RETURN(soc_port_eee_timers_setup(unit, port, speed));
   1293     }
   1294 
   1295     return SOC_E_NONE;
   1296 }
   1297 
   1298 /*
   1299  * Function:
   1300  *      mac_xl_speed_get
   1301  * Purpose:
   1302  *      Get XLMAC speed
   1303  * Parameters:
   1304  *      unit - XGS unit #.
   1305  *      port - XGS port # on unit.
   1306  *      speed - (OUT) speed in Mb
   1307  * Returns:
   1308  *      SOC_E_XXX
   1309  */
   1310 STATIC int
   1311 mac_xl_speed_get(int unit, soc_port_t port, int *speed)
   1312 {
   1313     uint64 rval;
   1314 #ifdef BCM_GREYHOUND2_SUPPORT
   1315     int val = 0;
   1316 #endif
   1317 
   1318     SOC_IF_ERROR_RETURN(READ_XLMAC_MODEr(unit, port, &rval));
   1319     switch (soc_reg64_field32_get(unit, XLMAC_MODEr, rval, SPEED_MODEf)) {
   1320     case SOC_XLMAC_SPEED_10:
   1321         *speed = 10;
   1322         break;
   1323     case SOC_XLMAC_SPEED_100:
   1324         *speed = 100;
   1325         break;
   1326     case SOC_XLMAC_SPEED_1000:
   1327         *speed = 1000;
   1328         break;
   1329     case SOC_XLMAC_SPEED_2500:
   1330         *speed = 2500;
   1331         break;
   1332     case SOC_XLMAC_SPEED_10000:
   1333     default:
   1334         *speed = 10000;
   1335         break;
   1336     }
   1337 #ifdef BCM_GREYHOUND2_SUPPORT
   1338     if (soc_feature(unit, soc_feature_xlmac_speed_display_above_10g)) {
   1339         if (SOC_SUCCESS(soc_granular_speed_get(unit, port, &val))) {
   1340             *speed = val;
   1341         }
   1342     }
   1343 #endif
   1344     LOG_VERBOSE(BSL_LS_SOC_10G,
   1345                 (BSL_META_U(unit,
   1346                             "mac_xl_speed_get: unit %d port %s speed=%dMb\n"),
   1347                  unit, SOC_PORT_NAME(unit, port),
   1348                  *speed));
   1349     return SOC_E_NONE;
   1350 }
   1351 
   1352 /*
   1353  * Function:
   1354  *      mac_xl_loopback_set
   1355  * Purpose:
   1356  *      Set a XLMAC into/out-of loopback mode
   1357  * Parameters:
   1358  *      unit - XGS unit #.
   1359  *      port - XGS unit # on unit.
   1360  *      loopback - Boolean: true -> loopback mode, false -> normal operation
   1361  * Note:
   1362  *      On Xlmac, when setting loopback, we enable the TX/RX function also.
   1363  *      Note that to test the PHY, we use the remote loopback facility.
   1364  * Returns:
   1365  *      SOC_E_XXX
   1366  */
   1367 STATIC int
   1368 mac_xl_loopback_set(int unit, soc_port_t port, int lb)
   1369 {
   1370     LOG_VERBOSE(BSL_LS_SOC_10G,
   1371                 (BSL_META_U(unit,
   1372                             "mac_xl_loopback_set: unit %d port %s loopback=%s\n"),
   1373                  unit, SOC_PORT_NAME(unit, port),
   1374                  lb ? "local" : "no"));
   1375 
   1376     /* need to enable clock compensation for applicable serdes device */
   1377     (void)soc_phyctrl_notify(unit, port, phyEventMacLoopback, lb ? 1 : 0);
   1378 
   1379     SOC_IF_ERROR_RETURN
   1380         (soc_mac_xl.md_control_set(unit, port,
   1381                                    SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE,
   1382                                    lb ? 0 : 1));
   1383     SOC_IF_ERROR_RETURN
   1384         (soc_mac_xl.md_control_set(unit, port,
   1385                                    SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE,
   1386                                    lb ? 0 : 1));
   1387 
   1388     return soc_reg_field32_modify(unit, XLMAC_CTRLr, port, LOCAL_LPBKf,
   1389                                   lb ? 1 : 0);
   1390 
   1391     return SOC_E_NONE;
   1392 }
   1393 
   1394 /*
   1395  * Function:
   1396  *      mac_xl_loopback_get
   1397  * Purpose:
   1398  *      Get current XLMAC loopback mode setting.
   1399  * Parameters:
   1400  *      unit - XGS unit #.
   1401  *      port - XGS port # on unit.
   1402  *      loopback - (OUT) Boolean: true = loopback, false = normal
   1403  * Returns:
   1404  *      SOC_E_XXX
   1405  */
   1406 STATIC int
   1407 mac_xl_loopback_get(int unit, soc_port_t port, int *lb)
   1408 {
   1409     uint64 ctrl;
   1410 
   1411     SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &ctrl));
   1412 
   1413     *lb = soc_reg64_field32_get(unit, XLMAC_CTRLr, ctrl, LOCAL_LPBKf);
   1414 
   1415     LOG_VERBOSE(BSL_LS_SOC_10G,
   1416                 (BSL_META_U(unit,
   1417                             "mac_xl_loopback_get: unit %d port %s loopback=%s\n"),
   1418                  unit, SOC_PORT_NAME(unit, port),
   1419                  *lb ? "True" : "False"));
   1420     return SOC_E_NONE;
   1421 }
   1422 
   1423 /*
   1424  * Function:
   1425  *      mac_xl_pause_addr_set
   1426  * Purpose:
   1427  *      Configure PAUSE frame source address.
   1428  * Parameters:
   1429  *      unit - XGS unit #.
   1430  *      port - XGS port # on unit.
   1431  *      pause_mac - (OUT) MAC address used for pause transmission.
   1432  * Returns:
   1433  *      SOC_E_XXX
   1434  */
   1435 STATIC int
   1436 mac_xl_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t mac)
   1437 {
   1438     static soc_field_t fields[2] = { SA_HIf, SA_LOf };
   1439     uint32 values[2];
   1440 
   1441     LOG_VERBOSE(BSL_LS_SOC_10G,
   1442                 (BSL_META_U(unit,
   1443                             "mac_xl_pause_addr_set: unit %d port %s MAC=<"
   1444                             "%02x:%02x:%02x:%02x:%02x:%02x>\n"),
   1445                  unit, SOC_PORT_NAME(unit, port),
   1446                  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
   1447 
   1448     values[0] = (mac[0] << 8) | mac[1];
   1449     values[1] = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
   1450 
   1451     SOC_IF_ERROR_RETURN
   1452         (soc_reg_fields32_modify(unit, XLMAC_TX_MAC_SAr, port, 2, fields,
   1453                                  values));
   1454     SOC_IF_ERROR_RETURN
   1455         (soc_reg_fields32_modify(unit, XLMAC_RX_MAC_SAr, port, 2, fields,
   1456                                  values));
   1457 
   1458     return SOC_E_NONE;
   1459 }
   1460 
   1461 /*
   1462  * Function:
   1463  *      mac_xl_pause_addr_get
   1464  * Purpose:
   1465  *      Retrieve PAUSE frame source address.
   1466  * Parameters:
   1467  *      unit - XGS unit #.
   1468  *      port - XGS port # on unit.
   1469  *      pause_mac - (OUT) MAC address used for pause transmission.
   1470  * Returns:
   1471  *      SOC_E_XXX
   1472  * NOTE: We always write the same thing to TX & RX SA
   1473  *       so, we just return the contects on RX_MAC_SA.
   1474  */
   1475 STATIC int
   1476 mac_xl_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t mac)
   1477 {
   1478     uint64 rval64;
   1479     uint32 values[2];
   1480 
   1481     SOC_IF_ERROR_RETURN(READ_XLMAC_RX_MAC_SAr(unit, port, &rval64));
   1482     values[0] = soc_reg64_field32_get(unit, XLMAC_RX_MAC_SAr, rval64, SA_HIf);
   1483     values[1] = soc_reg64_field32_get(unit, XLMAC_RX_MAC_SAr, rval64, SA_LOf);
   1484 
   1485     mac[0] = (values[0] & 0x0000ff00) >> 8;
   1486     mac[1] = values[0] & 0x000000ff;
   1487     mac[2] = (values[1] & 0xff000000) >> 24;
   1488     mac[3] = (values[1] & 0x00ff0000) >> 16;
   1489     mac[4] = (values[1] & 0x0000ff00) >> 8;
   1490     mac[5] = values[1] & 0x000000ff;
   1491 
   1492     LOG_VERBOSE(BSL_LS_SOC_10G,
   1493                 (BSL_META_U(unit,
   1494                             "mac_xl_pause_addr_get: unit %d port %s MAC=<"
   1495                             "%02x:%02x:%02x:%02x:%02x:%02x>\n"),
   1496                  unit, SOC_PORT_NAME(unit, port),
   1497                  mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
   1498     return SOC_E_NONE;
   1499 }
   1500 
   1501 /*
   1502  * Function:
   1503  *      mac_xl_interface_set
   1504  * Purpose:
   1505  *      Set a XLMAC interface type
   1506  * Parameters:
   1507  *      unit - XGS unit #.
   1508  *      port - XGS port # on unit.
   1509  *      pif - one of SOC_PORT_IF_*
   1510  * Returns:
   1511  *      SOC_E_NONE
   1512  *      SOC_E_UNAVAIL - requested mode not supported.
   1513  * Notes:
   1514  */
   1515 STATIC int
   1516 mac_xl_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   1517 {
   1518 #ifdef BROADCOM_DEBUG
   1519     LOG_VERBOSE(BSL_LS_SOC_10G,
   1520                 (BSL_META_U(unit,
   1521                             "mac_xl_interface_set: unit %d port %s interface=%s\n"),
   1522                  unit, SOC_PORT_NAME(unit, port),
   1523                  mac_xl_port_if_names[pif]));
   1524 #endif
   1525     return SOC_E_NONE;
   1526 }
   1527 
   1528 /*
   1529  * Function:
   1530  *      mac_xl_interface_get
   1531  * Purpose:
   1532  *      Retrieve XLMAC interface type
   1533  * Parameters:
   1534  *      unit - XGS unit #.
   1535  *      port - XGS port # on unit.
   1536  *      pif - (OUT) one of SOC_PORT_IF_*
   1537  * Returns:
   1538  *      SOC_E_NONE
   1539  */
   1540 STATIC int
   1541 mac_xl_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   1542 {
   1543     *pif = SOC_PORT_IF_MII;
   1544 
   1545 #ifdef BROADCOM_DEBUG
   1546     LOG_VERBOSE(BSL_LS_SOC_10G,
   1547                 (BSL_META_U(unit,
   1548                             "mac_xl_interface_get: unit %d port %s interface=%s\n"),
   1549                  unit, SOC_PORT_NAME(unit, port),
   1550                  mac_xl_port_if_names[*pif]));
   1551 #endif
   1552     return SOC_E_NONE;
   1553 }
   1554 
   1555 /*
   1556  * Function:
   1557  *      mac_xl_frame_max_set
   1558  * Description:
   1559  *      Set the maximum receive frame size for the port
   1560  * Parameters:
   1561  *      unit - Device number
   1562  *      port - Port number
   1563  *      size - Maximum frame size in bytes
   1564  * Return Value:
   1565  *      SOC_E_XXX
   1566  */
   1567 STATIC int
   1568 mac_xl_frame_max_set(int unit, soc_port_t port, int size)
   1569 {
   1570     LOG_VERBOSE(BSL_LS_SOC_10G,
   1571                 (BSL_META_U(unit,
   1572                             "mac_xl_frame_max_set: unit %d port %s size=%d\n"),
   1573                  unit, SOC_PORT_NAME(unit, port),
   1574                  size));
   1575 
   1576     if (IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)) {
   1577         /* For VLAN tagged packets */
   1578         size += 4;
   1579     }
   1580     return soc_reg_field32_modify(unit, XLMAC_RX_MAX_SIZEr, port, RX_MAX_SIZEf,
   1581                                   size);
   1582 }
   1583 
   1584 /*
   1585  * Function:
   1586  *      mac_xl_frame_max_get
   1587  * Description:
   1588  *      Set the maximum receive frame size for the port
   1589  * Parameters:
   1590  *      unit - Device number
   1591  *      port - Port number
   1592  *      size - Maximum frame size in bytes
   1593  * Return Value:
   1594  *      SOC_E_XXX
   1595  */
   1596 STATIC int
   1597 mac_xl_frame_max_get(int unit, soc_port_t port, int *size)
   1598 {
   1599     uint64 rval;
   1600 
   1601     SOC_IF_ERROR_RETURN(READ_XLMAC_RX_MAX_SIZEr(unit, port, &rval));
   1602     *size = soc_reg64_field32_get(unit, XLMAC_RX_MAX_SIZEr, rval,
   1603                                   RX_MAX_SIZEf);
   1604     if (IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)) {
   1605         /* For VLAN tagged packets */
   1606         *size -= 4;
   1607     }
   1608 
   1609     LOG_VERBOSE(BSL_LS_SOC_10G,
   1610                 (BSL_META_U(unit,
   1611                             "mac_xl_frame_max_get: unit %d port %s size=%d\n"),
   1612                  unit, SOC_PORT_NAME(unit, port),
   1613                  *size));
   1614     return SOC_E_NONE;
   1615 }
   1616 
   1617 /*
   1618  * Function:
   1619  *      mac_xl_ifg_set
   1620  * Description:
   1621  *      Sets the new ifg (Inter-frame gap) value
   1622  * Parameters:
   1623  *      unit   - Device number
   1624  *      port   - Port number
   1625  *      speed  - the speed for which the IFG is being set
   1626  *      duplex - the duplex for which the IFG is being set
   1627  *      ifg - number of bits to use for average inter-frame gap
   1628  * Return Value:
   1629  *      SOC_E_XXX
   1630  * Notes:
   1631  *      The function makes sure the IFG value makes sense and updates the
   1632  *      IPG register in case the speed/duplex match the current settings
   1633  */
   1634 STATIC int
   1635 mac_xl_ifg_set(int unit, soc_port_t port, int speed,
   1636                 soc_port_duplex_t duplex, int ifg)
   1637 {
   1638     int         cur_speed;
   1639     int         cur_duplex;
   1640     int         real_ifg;
   1641     int         encap = 0;
   1642 
   1643     soc_ipg_t  *si = &SOC_PERSIST(unit)->ipg[port];
   1644     uint64      rval, orval;
   1645     soc_port_ability_t ability;
   1646     uint32      pa_flag;
   1647 
   1648     LOG_VERBOSE(BSL_LS_SOC_10G,
   1649                 (BSL_META_U(unit,
   1650                             "mac_xl_ifg_set: unit %d port %s speed=%dMb duplex=%s "
   1651                             "ifg=%d\n"),
   1652                  unit, SOC_PORT_NAME(unit, port),
   1653                  speed, duplex ? "True" : "False", ifg));
   1654 
   1655     pa_flag = SOC_PA_SPEED(speed); 
   1656     sal_memset(&ability, 0, sizeof(soc_port_ability_t));
   1657     soc_mac_xl.md_ability_local_get(unit, port, &ability);
   1658     if (!(pa_flag & ability.speed_full_duplex)) {
   1659         return SOC_E_PARAM;
   1660     }
   1661 
   1662     /* Silently adjust the specified ifp bits to valid value */
   1663     /* valid value: 8 to 64 bytes (i.e. multiple of 8 bits) */
   1664     real_ifg = ifg < 64 ? 64 : (ifg > 512 ? 512 : (ifg + 7) & (0x7f << 3));
   1665 
   1666     SOC_IF_ERROR_RETURN(mac_xl_encap_get(unit, port, &encap));
   1667     if (encap == SOC_ENCAP_HIGIG) {
   1668         si->fd_hg = real_ifg;
   1669     } else if (encap == SOC_ENCAP_HIGIG2) {
   1670         si->fd_hg2 = real_ifg;
   1671     } else {
   1672         /* for encap == IEEE */
   1673         si->fd_xe = real_ifg;
   1674     }
   1675 
   1676     SOC_IF_ERROR_RETURN(mac_xl_duplex_get(unit, port, &cur_duplex));
   1677     SOC_IF_ERROR_RETURN(mac_xl_speed_get(unit, port, &cur_speed));
   1678 
   1679     /* XLMAC_MODE supports only 4 speeds with 4 being max as LINK_10G_PLUS */ 
   1680     if ((speed > 10000) && (cur_speed == 10000)) { 
   1681         cur_speed = speed; 
   1682     } 
   1683 
   1684     if (cur_speed == speed &&
   1685         cur_duplex == (duplex == SOC_PORT_DUPLEX_FULL ? TRUE : FALSE)) {
   1686         SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &rval));
   1687         orval = rval;
   1688         soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, AVERAGE_IPGf,
   1689                               real_ifg / 8);
   1690         if (COMPILER_64_NE(rval, orval)) {
   1691             SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, rval));
   1692         }
   1693     }
   1694 
   1695     return SOC_E_NONE;
   1696 }
   1697 
   1698 /*
   1699  * Function:
   1700  *      mac_xl_ifg_get
   1701  * Description:
   1702  *      Sets the new ifg (Inter-frame gap) value
   1703  * Parameters:
   1704  *      unit   - Device number
   1705  *      port   - Port number
   1706  *      speed  - the speed for which the IFG is being set
   1707  *      duplex - the duplex for which the IFG is being set
   1708  *      size - Maximum frame size in bytes
   1709  * Return Value:
   1710  *      SOC_E_XXX
   1711  * Notes:
   1712  *      The function makes sure the IFG value makes sense and updates the
   1713  *      IPG register in case the speed/duplex match the current settings
   1714  */
   1715 STATIC int
   1716 mac_xl_ifg_get(int unit, soc_port_t port, int speed,
   1717                 soc_port_duplex_t duplex, int *ifg)
   1718 {
   1719     soc_ipg_t  *si = &SOC_PERSIST(unit)->ipg[port];
   1720     soc_port_ability_t ability;
   1721     uint32      pa_flag;
   1722     int         encap = 0;
   1723 
   1724     if (!duplex) {
   1725         return SOC_E_PARAM;
   1726     }
   1727 
   1728     pa_flag = SOC_PA_SPEED(speed); 
   1729     sal_memset(&ability, 0, sizeof(soc_port_ability_t));
   1730     soc_mac_xl.md_ability_local_get(unit, port, &ability);
   1731     if (!(pa_flag & ability.speed_full_duplex)) {
   1732         return SOC_E_PARAM;
   1733     }
   1734 
   1735     SOC_IF_ERROR_RETURN(mac_xl_encap_get(unit, port, &encap));
   1736     if (encap == SOC_ENCAP_HIGIG) {
   1737         *ifg = si->fd_hg;
   1738     } else if (encap == SOC_ENCAP_HIGIG2) {
   1739         *ifg = si->fd_hg2;
   1740     } else {
   1741         /* for encap == IEEE */
   1742         *ifg = si->fd_xe;
   1743     }
   1744 
   1745     LOG_VERBOSE(BSL_LS_SOC_10G,
   1746                 (BSL_META_U(unit,
   1747                             "mac_xl_ifg_get: unit %d port %s speed=%dMb duplex=%s "
   1748                             "ifg=%d\n"),
   1749                  unit, SOC_PORT_NAME(unit, port),
   1750                  speed, duplex ? "True" : "False", *ifg));
   1751     return SOC_E_NONE;
   1752 }
   1753 
   1754 /*
   1755  * Function:
   1756  *      _mac_xl_port_mode_update
   1757  * Purpose:
   1758  *      Set the XLMAC port encapsulation mode.
   1759  * Parameters:
   1760  *      unit - XGS unit #.
   1761  *      port - XGS port # on unit.
   1762  *      hg_mode - SOC HG encap modes. value={HG/HG2/HG2-LITE}
   1763  * Returns:
   1764  *      SOC_E_XXX
   1765  */
   1766 STATIC int
   1767 _mac_xl_port_mode_update(int unit, soc_port_t port, int hg_mode)
   1768 {
   1769     uint32              rval;
   1770     uint64              val64;
   1771     soc_pbmp_t          ctr_pbmp;
   1772     int                 rv = SOC_E_NONE;
   1773     int                 to_hg_port = 0 ;
   1774     int                 phy_enable = 0;
   1775     int                 speed = 0;
   1776 
   1777     /* Pause linkscan */
   1778     soc_linkscan_pause(unit);
   1779 
   1780     /* Pause counter collection */
   1781     COUNTER_LOCK(unit);
   1782 
   1783     /* for original hg_mode parameter is at value={TRUE|FALSE} */
   1784     to_hg_port = (hg_mode != SOC_ENCAP_IEEE) ? TRUE : FALSE;
   1785     if (soc_feature(unit, soc_feature_hg2_light_in_portmacro)) {
   1786         soc_xport_type_mode_update(unit, port, hg_mode);
   1787     } else {
   1788         soc_xport_type_update(unit, port, to_hg_port);
   1789     }
   1790 
   1791     if (soc_feature(unit, soc_feature_port_encap_speed_max_config)) {
   1792         if (to_hg_port) {
   1793             SOC_IF_ERROR_RETURN(soc_port_hg_speed_get(unit, port, &speed));
   1794             SOC_IF_ERROR_RETURN(soc_phyctrl_set_speed_max(unit, port, speed));
   1795         } else {
   1796             speed = SOC_INFO(unit).port_init_speed[port];
   1797             SOC_IF_ERROR_RETURN(soc_phyctrl_set_speed_max(unit, port, speed));
   1798         }
   1799     }
   1800     rv = soc_phyctrl_enable_get(unit, port, &phy_enable);
   1801 
   1802     if (SOC_SUCCESS(rv)) {
   1803         rv = soc_phyctrl_init(unit, port);
   1804     }
   1805 
   1806     if (soc_feature(unit, soc_feature_port_enable_encap_restore)){
   1807         if (SOC_SUCCESS(rv)) {
   1808             rv = soc_phyctrl_enable_set(unit, port, phy_enable);
   1809         }
   1810     } else {
   1811         /* Re-enable phy after init.*/
   1812         if (SOC_SUCCESS(rv) && phy_enable) {
   1813             rv = soc_phyctrl_enable_set(unit, port, phy_enable);
   1814         }
   1815     }
   1816 
   1817     if (SOC_SUCCESS(rv)) {
   1818         rv = mac_xl_init(unit, port);
   1819     }
   1820 
   1821     if (SOC_SUCCESS(rv)) {
   1822         rv = mac_xl_enable_set(unit, port, 0);
   1823     }
   1824 
   1825     if (SOC_SUCCESS(rv)) {
   1826         SOC_PBMP_CLEAR(ctr_pbmp);
   1827         SOC_PBMP_PORT_SET(ctr_pbmp, port);
   1828         COMPILER_64_SET(val64, 0, 0);
   1829         rv = soc_counter_set_by_port(unit, ctr_pbmp, val64);
   1830     }
   1831 
   1832     COUNTER_UNLOCK(unit);
   1833     soc_linkscan_continue(unit);
   1834 
   1835     if (SOC_REG_IS_VALID(unit, XLPORT_CONFIGr)) {
   1836         uint32  xlp_hg_mode; 
   1837 
   1838         xlp_hg_mode = (to_hg_port) ? 1 : 0;
   1839 #ifdef BCM_GREYHOUND_SUPPORT
   1840         /* GH specific design is to apply HG setting PGW interface */
   1841         if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 
   1842                 SOC_IS_GREYHOUND2(unit)) {
   1843 
   1844             /* XLPORT and PGW register for HIGIG_MODEf is confirmed 
   1845              *  will be '1' for HG/HG+ setting only and '0' for other
   1846              *  encap mode{IEEE/HG2/HG2-LITE}
   1847              */
   1848             xlp_hg_mode = (hg_mode == SOC_ENCAP_HIGIG) ? 1 : 0; 
   1849 
   1850             /* only port in XLMAC allows PGW encap setting below */
   1851 #ifdef BCM_GREYHOUND2_SUPPORT
   1852             if (SOC_IS_GREYHOUND2(unit)) {
   1853                 SOC_IF_ERROR_RETURN
   1854                     (soc_greyhound2_pgw_encap_field_modify(unit, port,
   1855                         HIGIG_MODEf, xlp_hg_mode));
   1856             } else 
   1857 #endif  /* GREYHOUND2 */
   1858             {
   1859             SOC_IF_ERROR_RETURN
   1860                 (soc_greyhound_pgw_encap_field_modify(unit, port,
   1861                      HIGIG_MODEf, xlp_hg_mode));
   1862         }
   1863         }
   1864 #endif /* BCM_GREYHOUND_SUPPORT */
   1865         SOC_IF_ERROR_RETURN(READ_XLPORT_CONFIGr(unit, port, &rval));
   1866         soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, HIGIG_MODEf,
   1867                           xlp_hg_mode);
   1868         if (soc_feature(unit, soc_feature_no_higig_plus)) {
   1869             soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, HIGIG2_MODEf,
   1870                               xlp_hg_mode); 
   1871         }
   1872         SOC_IF_ERROR_RETURN(WRITE_XLPORT_CONFIGr(unit, port, rval));
   1873     }
   1874     if (SOC_REG_IS_VALID(unit, PORT_CONFIGr)) {
   1875         SOC_IF_ERROR_RETURN(READ_PORT_CONFIGr(unit, port, &rval));
   1876         soc_reg_field_set(unit, PORT_CONFIGr, &rval, HIGIG_MODEf,
   1877                           to_hg_port);
   1878         SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval));
   1879     }
   1880     return rv;
   1881 }
   1882 
   1883 /*
   1884  * Function:
   1885  *      mac_xl_encap_set
   1886  * Purpose:
   1887  *      Set the XLMAC port encapsulation mode.
   1888  * Parameters:
   1889  *      unit - XGS unit #.
   1890  *      port - XGS port # on unit.
   1891  *      mode - (IN) encap bits (defined above)
   1892  * Returns:
   1893  *      SOC_E_XXX
   1894  */
   1895 STATIC int
   1896 mac_xl_encap_set(int unit, soc_port_t port, int mode)
   1897 {
   1898     int enable, encap, rv;
   1899     int runt;
   1900 
   1901 #ifdef BROADCOM_DEBUG
   1902     LOG_VERBOSE(BSL_LS_SOC_10G,
   1903                 (BSL_META_U(unit,
   1904                             "mac_xl_encap_set: unit %d port %s encapsulation=%s\n"),
   1905                  unit, SOC_PORT_NAME(unit, port),
   1906                  mac_xl_encap_mode[mode]));
   1907 #endif
   1908 
   1909     switch (mode) {
   1910     case SOC_ENCAP_IEEE:
   1911     case SOC_ENCAP_HIGIG2_LITE:
   1912         encap = 0;
   1913         break;
   1914     case SOC_ENCAP_HIGIG:
   1915         encap = 1;
   1916         break;
   1917     case SOC_ENCAP_HIGIG2:
   1918         encap = 2;
   1919         break;
   1920     default:
   1921         return SOC_E_PARAM;
   1922     }
   1923 
   1924     if (!soc_feature(unit, soc_feature_xport_convertible)) {
   1925         if ((IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) ||
   1926             (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE)) {
   1927             return SOC_E_PARAM;
   1928         }
   1929     }
   1930 
   1931     SOC_IF_ERROR_RETURN(mac_xl_enable_get(unit, port, &enable));
   1932 
   1933     if (enable) {
   1934         /* Turn off TX/RX enable */
   1935         SOC_IF_ERROR_RETURN(mac_xl_enable_set(unit, port, 0));
   1936     }
   1937 
   1938     if (soc_feature(unit, soc_feature_hg2_light_in_portmacro)) {
   1939         /* mode update for all encap mode change! */
   1940         SOC_IF_ERROR_RETURN(_mac_xl_port_mode_update(unit, port, mode));
   1941     } else if ((IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) || 
   1942             (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE)) {
   1943         /* IEEE -> HG or HG -> IEEE */
   1944         SOC_IF_ERROR_RETURN(_mac_xl_port_mode_update(unit, port, mode));
   1945     }
   1946 
   1947     /* apply encap setting */
   1948     rv = soc_reg_field32_modify(unit, XLMAC_MODEr, port, HDR_MODEf, encap);
   1949 
   1950     /* assigning runt value per encap setting */
   1951     if ((mode == SOC_ENCAP_HIGIG2) || (mode == SOC_ENCAP_HIGIG2_LITE)) {
   1952         runt = XLMAC_RUNT_THRESHOLD_HG2;
   1953     } else if (mode == SOC_ENCAP_HIGIG) {
   1954         runt = XLMAC_RUNT_THRESHOLD_HG1;
   1955     } else {
   1956         runt = XLMAC_RUNT_THRESHOLD_IEEE;
   1957     }
   1958         SOC_IF_ERROR_RETURN
   1959             (soc_reg_field32_modify(unit, XLMAC_RX_CTRLr, port, RUNT_THRESHOLDf,
   1960                                     runt));
   1961 
   1962     SOC_IF_ERROR_RETURN
   1963         (soc_reg_field32_modify(unit, XLMAC_RX_CTRLr, port, STRICT_PREAMBLEf,
   1964                                 mode == SOC_ENCAP_IEEE ? 1 : 0));
   1965 
   1966     if (enable) {
   1967         /* Re-enable transmitter and receiver */
   1968         SOC_IF_ERROR_RETURN(mac_xl_enable_set(unit, port, 1));
   1969     }
   1970 
   1971     return rv;
   1972 }
   1973 
   1974 /*
   1975  * Function:
   1976  *      mac_xl_encap_get
   1977  * Purpose:
   1978  *      Get the XLMAC port encapsulation mode.
   1979  * Parameters:
   1980  *      unit - XGS unit #.
   1981  *      port - XGS port # on unit.
   1982  *      mode - (INT) encap bits (defined above)
   1983  * Returns:
   1984  *      SOC_E_XXX
   1985  */
   1986 STATIC int
   1987 mac_xl_encap_get(int unit, soc_port_t port, int *mode)
   1988 {
   1989     uint64 rval;
   1990 
   1991     if (!mode) {
   1992         return SOC_E_PARAM;
   1993     }
   1994 
   1995     SOC_IF_ERROR_RETURN(READ_XLMAC_MODEr(unit, port, &rval));
   1996     switch (soc_reg64_field32_get(unit, XLMAC_MODEr, rval, HDR_MODEf)) {
   1997     case 0:
   1998         *mode = SOC_ENCAP_IEEE;
   1999         break;
   2000     case 1:
   2001         *mode = SOC_ENCAP_HIGIG;
   2002         break;
   2003     case 2:
   2004         *mode = SOC_ENCAP_HIGIG2;
   2005         break;
   2006     default:
   2007         *mode = SOC_ENCAP_COUNT;
   2008     }
   2009 
   2010 #ifdef BROADCOM_DEBUG
   2011     LOG_VERBOSE(BSL_LS_SOC_10G,
   2012                 (BSL_META_U(unit,
   2013                             "mac_xl_encap_get: unit %d port %s encapsulation=%s\n"),
   2014                  unit, SOC_PORT_NAME(unit, port),
   2015                  mac_xl_encap_mode[*mode]));
   2016 #endif
   2017     return SOC_E_NONE;
   2018 }
   2019 
   2020 /*
   2021  * Function:
   2022  *      mac_xl_expected_rx_latency_get
   2023  * Purpose:
   2024  *      Get the XLMAC port expected Rx latency
   2025  * Parameters:
   2026  *      unit - XGS unit #.
   2027  *      port - XGS port # on unit.
   2028  *      latency - (OUT) Latency in NS
   2029  * Returns:
   2030  *      SOC_E_XXX
   2031  */
   2032 STATIC int
   2033 mac_xl_expected_rx_latency_get(int unit, soc_port_t port, int *latency)
   2034 {
   2035     int speed = 0;
   2036     SOC_IF_ERROR_RETURN(mac_xl_speed_get(unit, port, &speed));
   2037 
   2038     switch (speed) {
   2039     case 1000:  /* GigE */
   2040         *latency = 510; /* From SDK-69340 */
   2041         break;
   2042 
   2043     case 10000:  /* 10G */
   2044         *latency = 230; /* From SDK-69340 */
   2045         break;
   2046 
   2047     default:
   2048         *latency = 0;
   2049         break;
   2050     }
   2051 
   2052     return SOC_E_NONE;
   2053 }
   2054 
   2055 /*
   2056  * Function:
   2057  *      mac_xl_control_set
   2058  * Purpose:
   2059  *      To configure MAC control properties.
   2060  * Parameters:
   2061  *      unit - XGS unit #.
   2062  *      port - XGS port # on unit.
   2063  *      type - MAC control property to set.
   2064  *      int  - New setting for MAC control.
   2065  * Returns:
   2066  *      SOC_E_XXX
   2067  */
   2068 STATIC int
   2069 mac_xl_control_set(int unit, soc_port_t port, soc_mac_control_t type,
   2070                   int value)
   2071 {
   2072     uint64 rval, copy;
   2073     uint32 fval;
   2074 
   2075     LOG_VERBOSE(BSL_LS_SOC_10G,
   2076                 (BSL_META_U(unit,
   2077                             "mac_xl_control_set: unit %d port %s type=%d value=%d\n"),
   2078                  unit, SOC_PORT_NAME(unit, port),
   2079                  type, value));
   2080 
   2081     switch (type) {
   2082     case SOC_MAC_CONTROL_RX_SET:
   2083         SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &rval));
   2084         copy = rval;
   2085         soc_reg64_field32_set(unit, XLMAC_CTRLr, &rval, RX_ENf, value ? 1 : 0);
   2086         if (COMPILER_64_NE(rval, copy)) {
   2087             SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, rval));
   2088         }    
   2089         break;
   2090     case SOC_MAC_CONTROL_TX_SET:
   2091         SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &rval));
   2092         copy = rval;
   2093         soc_reg64_field32_set(unit, XLMAC_CTRLr, &rval, TX_ENf, value ? 1 : 0);
   2094         if (COMPILER_64_NE(rval, copy)) {
   2095             SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, rval));
   2096         }    
   2097         break;
   2098     case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH:
   2099         if (value < 0 || value > XLMAC_THROT_10G_TO_2P5G) {
   2100             return SOC_E_PARAM;
   2101         } else {
   2102             SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &rval));
   2103             if ( value == XLMAC_THROT_10G_TO_5G ) {
   2104                 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_DENOMf, 21);
   2105                 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_NUMf, 21);
   2106             } else if (value == XLMAC_THROT_10G_TO_2P5G) {
   2107                 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_DENOMf, 21);
   2108                 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_NUMf, 63);
   2109             } else if (value >= 8) {
   2110                 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval,
   2111                                       THROT_DENOMf, value);
   2112                 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_NUMf,
   2113                                       1);
   2114             } else {
   2115                 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval,
   2116                                       THROT_DENOMf, 0);
   2117                 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_NUMf,
   2118                                       0);
   2119             }
   2120             SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, rval));
   2121         }
   2122         return SOC_E_NONE;
   2123 
   2124     case SOC_MAC_PASS_CONTROL_FRAME:
   2125         if (SOC_REG_IS_VALID(unit, XLMAC_PAUSE_CTRLr)) {
   2126             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_PAUSE_CTRLr, port,
   2127                                                    RX_PAUSE_ENf, value ? 0 : 1));
   2128 
   2129             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_PAUSE_CTRLr, port,
   2130                                                    TX_PAUSE_ENf, value ? 0 : 1));
   2131         }
   2132         break;
   2133 
   2134     case SOC_MAC_CONTROL_PFC_TYPE:
   2135         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_PFC_TYPEr, port,
   2136                                                    PFC_ETH_TYPEf, value));
   2137         break;
   2138 
   2139     case SOC_MAC_CONTROL_PFC_OPCODE:
   2140         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_PFC_OPCODEr,
   2141                                                    port, PFC_OPCODEf, value));
   2142         break;
   2143 
   2144     case SOC_MAC_CONTROL_PFC_CLASSES:
   2145         if (value != 8) {
   2146             return SOC_E_PARAM;
   2147         }
   2148         break;
   2149 
   2150     case SOC_MAC_CONTROL_PFC_MAC_DA_OUI:
   2151         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_DAr(unit, port, &rval));
   2152         fval = soc_reg64_field32_get(unit, XLMAC_PFC_DAr, rval, PFC_MACDA_LOf);
   2153         fval &= 0x00ffffff;
   2154         fval |= (value & 0xff) << 24;
   2155         soc_reg64_field32_set(unit, XLMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval);
   2156 
   2157         soc_reg64_field32_set(unit, XLMAC_PFC_DAr, &rval, PFC_MACDA_HIf,
   2158                               value >> 8);
   2159         SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_DAr(unit, port, rval));
   2160         break;
   2161 
   2162     case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI:
   2163         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_DAr(unit, port, &rval));
   2164         fval = soc_reg64_field32_get(unit, XLMAC_PFC_DAr, rval, PFC_MACDA_LOf);
   2165         fval &= 0xff000000;
   2166         fval |= value;
   2167         soc_reg64_field32_set(unit, XLMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval);
   2168         SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_DAr(unit, port, rval));
   2169         break;
   2170 
   2171     case SOC_MAC_CONTROL_PFC_RX_PASS:
   2172         /* this is always true */
   2173         break;
   2174 
   2175     case SOC_MAC_CONTROL_PFC_RX_ENABLE:
   2176         SOC_IF_ERROR_RETURN
   2177             (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, RX_PFC_ENf,
   2178                                     value ? 1 : 0));
   2179         break;
   2180 
   2181     case SOC_MAC_CONTROL_PFC_TX_ENABLE:
   2182         SOC_IF_ERROR_RETURN
   2183             (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, TX_PFC_ENf,
   2184                                     value ? 1 : 0));
   2185         break;
   2186 
   2187     case SOC_MAC_CONTROL_PFC_FORCE_XON:
   2188         SOC_IF_ERROR_RETURN
   2189             (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, FORCE_PFC_XONf,
   2190                                     value ? 1 : 0));
   2191         break;
   2192 
   2193     case SOC_MAC_CONTROL_PFC_STATS_ENABLE:
   2194         SOC_IF_ERROR_RETURN
   2195             (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, PFC_STATS_ENf,
   2196                                     value ? 1 : 0));
   2197         break;
   2198 
   2199     case SOC_MAC_CONTROL_PFC_REFRESH_TIME:
   2200         SOC_IF_ERROR_RETURN
   2201             (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, 
   2202                                     PFC_REFRESH_TIMERf, value));
   2203         break;
   2204 
   2205     case SOC_MAC_CONTROL_PFC_XOFF_TIME:
   2206         SOC_IF_ERROR_RETURN
   2207             (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, 
   2208                                     PFC_XOFF_TIMERf, value));
   2209         break;
   2210 
   2211     case SOC_MAC_CONTROL_LLFC_RX_ENABLE:
   2212         SOC_IF_ERROR_RETURN
   2213             (soc_reg_field32_modify(unit, XLMAC_LLFC_CTRLr, port, RX_LLFC_ENf,
   2214                                     value ? 1 : 0));
   2215         SOC_IF_ERROR_RETURN 
   2216             (soc_llfc_xon_set(unit, port, value ? 1 : 0));
   2217         break;
   2218 
   2219     case SOC_MAC_CONTROL_LLFC_TX_ENABLE:
   2220         SOC_IF_ERROR_RETURN
   2221             (soc_reg_field32_modify(unit, XLMAC_LLFC_CTRLr, port, TX_LLFC_ENf,
   2222                                     value ? 1 : 0));
   2223         break;
   2224 
   2225     case SOC_MAC_CONTROL_EEE_ENABLE:
   2226         if (!soc_feature(unit, soc_feature_eee)) {
   2227             return SOC_E_UNAVAIL;
   2228         }
   2229         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_EEE_CTRLr, 
   2230                                                    port, EEE_ENf, value));
   2231         break;
   2232 
   2233     case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME:
   2234         if (!soc_feature(unit, soc_feature_eee)) {
   2235             return SOC_E_UNAVAIL;
   2236         }
   2237         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_EEE_TIMERSr, 
   2238                                     port, EEE_DELAY_ENTRY_TIMERf, value));
   2239         break;
   2240 
   2241     case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME:
   2242         if (!soc_feature(unit, soc_feature_eee)) {
   2243             return SOC_E_UNAVAIL;
   2244         }
   2245         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_EEE_TIMERSr, 
   2246                                     port, EEE_WAKE_TIMERf, value));
   2247         break;
   2248 
   2249     case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE:
   2250         SOC_IF_ERROR_RETURN
   2251             (soc_reg_field32_modify(unit, XLMAC_RX_LSS_CTRLr, port,
   2252                                     LOCAL_FAULT_DISABLEf, value ? 0 : 1));
   2253         break;
   2254 
   2255     case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE:
   2256         SOC_IF_ERROR_RETURN
   2257             (soc_reg_field32_modify(unit, XLMAC_RX_LSS_CTRLr, port,
   2258                                     REMOTE_FAULT_DISABLEf, value ? 0 : 1));
   2259         break;
   2260     case SOC_MAC_CONTROL_FAILOVER_RX_SET:
   2261         break;
   2262     case SOC_MAC_CONTROL_EGRESS_DRAIN:
   2263         SOC_IF_ERROR_RETURN(mac_xl_egress_queue_drain(unit, port));
   2264         break;
   2265     case SOC_MAC_CONTROL_RX_VLAN_TAG_OUTER_TPID:
   2266         SOC_IF_ERROR_RETURN
   2267             (soc_reg_field32_modify(unit, XLMAC_RX_VLAN_TAGr, port, 
   2268                                     OUTER_VLAN_TAGf, value));
   2269         SOC_IF_ERROR_RETURN
   2270             (soc_reg_field32_modify(unit, XLMAC_RX_VLAN_TAGr, port, 
   2271                                     OUTER_VLAN_TAG_ENABLEf, value ? 1 : 0));
   2272         break;
   2273     case SOC_MAC_CONTROL_RX_VLAN_TAG_INNER_TPID:
   2274         SOC_IF_ERROR_RETURN
   2275             (soc_reg_field32_modify(unit, XLMAC_RX_VLAN_TAGr, port, 
   2276                                     INNER_VLAN_TAGf, value));
   2277         SOC_IF_ERROR_RETURN
   2278             (soc_reg_field32_modify(unit, XLMAC_RX_VLAN_TAGr, port, 
   2279                                     INNER_VLAN_TAG_ENABLEf, value ? 1 : 0));
   2280         break;
   2281     default:
   2282         return SOC_E_UNAVAIL;
   2283     }
   2284 
   2285     return SOC_E_NONE;
   2286 }
   2287 
   2288 /*
   2289  * Function:
   2290  *      mac_xl_control_get
   2291  * Purpose:
   2292  *      To get current MAC control setting.
   2293  * Parameters:
   2294  *      unit - XGS unit #.
   2295  *      port - XGS port # on unit.
   2296  *      type - MAC control property to set.
   2297  *      int  - New setting for MAC control.
   2298  * Returns:
   2299  *      SOC_E_XXX
   2300  */
   2301 STATIC int
   2302 mac_xl_control_get(int unit, soc_port_t port, soc_mac_control_t type,
   2303                   int *value)
   2304 {
   2305     int rv;
   2306     uint64 rval;
   2307     uint32 fval0, fval1;
   2308 
   2309     if (value == NULL) {
   2310         return SOC_E_PARAM;
   2311     }
   2312 
   2313     rv = SOC_E_NONE;
   2314     switch (type) {
   2315     case SOC_MAC_CONTROL_RX_SET:
   2316         SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &rval));
   2317         *value = soc_reg64_field32_get(unit, XLMAC_CTRLr, rval, RX_ENf);
   2318         break;
   2319     case SOC_MAC_CONTROL_TX_SET:
   2320         SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &rval));
   2321         *value = soc_reg64_field32_get(unit, XLMAC_CTRLr, rval, TX_ENf);
   2322         break;
   2323     case SOC_MAC_CONTROL_SW_RESET:
   2324         SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &rval));
   2325         *value = soc_reg64_field32_get(unit, XLMAC_CTRLr, rval, SOFT_RESETf);
   2326         break;
   2327     case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH:
   2328         SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &rval));
   2329         *value = soc_reg64_field32_get(unit, XLMAC_TX_CTRLr, rval,
   2330                                        THROT_DENOMf);
   2331         break;
   2332 
   2333     case SOC_MAC_CONTROL_TIMESTAMP_TRANSMIT:
   2334          { 
   2335             uint32  timestamp = 0;
   2336             if (soc_feature(unit, soc_feature_timestamp_counter) &&
   2337                 soc_property_get(unit, spn_SW_TIMESTAMP_FIFO_ENABLE, 1)) {
   2338                 if (soc_counter_timestamp_get(unit, port,
   2339                                               &timestamp) != SOC_E_NOT_FOUND) {
   2340                     *value = (int)timestamp;
   2341                     break;
   2342                 }
   2343             }
   2344         SOC_IF_ERROR_RETURN
   2345             (READ_XLMAC_TX_TIMESTAMP_FIFO_STATUSr(unit, port, &rval));
   2346         if (soc_reg64_field32_get(unit, XLMAC_TX_TIMESTAMP_FIFO_STATUSr, rval,
   2347                                   ENTRY_COUNTf) == 0) {
   2348             return SOC_E_EMPTY;
   2349         }
   2350         SOC_IF_ERROR_RETURN
   2351             (READ_XLMAC_TX_TIMESTAMP_FIFO_DATAr(unit, port, &rval));
   2352         *value = soc_reg64_field32_get(unit, XLMAC_TX_TIMESTAMP_FIFO_DATAr,
   2353                                        rval, TIME_STAMPf);
   2354         }
   2355         break;
   2356 
   2357     case SOC_MAC_PASS_CONTROL_FRAME:
   2358         *value = TRUE;
   2359         break;
   2360 
   2361     case SOC_MAC_CONTROL_PFC_TYPE:
   2362         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_TYPEr(unit, port, &rval));
   2363         *value = soc_reg64_field32_get(unit, XLMAC_PFC_TYPEr, rval,
   2364                                        PFC_ETH_TYPEf);
   2365         break;
   2366 
   2367     case SOC_MAC_CONTROL_PFC_OPCODE:
   2368         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_OPCODEr(unit, port, &rval));
   2369         *value = soc_reg64_field32_get(unit, XLMAC_PFC_OPCODEr, rval,
   2370                                        PFC_OPCODEf);
   2371         break;
   2372 
   2373     case SOC_MAC_CONTROL_PFC_CLASSES:
   2374         *value = 8;
   2375         break;
   2376 
   2377     case SOC_MAC_CONTROL_PFC_MAC_DA_OUI:
   2378         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_DAr(unit, port, &rval));
   2379         fval0 = soc_reg64_field32_get(unit, XLMAC_PFC_DAr, rval,
   2380                                       PFC_MACDA_LOf);
   2381         fval1 = soc_reg64_field32_get(unit, XLMAC_PFC_DAr, rval,
   2382                                       PFC_MACDA_HIf);
   2383         *value = (fval0 >> 24) | (fval1 << 8);
   2384         break;
   2385 
   2386     case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI:
   2387         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_DAr(unit, port, &rval));
   2388         *value = soc_reg64_field32_get(unit, XLMAC_PFC_DAr, rval,
   2389                                        PFC_MACDA_LOf) & 0x00ffffff;
   2390         break;
   2391 
   2392     case SOC_MAC_CONTROL_PFC_RX_PASS:
   2393         *value = TRUE;
   2394         break;
   2395 
   2396     case SOC_MAC_CONTROL_PFC_RX_ENABLE:
   2397         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval));
   2398         *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval,
   2399                                        RX_PFC_ENf);
   2400         break;
   2401 
   2402     case SOC_MAC_CONTROL_PFC_TX_ENABLE:
   2403         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval));
   2404         *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval,
   2405                                        TX_PFC_ENf);
   2406         break;
   2407 
   2408     case SOC_MAC_CONTROL_PFC_FORCE_XON:
   2409         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval));
   2410         *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval,
   2411                                        FORCE_PFC_XONf);
   2412         break;
   2413 
   2414     case SOC_MAC_CONTROL_PFC_STATS_ENABLE:
   2415         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval));
   2416         *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval,
   2417                                        PFC_STATS_ENf);
   2418         break;
   2419 
   2420     case SOC_MAC_CONTROL_PFC_REFRESH_TIME:
   2421         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval));
   2422         *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval,
   2423                                        PFC_REFRESH_TIMERf);
   2424         break;
   2425 
   2426     case SOC_MAC_CONTROL_PFC_XOFF_TIME:
   2427         SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval));
   2428         *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval,
   2429                                        PFC_XOFF_TIMERf);
   2430         break;
   2431 
   2432     case SOC_MAC_CONTROL_LLFC_RX_ENABLE:
   2433         SOC_IF_ERROR_RETURN(READ_XLMAC_LLFC_CTRLr(unit, port, &rval));
   2434         *value = soc_reg64_field32_get(unit, XLMAC_LLFC_CTRLr, rval,
   2435                                        RX_LLFC_ENf);
   2436         break;
   2437 
   2438     case SOC_MAC_CONTROL_LLFC_TX_ENABLE:
   2439         SOC_IF_ERROR_RETURN(READ_XLMAC_LLFC_CTRLr(unit, port, &rval));
   2440         *value = soc_reg64_field32_get(unit, XLMAC_LLFC_CTRLr, rval,
   2441                                        TX_LLFC_ENf);
   2442         break;
   2443 
   2444     case SOC_MAC_CONTROL_EEE_ENABLE:
   2445         if (!soc_feature(unit, soc_feature_eee)) {
   2446             return SOC_E_UNAVAIL;
   2447         }
   2448         SOC_IF_ERROR_RETURN(READ_XLMAC_EEE_CTRLr(unit, port, &rval));
   2449         *value = soc_reg64_field32_get(unit, XLMAC_EEE_CTRLr, rval, EEE_ENf);
   2450         break;
   2451 
   2452     case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME:
   2453         if (!soc_feature(unit, soc_feature_eee)) {
   2454             return SOC_E_UNAVAIL;
   2455         }
   2456         SOC_IF_ERROR_RETURN(READ_XLMAC_EEE_TIMERSr(unit, port, &rval));
   2457         *value = soc_reg64_field32_get(unit, XLMAC_EEE_TIMERSr, rval,
   2458                 EEE_DELAY_ENTRY_TIMERf);
   2459         break;
   2460 
   2461     case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME:
   2462         if (!soc_feature(unit, soc_feature_eee)) {
   2463             return SOC_E_UNAVAIL;
   2464         }
   2465         SOC_IF_ERROR_RETURN(READ_XLMAC_EEE_TIMERSr(unit, port, &rval));
   2466         *value = soc_reg64_field32_get(unit, XLMAC_EEE_TIMERSr, rval,
   2467                 EEE_WAKE_TIMERf);
   2468         break;
   2469 
   2470     case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE:
   2471         SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &rval));
   2472         *value = soc_reg64_field32_get(unit, XLMAC_RX_LSS_CTRLr, rval,
   2473                                        LOCAL_FAULT_DISABLEf) ? 0 : 1;
   2474         break;
   2475 
   2476     case SOC_MAC_CONTROL_FAULT_LOCAL_STATUS:
   2477         SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &rval));
   2478         if (soc_reg64_field32_get(unit, XLMAC_RX_LSS_CTRLr, rval,
   2479                                   LOCAL_FAULT_DISABLEf) == 1) {
   2480             *value = 0;
   2481         } else {
   2482             SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_STATUSr(unit, port, &rval));
   2483             *value = soc_reg64_field32_get(unit, XLMAC_RX_LSS_STATUSr, rval,
   2484                                            LOCAL_FAULT_STATUSf);
   2485         }
   2486         break;
   2487 
   2488     case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE:
   2489         SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &rval));
   2490         *value = soc_reg64_field32_get(unit, XLMAC_RX_LSS_CTRLr, rval,
   2491                                        REMOTE_FAULT_DISABLEf) ? 0 : 1;
   2492         break;
   2493 
   2494     case SOC_MAC_CONTROL_FAULT_REMOTE_STATUS:
   2495         SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &rval));
   2496         if (soc_reg64_field32_get(unit, XLMAC_RX_LSS_CTRLr, rval,
   2497                                   REMOTE_FAULT_DISABLEf) == 1) {
   2498             *value = 0;
   2499         } else {
   2500             SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_STATUSr(unit, port, &rval));
   2501             *value = soc_reg64_field32_get(unit, XLMAC_RX_LSS_STATUSr, rval,
   2502                                            REMOTE_FAULT_STATUSf);
   2503         }
   2504         break;
   2505     case SOC_MAC_CONTROL_RX_VLAN_TAG_OUTER_TPID:
   2506         SOC_IF_ERROR_RETURN(READ_XLMAC_RX_VLAN_TAGr(unit, port, &rval));
   2507         *value = soc_reg64_field32_get(unit, XLMAC_RX_VLAN_TAGr, 
   2508                                        rval, OUTER_VLAN_TAGf);
   2509         break;
   2510     case SOC_MAC_CONTROL_RX_VLAN_TAG_INNER_TPID:
   2511         SOC_IF_ERROR_RETURN(READ_XLMAC_RX_VLAN_TAGr(unit, port, &rval));
   2512         *value = soc_reg64_field32_get(unit, XLMAC_RX_VLAN_TAGr, 
   2513                                        rval, INNER_VLAN_TAGf);
   2514         break;
   2515     case SOC_MAC_CONTROL_EXPECTED_RX_LATENCY:
   2516         SOC_IF_ERROR_RETURN(mac_xl_expected_rx_latency_get(unit, port, value));
   2517         break;
   2518 
   2519     default:
   2520         return SOC_E_UNAVAIL;
   2521     }
   2522 
   2523     LOG_VERBOSE(BSL_LS_SOC_10G,
   2524                 (BSL_META_U(unit,
   2525                             "mac_xl_control_get: unit %d port %s type=%d value=%d "
   2526                             "rv=%d\n"),
   2527                  unit, SOC_PORT_NAME(unit, port),
   2528                  type, *value, rv));
   2529     return rv;
   2530 }
   2531 
   2532 /*
   2533  * Function:
   2534  *      mac_xl_ability_local_get
   2535  * Purpose:
   2536  *      Return the abilities of XLMAC
   2537  * Parameters:
   2538  *      unit - XGS unit #.
   2539  *      port - XGS port # on unit.
   2540  *      mode - (OUT) Supported operating modes as a mask of abilities.
   2541  * Returns:
   2542  *      SOC_E_XXX
   2543  */
   2544 STATIC int
   2545 mac_xl_ability_local_get(int unit, soc_port_t port,
   2546                           soc_port_ability_t *ability)
   2547 {
   2548     soc_info_t *si = &SOC_INFO(unit);
   2549     int blk, bindex, port_speed_max, i;
   2550     int phy_port, active_port;
   2551     uint32 active_mask;
   2552 #ifdef BCM_METROLITE_SUPPORT
   2553     uint32 rval = 0;
   2554     uint32 port_mode = 0xF;
   2555 #endif
   2556 
   2557     if (NULL == ability) {
   2558         return SOC_E_PARAM;
   2559     }
   2560 
   2561     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   2562     ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   2563     ability->interface = SOC_PA_INTF_MII | SOC_PA_INTF_XGMII;
   2564     ability->medium    = SOC_PA_ABILITY_NONE;
   2565     ability->loopback  = SOC_PA_LB_MAC;
   2566     ability->flags     = SOC_PA_ABILITY_NONE;
   2567     ability->encap = SOC_PA_ENCAP_IEEE | SOC_PA_ENCAP_HIGIG |
   2568         SOC_PA_ENCAP_HIGIG2;
   2569 
   2570 #ifdef BCM_SABER2_SUPPORT
   2571     if (SOC_IS_SABER2(unit) && IS_XL_PORT(unit,port)) {
   2572         ability->encap |= SOC_PA_ENCAP_HIGIG2_LITE; 
   2573         ability->speed_full_duplex = SOC_PA_ABILITY_NONE;
   2574     } 
   2575 #endif
   2576 
   2577     /* Adjust port_speed_max according to the port config */
   2578     port_speed_max = SOC_INFO(unit).port_speed_max[port];
   2579     if (soc_feature(unit, soc_feature_logical_port_num) && 
   2580         !soc_feature(unit, soc_feature_tsce)) {
   2581         phy_port = si->port_l2p_mapping[port];
   2582         bindex = -1;
   2583         for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) {
   2584             blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i);
   2585             if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT) {
   2586                 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i);
   2587                 break;
   2588             }
   2589         }
   2590         if (port_speed_max > 10000) {
   2591             active_mask = 0;
   2592             for (i = bindex + 1; i <= 3; i++) {
   2593                 active_port = si->port_p2l_mapping[phy_port - bindex + i];
   2594                 if (active_port != -1 &&
   2595                     !SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit, all),
   2596                                      active_port)) {
   2597                     active_mask |= 1 << i;
   2598                 }
   2599             }
   2600             if (bindex == 0) { /* Lanes 0 */
   2601                 if (active_mask & 0x2) { /* lane 1 is in use */
   2602                     port_speed_max = 10000;
   2603                 } else if (port_speed_max > 20000 && active_mask & 0xc) {
   2604                     /* Lane 1 isn't in use, lane 2 or 3 (or both) is (are) in use */
   2605                     port_speed_max = 20000;
   2606                 }
   2607             } else { /* (Must be) lanes 2 */
   2608                 if (active_mask & 0x8) { /* lane 3 is in use */
   2609                     port_speed_max = 10000;
   2610                 }
   2611             }
   2612         }
   2613     }
   2614     if (IS_HL_PORT(unit , port)) {
   2615         if (SOC_INFO(unit).port_speed_max[port]) {
   2616             ability->speed_full_duplex |= SOC_PA_SPEED_2500MB;
   2617             if (SOC_IS_HURRICANE2(unit)) {
   2618                 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   2619             }
   2620 #ifdef BCM_METROLITE_SUPPORT
   2621             /* HL is supported in 4x1G */
   2622             if (SOC_IS_METROLITE(unit))  {
   2623                 if (SOC_REG_PORT_VALID(unit, XLPORT_MODE_REGr, port)) {
   2624                     SOC_IF_ERROR_RETURN(READ_XLPORT_MODE_REGr(unit, port, &rval));
   2625                     port_mode = soc_reg_field_get(unit, XLPORT_MODE_REGr, rval,
   2626                                               XPORT0_CORE_PORT_MODEf);
   2627                     /* Quad Port Mode. Lanes 0..3 individually active */
   2628                     if (port_mode == 0x0){
   2629                         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   2630                     }
   2631                 }
   2632             }
   2633 #endif
   2634         }
   2635     } else if (IS_HG_PORT(unit , port)) {
   2636         switch (port_speed_max) {
   2637         case 42000:
   2638             ability->speed_full_duplex |= SOC_PA_SPEED_42GB;
   2639             /* fall through */
   2640         case 40000:
   2641             ability->speed_full_duplex |= SOC_PA_SPEED_40GB;
   2642             if(soc_feature(unit, soc_feature_higig_misc_speed_support)) {
   2643                 ability->speed_full_duplex |= SOC_PA_SPEED_42GB;
   2644             }
   2645             /* fall through */
   2646         case 32000:
   2647             ability->speed_full_duplex |= SOC_PA_SPEED_32GB;
   2648             /* fall through */
   2649         case 30000:
   2650             ability->speed_full_duplex |= SOC_PA_SPEED_30GB;
   2651             /* fall through */
   2652         case 25000:
   2653             ability->speed_full_duplex |= SOC_PA_SPEED_25GB;
   2654             /* fall through */
   2655         case 21000:
   2656             ability->speed_full_duplex |= SOC_PA_SPEED_21GB;
   2657             /* fall through */
   2658         case 20000:
   2659             ability->speed_full_duplex |= SOC_PA_SPEED_20GB;
   2660             if(soc_feature(unit, soc_feature_higig_misc_speed_support)) {
   2661                 ability->speed_full_duplex |= SOC_PA_SPEED_21GB;
   2662             }
   2663             /* fall through */
   2664         case 16000:
   2665             ability->speed_full_duplex |= SOC_PA_SPEED_16GB;
   2666             /* fall through */
   2667         case 15000:
   2668             ability->speed_full_duplex |= SOC_PA_SPEED_15GB;
   2669             /* fall through */
   2670         case 13000:
   2671             ability->speed_full_duplex |= SOC_PA_SPEED_13GB;
   2672             /* fall through */
   2673         case 12000:
   2674             ability->speed_full_duplex |= SOC_PA_SPEED_12GB;
   2675             /* fall through */
   2676         case 11000:
   2677             ability->speed_full_duplex |= SOC_PA_SPEED_11GB;
   2678             /* fall through */
   2679         case 10000:
   2680             ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   2681             if(soc_feature(unit, soc_feature_higig_misc_speed_support)) {
   2682                 ability->speed_full_duplex |= SOC_PA_SPEED_11GB;
   2683                 ability->speed_full_duplex |= SOC_PA_SPEED_5000MB;
   2684                 /* For 11G and 5G speeds, MAC should be in 10G */
   2685             }
   2686             break;
   2687         case 5000:
   2688             if(soc_feature(unit, soc_feature_higig_misc_speed_support)) {
   2689                 ability->speed_full_duplex |= SOC_PA_SPEED_5000MB;
   2690                 /* For 5G speed, MAC will actually be set to 10G */
   2691             }
   2692             break;
   2693         default:
   2694             break;
   2695         }
   2696     } else {
   2697         if (port_speed_max >= 40000) {
   2698             ability->speed_full_duplex |= SOC_PA_SPEED_40GB;
   2699         }
   2700         if (port_speed_max >= 20000) {
   2701             ability->speed_full_duplex |= SOC_PA_SPEED_20GB;
   2702         }
   2703         if (port_speed_max >= 10000) {
   2704             ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   2705         }
   2706         if (port_speed_max >= 5000) {
   2707             ability->speed_full_duplex |= SOC_PA_SPEED_5000MB;
   2708             /* For 5G speed, MAC will actually be set to 10G */
   2709         }
   2710         /* Temp fix running regression, saber2 check 
   2711          * In Saber2, the xlmac is used for MXQ ports as well. 
   2712          */
   2713         if (soc_feature(unit, soc_feature_unified_port) || (SOC_IS_SABER2(unit))) {
   2714             if (port_speed_max >= 2500) {
   2715                 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB;
   2716             }
   2717             if (port_speed_max >= 1000) {
   2718                 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   2719             }
   2720             if (port_speed_max >= 100) {
   2721                 ability->speed_full_duplex |= SOC_PA_SPEED_100MB;
   2722             }
   2723             if (port_speed_max >= 10) {
   2724                 ability->speed_full_duplex |= SOC_PA_SPEED_10MB;
   2725             }
   2726         }
   2727     }
   2728 
   2729     LOG_VERBOSE(BSL_LS_SOC_10G,
   2730                 (BSL_META_U(unit,
   2731                             "mac_xl_ability_local_get: unit %d port %s "
   2732                             "speed_half=0x%x speed_full=0x%x encap=0x%x pause=0x%x "
   2733                             "interface=0x%x medium=0x%x loopback=0x%x flags=0x%x\n"),
   2734                  unit, SOC_PORT_NAME(unit, port),
   2735                  ability->speed_half_duplex, ability->speed_full_duplex,
   2736                  ability->encap, ability->pause, ability->interface,
   2737                  ability->medium, ability->loopback, ability->flags));
   2738     return SOC_E_NONE;
   2739 }
   2740 
   2741 static int
   2742 mac_xl_timesync_tx_info_get (int unit, soc_port_t port,
   2743                                         soc_port_timesync_tx_info_t *tx_info)
   2744 {
   2745     uint64 rval;
   2746 
   2747     SOC_IF_ERROR_RETURN
   2748         (READ_XLMAC_TX_TIMESTAMP_FIFO_STATUSr(unit, port, &rval));
   2749     if (soc_reg64_field32_get(unit, XLMAC_TX_TIMESTAMP_FIFO_STATUSr, rval,
   2750                               ENTRY_COUNTf) == 0) {
   2751         return SOC_E_EMPTY;
   2752     }
   2753     SOC_IF_ERROR_RETURN
   2754         (READ_XLMAC_TX_TIMESTAMP_FIFO_DATAr(unit, port, &rval));
   2755     tx_info->timestamps_in_fifo = soc_reg64_field32_get(unit, XLMAC_TX_TIMESTAMP_FIFO_DATAr,
   2756                                    rval, TIME_STAMPf);
   2757     tx_info->timestamps_in_fifo_hi = 0;
   2758     tx_info->sequence_id = soc_reg64_field32_get(unit,
   2759                 XLMAC_TX_TIMESTAMP_FIFO_DATAr, rval, SEQUENCE_IDf);
   2760 
   2761     return (SOC_E_NONE);
   2762 }
   2763 
   2764 /* Exported XLMAC driver structure */
   2765 mac_driver_t soc_mac_xl = {
   2766     "XLMAC Driver",               /* drv_name */
   2767     mac_xl_init,                  /* md_init  */
   2768     mac_xl_enable_set,            /* md_enable_set */
   2769     mac_xl_enable_get,            /* md_enable_get */
   2770     mac_xl_duplex_set,            /* md_duplex_set */
   2771     mac_xl_duplex_get,            /* md_duplex_get */
   2772     mac_xl_speed_set,             /* md_speed_set */
   2773     mac_xl_speed_get,             /* md_speed_get */
   2774     mac_xl_pause_set,             /* md_pause_set */
   2775     mac_xl_pause_get,             /* md_pause_get */
   2776     mac_xl_pause_addr_set,        /* md_pause_addr_set */
   2777     mac_xl_pause_addr_get,        /* md_pause_addr_get */
   2778     mac_xl_loopback_set,          /* md_lb_set */
   2779     mac_xl_loopback_get,          /* md_lb_get */
   2780     mac_xl_interface_set,         /* md_interface_set */
   2781     mac_xl_interface_get,         /* md_interface_get */
   2782     NULL,                         /* md_ability_get - Deprecated */
   2783     mac_xl_frame_max_set,         /* md_frame_max_set */
   2784     mac_xl_frame_max_get,         /* md_frame_max_get */
   2785     mac_xl_ifg_set,               /* md_ifg_set */
   2786     mac_xl_ifg_get,               /* md_ifg_get */
   2787     mac_xl_encap_set,             /* md_encap_set */
   2788     mac_xl_encap_get,             /* md_encap_get */
   2789     mac_xl_control_set,           /* md_control_set */
   2790     mac_xl_control_get,           /* md_control_get */
   2791     mac_xl_ability_local_get,     /* md_ability_local_get */
   2792     mac_xl_timesync_tx_info_get   /* md_timesync_tx_info_get */
   2793  };
   2794 
   2795 #endif /* BCM_XLMAC_SUPPORT */