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

clmac.c (80018B)


      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  * CLMAC driver
      8  */
      9 
     10 #include <sal/core/libc.h>
     11 #include <shared/alloc.h>
     12 #include <sal/core/spl.h>
     13 #include <sal/core/boot.h>
     14 #include <shared/bsl.h>
     15 #include <soc/drv.h>
     16 #include <soc/error.h>
     17 #include <soc/cmic.h>
     18 #include <soc/portmode.h>
     19 #include <soc/ll.h>
     20 #include <soc/macutil.h>
     21 #include <soc/phyctrl.h>
     22 #include <soc/debug.h>
     23 #ifdef BCM_GREYHOUND2_SUPPORT
     24 #include <soc/greyhound2.h>
     25 #endif
     26 #ifdef BCM_TOMAHAWK_SUPPORT
     27 #include <soc/tomahawk.h>
     28 #endif
     29 
     30 #ifdef BCM_CLMAC_SUPPORT
     31 
     32 /* Gen version of PM4x25G
     33  * Gen1:0xA023 include TH, TD2P, Apache, Jericho, Jericho+, QAX, QMX
     34  * Gen2:0xA030 include TH+, TH2,
     35  */
     36 enum clmac_version_e {
     37     CLMAC_VERSION_A023 = 0xA023,
     38     CLMAC_VERSION_A030 = 0xA030
     39 };
     40 
     41 #define CLMAC_RUNT_THRESHOLD_IEEE  0x40   /* Runt threshold value for XE ports */
     42 #define CLMAC_RUNT_THRESHOLD_HG1   0x48   /* Runt threshold value for HG1 ports */
     43 #define CLMAC_RUNT_THRESHOLD_HG2   0x4c   /* Runt threshold value for HG2 ports */
     44 
     45 /*
     46  * CLMAC Register field definitions.
     47  */
     48 
     49 #define JUMBO_MAXSZ              0x3fe8 /* Max legal value (per regsfile) */
     50 
     51 #define SOC_CLMAC_SPEED_1000   0x2
     52 #define SOC_CLMAC_SPEED_100000 0x4
     53 
     54 /*
     55  * CLMAC timestamp delay definitions
     56  */
     57 #define CLMAC_TX_LINE_RATE_NS   0x3 /* TSC CLK FREQ is 644MHz */
     58 #define CLMAC_TSC_CLK_NS        4
     59 
     60 /* Transmit CRC Modes */
     61 #define CLMAC_CRC_APPEND        0x0
     62 #define CLMAC_CRC_KEEP          0x1
     63 #define CLMAC_CRC_REPLACE       0x2
     64 #define CLMAC_CRC_PER_PKT_MODE  0x3
     65 
     66 /*
     67  *  WAN mode throttling
     68  *  THROT_10G_TO_5G: throt_num=21 throt_denom=21
     69  *  THROT_10G_TO_2P5G: throt_num=63 throt_denom=21
     70  */
     71 #define CLMAC_THROT_10G_TO_5G    256
     72 #define CLMAC_THROT_10G_TO_2P5G  257
     73 
     74 mac_driver_t soc_mac_cl;
     75 
     76 #ifdef BROADCOM_DEBUG
     77 static char *mac_cl_encap_mode[] = SOC_ENCAP_MODE_NAMES_INITIALIZER;
     78 static char *mac_cl_port_if_names[] = SOC_PORT_IF_NAMES_INITIALIZER;
     79 #endif /* BROADCOM_DEBUG */
     80 
     81 STATIC int
     82 _mac_cl_timestamp_delay_set(int unit, soc_port_t port, int speed);
     83 STATIC int
     84 mac_cl_speed_get(int unit, soc_port_t port, int *speed);
     85 
     86 STATIC int
     87 _clmac_gen_version_get(int unit, soc_port_t port, int *ver)
     88 {
     89     int         rv;
     90     uint64 reg_val;
     91     rv  = SOC_E_NONE;
     92 
     93     if (!SOC_REG_IS_VALID(unit, CLMAC_VERSION_IDr)) {
     94         *ver = -1;
     95     } else {
     96         SOC_IF_ERROR_RETURN(READ_CLMAC_VERSION_IDr(unit, port, &reg_val));
     97         *ver = soc_reg64_field32_get(unit, CLMAC_VERSION_IDr, reg_val, CLMAC_VERSIONf);
     98     }
     99 
    100     return rv;
    101 }
    102 
    103 STATIC int
    104 _mac_cl_drain_cells(int unit, soc_port_t port, int notify_phy)
    105 {
    106     int         rv;
    107     int         pause_tx = 0, pause_rx = 0, pfc_rx = 0, llfc_rx = 0;
    108     soc_field_t fields[2];
    109     uint32      values[2], fval, drain_timeout;
    110     uint64      mac_ctrl, rval64;
    111     soc_timeout_t to;
    112 
    113     rv  = SOC_E_NONE;
    114 
    115     if (SOC_IS_RELOADING(unit)) {
    116         return rv;
    117     }
    118 
    119     drain_timeout = SAL_BOOT_QUICKTURN ? 250000000 : 250000;
    120     if (!soc_feature(unit, soc_feature_mmu_hw_flush)) {
    121         /* Drain cells in mmu/port before cells entering TX FIFO */
    122         SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, TRUE));
    123 
    124         /* Disable pause/pfc/llfc function */
    125         SOC_IF_ERROR_RETURN
    126             (soc_mac_cl.md_pause_get(unit, port, &pause_tx, &pause_rx));
    127         SOC_IF_ERROR_RETURN
    128             (soc_mac_cl.md_pause_set(unit, port, pause_tx, 0));
    129 
    130         SOC_IF_ERROR_RETURN
    131             (soc_mac_cl.md_control_get(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE,
    132                                        &pfc_rx));
    133         SOC_IF_ERROR_RETURN
    134             (soc_mac_cl.md_control_set(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE,
    135                                        0));
    136 
    137         SOC_IF_ERROR_RETURN
    138             (soc_mac_cl.md_control_get(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE,
    139                                        &llfc_rx));
    140         SOC_IF_ERROR_RETURN
    141             (soc_mac_cl.md_control_set(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE,
    142                                        0));
    143     }
    144 
    145     if (!soc_feature(unit, soc_feature_mmu_hw_flush)) {
    146         /* Assert SOFT_RESET before DISCARD just in case there is no credit left */
    147         SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &mac_ctrl));
    148         soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 1);
    149         /* Drain data in TX FIFO without egressing */
    150         SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, mac_ctrl));
    151     }
    152 
    153     fields[0] = DISCARDf;
    154     values[0] = 1;
    155     fields[1] = EP_DISCARDf;
    156     values[1] = 1;
    157     SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, CLMAC_TX_CTRLr, port, 2,
    158                                                 fields, values));
    159 
    160     /* Reset EP credit before de-assert SOFT_RESET */
    161     SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port));
    162 
    163     if (!soc_feature(unit, soc_feature_mmu_hw_flush)) {
    164         /* De-assert SOFT_RESET to let the drain start */
    165         soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0);
    166         SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, mac_ctrl));
    167     }
    168 
    169     if (notify_phy == 1) {
    170         /* Notify PHY driver */
    171         SOC_IF_ERROR_RETURN
    172             (soc_phyctrl_notify(unit, port, phyEventStop, PHY_STOP_DRAIN));
    173     }
    174 
    175     /* Wait until mmu cell count is 0 */
    176     rv = soc_egress_drain_cells(unit, port, drain_timeout);
    177     if (SOC_E_NONE == rv) {
    178         /* Wait until TX fifo cell count is 0 */
    179         soc_timeout_init(&to, drain_timeout, 0);
    180         for (;;) {
    181             rv =  READ_CLMAC_TXFIFO_CELL_CNTr(unit, port, &rval64);
    182             if (SOC_E_NONE != rv) {
    183                 break;
    184             }
    185             fval = soc_reg64_field32_get(unit, CLMAC_TXFIFO_CELL_CNTr, rval64,
    186                                          CELL_CNTf);
    187             if (fval == 0) {
    188                 break;
    189             }
    190             if (soc_timeout_check(&to)) {
    191                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    192                             (BSL_META_U(unit,
    193                                 "mac_cl_drain_cells: unit %d "
    194                                 "ERROR: port %s: "
    195                                 "timeout draining TX FIFO (%d cells remain)\n"),
    196                                 unit, SOC_PORT_NAME(unit, port), fval));
    197                 rv = SOC_E_INTERNAL;
    198                 break;
    199             }
    200         }
    201     }
    202 
    203     if (notify_phy == 1) {
    204         /* Notify PHY driver */
    205         SOC_IF_ERROR_RETURN
    206             (soc_phyctrl_notify(unit, port, phyEventResume, PHY_STOP_DRAIN));
    207     }
    208   
    209     /* Stop TX FIFO draining */
    210     values[0] = 0;
    211     values[1] = 0;
    212     SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, CLMAC_TX_CTRLr, port, 2,
    213                                                 fields, values));
    214     /* Restore config below only if modified above, i.e. h/w flush not used */
    215     if (!soc_feature(unit, soc_feature_mmu_hw_flush)) {
    216         /* Restore original pause/pfc/llfc configuration */
    217         SOC_IF_ERROR_RETURN
    218             (soc_mac_cl.md_pause_set(unit, port, pause_tx, pause_rx));
    219         SOC_IF_ERROR_RETURN
    220             (soc_mac_cl.md_control_set(unit, port,
    221                                        SOC_MAC_CONTROL_PFC_RX_ENABLE,
    222                                        pfc_rx));
    223         SOC_IF_ERROR_RETURN
    224             (soc_mac_cl.md_control_set(unit, port,
    225                                        SOC_MAC_CONTROL_LLFC_RX_ENABLE,
    226                                        llfc_rx));
    227     
    228         /* Stop draining cells in mmu/port */
    229         SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, FALSE));
    230     }
    231 
    232     return rv;
    233 }
    234 
    235 /*
    236  * Function:
    237  *      mac_cl_init
    238  * Purpose:
    239  *      Initialize Clmac into a known good state.
    240  * Parameters:
    241  *      unit - XGS unit #.
    242  *      port - Port number on unit.
    243  * Returns:
    244  *      SOC_E_XXX
    245  * Notes:
    246  */
    247 STATIC int
    248 mac_cl_init(int unit, soc_port_t port)
    249 {
    250     soc_info_t *si;
    251     uint64 mac_ctrl, rx_ctrl, tx_ctrl, rval;
    252     int ipg, runt;
    253     int mode;
    254     int encap = SOC_ENCAP_IEEE;
    255 
    256 
    257     si = &SOC_INFO(unit);
    258 
    259     /* Disable Tx/Rx, assume that MAC is stable (or out of reset) */
    260     SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &mac_ctrl));
    261 
    262     /* Reset EP credit before de-assert SOFT_RESET */
    263     if (soc_reg64_field32_get(unit, CLMAC_CTRLr, mac_ctrl, SOFT_RESETf)) {
    264         SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port));
    265     }
    266 
    267     soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0);
    268     soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, RX_ENf, 0);
    269     soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, TX_ENf, 0);
    270     if (soc_reg_field_valid(unit, CLMAC_CTRLr, XLGMII_ALIGN_ENBf)) {
    271         soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, XLGMII_ALIGN_ENBf,
    272                               1);
    273     }
    274     soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl,
    275                           XGMII_IPG_CHECK_DISABLEf,
    276                           IS_HG_PORT(unit, port) ? 1 : 0);
    277     SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, mac_ctrl));
    278 
    279     SOC_IF_ERROR_RETURN(READ_CLMAC_TX_CTRLr(unit, port, &tx_ctrl));
    280     ipg = IS_HG_PORT(unit,port)?  SOC_PERSIST(unit)->ipg[port].fd_hg:
    281                                   SOC_PERSIST(unit)->ipg[port].fd_xe;
    282     soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &tx_ctrl, AVERAGE_IPGf,
    283                           (ipg / 8) & 0x1f);
    284     soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf,
    285                           CLMAC_CRC_PER_PKT_MODE);
    286     SOC_IF_ERROR_RETURN(WRITE_CLMAC_TX_CTRLr(unit, port, tx_ctrl));
    287 
    288     if (IS_ST_PORT(unit, port)) {
    289         soc_mac_cl.md_pause_set(unit, port, FALSE, FALSE);
    290     } else {
    291         soc_mac_cl.md_pause_set(unit, port, TRUE, TRUE);
    292     }
    293 
    294     SOC_IF_ERROR_RETURN
    295         (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, PFC_REFRESH_ENf,
    296                                 1));
    297 
    298     if (soc_property_port_get(unit, port, spn_PHY_WAN_MODE, FALSE)) {
    299         /* Max speed for WAN mode is 9.294Gbps.
    300          * This setting gives 10Gbps * (13/14) or 9.286 Gbps */
    301         SOC_IF_ERROR_RETURN
    302             (soc_mac_cl.md_control_set(unit, port,
    303                                        SOC_MAC_CONTROL_FRAME_SPACING_STRETCH,
    304                                        13));
    305     }
    306 
    307     /* Set jumbo max size (8000 byte payload) */
    308     COMPILER_64_ZERO(rval);
    309 #ifdef BCM_XGS_SUPPORT
    310     if (SOC_IS_XGS3_SWITCH(unit)) {
    311         uint32 rval;
    312         soc_reg_t reg;
    313 
    314         reg = SOC_REG_IS_VALID(unit, EGR_MTUr) ? EGR_MTUr : EGR_MTU_SIZEr;
    315         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    316         soc_reg_field_set(unit, reg, &rval, MTU_SIZEf, SOC_INFO(unit).max_mtu);
    317         if (soc_reg_field_valid(unit, reg, MTU_ENABLEf)) {
    318             soc_reg_field_set(unit, reg, &rval, MTU_ENABLEf, 1);
    319         }
    320         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
    321     }
    322 
    323     if (SOC_IS_XGS(unit)) {
    324         soc_reg64_field32_set(unit, CLMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf,
    325                               SOC_INFO(unit).max_mtu);
    326     } else
    327 #endif
    328     {
    329         soc_reg64_field32_set(unit, CLMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf,
    330                               JUMBO_MAXSZ);
    331     }
    332     SOC_IF_ERROR_RETURN(WRITE_CLMAC_RX_MAX_SIZEr(unit, port, rval));
    333 
    334     /* Setup header mode, check for property for higig2 mode */
    335     SOC_IF_ERROR_RETURN(READ_CLMAC_MODEr(unit, port, &rval));
    336     if (IS_HG_PORT(unit, port)) {
    337         mode = soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE,
    338                soc_feature(unit, soc_feature_no_higig_plus) ? 1 : 0) ? 2 : 1;
    339         encap = (mode == 2) ? SOC_ENCAP_HIGIG2 : SOC_ENCAP_HIGIG;
    340         soc_reg64_field32_set(unit, CLMAC_MODEr, &rval, HDR_MODEf, mode);
    341     }
    342     SOC_IF_ERROR_RETURN(WRITE_CLMAC_MODEr(unit, port, rval));
    343 
    344     SOC_IF_ERROR_RETURN(READ_CLMAC_RX_CTRLr(unit, port, &rx_ctrl));
    345     soc_reg64_field32_set(unit, CLMAC_RX_CTRLr, &rx_ctrl, STRIP_CRCf, 0);
    346     soc_reg64_field32_set(unit, CLMAC_RX_CTRLr, &rx_ctrl, STRICT_PREAMBLEf,
    347                           si->port_speed_max[port] >= 10000 &&
    348                           IS_CL_PORT(unit, port) &&
    349                           !IS_HG_PORT(unit, port) ? 1 : 0);
    350     /* assigning RUNT_THRESHOLD per header mode setting */
    351     runt = (encap == SOC_ENCAP_HIGIG2) ? CLMAC_RUNT_THRESHOLD_HG2 :
    352            ((encap == SOC_ENCAP_HIGIG) ? CLMAC_RUNT_THRESHOLD_HG1 :
    353                                          CLMAC_RUNT_THRESHOLD_IEEE);
    354     soc_reg64_field32_set(unit, CLMAC_RX_CTRLr, &rx_ctrl, RUNT_THRESHOLDf,
    355                           runt);
    356     SOC_IF_ERROR_RETURN(WRITE_CLMAC_RX_CTRLr(unit, port, rx_ctrl));
    357 
    358     SOC_IF_ERROR_RETURN(READ_CLMAC_RX_LSS_CTRLr(unit, port, &rval));
    359     soc_reg64_field32_set(unit, CLMAC_RX_LSS_CTRLr, &rval,
    360                           DROP_TX_DATA_ON_LOCAL_FAULTf, 1);
    361     soc_reg64_field32_set(unit, CLMAC_RX_LSS_CTRLr, &rval,
    362                           DROP_TX_DATA_ON_REMOTE_FAULTf, 1);
    363     soc_reg64_field32_set(unit, CLMAC_RX_LSS_CTRLr, &rval,
    364                           DROP_TX_DATA_ON_LINK_INTERRUPTf, 1);
    365     SOC_IF_ERROR_RETURN(WRITE_CLMAC_RX_LSS_CTRLr(unit, port, rval));
    366 
    367     /* Disable loopback and bring CLMAC out of reset */
    368     soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, LOCAL_LPBKf, 0);
    369     soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, RX_ENf, 1);
    370     soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, TX_ENf, 1);
    371     SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, mac_ctrl));
    372 
    373     return SOC_E_NONE;
    374 }
    375 
    376 /*
    377  * Function:
    378  *      mac_cl_egress_queue_drain
    379  * Purpose:
    380  *      Drain the egress queues with out bringing down the port
    381  * Parameters:
    382  *      unit - XGS unit #.
    383  *      port - Port number on unit.
    384  * Returns:
    385  *      SOC_E_XXX
    386  */
    387 STATIC int
    388 mac_cl_egress_queue_drain(int unit, soc_port_t port)
    389 {
    390     uint64 ctrl, octrl;
    391     pbmp_t mask;
    392     int rx_enable = 0;
    393     int is_active = 0;
    394 
    395     LOG_VERBOSE(BSL_LS_SOC_10G,
    396                 (BSL_META_U(unit,
    397                             "mac_cl_egress_queue_drain: unit %d port %s \n"),
    398                  unit, SOC_PORT_NAME(unit, port)));
    399 
    400     SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl));
    401     octrl = ctrl;
    402 
    403     rx_enable = soc_reg64_field32_get(unit, CLMAC_CTRLr, ctrl, RX_ENf);
    404     /* Don't disable TX since it stops egress and hangs if CPU sends */
    405     soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, TX_ENf, 1);
    406     soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, RX_ENf, 0);
    407         /* Disable RX */
    408     SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl));
    409 
    410         /* Remove port from EPC_LINK */
    411     soc_link_mask2_get(unit, &mask);
    412     if (SOC_PBMP_MEMBER(mask, port)) {
    413         is_active = 1;
    414         SOC_PBMP_PORT_REMOVE(mask, port);
    415         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    416     }
    417 
    418         /* Drain cells */
    419     SOC_IF_ERROR_RETURN(_mac_cl_drain_cells(unit, port, 0));
    420 
    421         /* Put port into SOFT_RESET */
    422     soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 1);
    423     SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl));
    424 
    425         /* Reset EP credit before de-assert SOFT_RESET */
    426     SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port));
    427     SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl));
    428     soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, RX_ENf, rx_enable ? 1 : 0);
    429 
    430       /* Enable both TX and RX, deassert SOFT_RESET */
    431     soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 0);
    432     SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl));
    433 
    434         /* Restore CLMAC_CTRL to original value */
    435     SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, octrl));        
    436 
    437         /* Add port to EPC_LINK */
    438     if(is_active) {
    439         soc_link_mask2_get(unit, &mask);
    440         SOC_PBMP_PORT_ADD(mask, port);
    441         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    442     }
    443  
    444     return SOC_E_NONE;
    445 }
    446 
    447 /*
    448  * Function:
    449  *      mac_cl_enable_set
    450  * Purpose:
    451  *      Enable or disable MAC
    452  * Parameters:
    453  *      unit - XGS unit #.
    454  *      port - Port number on unit.
    455  *      enable - TRUE to enable, FALSE to disable
    456  * Returns:
    457  *      SOC_E_XXX
    458  */
    459 STATIC int
    460 mac_cl_enable_set(int unit, soc_port_t port, int enable)
    461 {
    462     uint64 ctrl, octrl;
    463     pbmp_t mask;
    464     int speed = 1000;
    465 
    466     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    467                 (BSL_META_U(unit,
    468                             "mac_cl_enable_set: unit %d port %s enable=%s\n"),
    469                             unit, SOC_PORT_NAME(unit, port),
    470                             enable ? "True" : "False"));
    471 
    472     SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl));
    473     octrl = ctrl;
    474     /* Don't disable TX since it stops egress and hangs if CPU sends */
    475     soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, TX_ENf, 1);
    476     soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, RX_ENf, enable ? 1 : 0);
    477 
    478     if (COMPILER_64_EQ(ctrl, octrl)) {
    479         if (enable) {
    480             return SOC_E_NONE;
    481         } else {
    482             if (soc_reg64_field32_get(unit, CLMAC_CTRLr, ctrl, SOFT_RESETf)) {
    483                 return SOC_E_NONE;
    484             }
    485         }
    486     }
    487 
    488 
    489     if (enable) {
    490         /* Reset EP credit before de-assert SOFT_RESET */
    491         SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port));
    492         /* Deassert SOFT_RESET */
    493         soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 0);
    494         /* Deassert EGR_XLPORT_BUFFER_SFT_RESET */
    495         SOC_IF_ERROR_RETURN(soc_port_egress_buffer_sft_reset(unit, port, 0));
    496         /* Release Ingress buffers from reset */
    497         SOC_IF_ERROR_RETURN(soc_port_ingress_buffer_reset(unit, port, 0));
    498         SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl));
    499 
    500 #if defined(BCM_TOMAHAWKPLUS_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
    501         /* Special handling for new mac version for TH+. Internally MAC loopback looks for rising */
    502         /* edge on MAC loopback configuration to enter loopback state */
    503         if (SOC_IS_TOMAHAWKPLUS(unit) || SOC_IS_GREYHOUND2(unit)) {
    504             uint32 ctrl_32;
    505             COMPILER_64_TO_32_LO(ctrl_32, ctrl);
    506             if (ctrl_32 & 0x4) {      /* Do only if loopback bit is intented to be set */
    507                 soc_reg_field32_modify(unit, CLMAC_CTRLr, port, LOCAL_LPBKf, 0);
    508                 sal_usleep(10);    /* Wait 10usec as suggested by MAC designer */
    509                 soc_reg_field32_modify(unit, CLMAC_CTRLr, port, LOCAL_LPBKf, 1);
    510             }
    511         }
    512 #endif /* TOMAHAWKPLUS || GREYHOUHD2 */
    513 
    514         /* Enable MMU port */
    515         SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, TRUE));
    516 
    517         soc_link_mask2_get(unit, &mask);
    518         SOC_PBMP_PORT_ADD(mask, port);
    519         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    520         SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventResume,
    521                                                PHY_STOP_MAC_DIS));
    522 
    523         /* set timestamp adjust delay */
    524         SOC_IF_ERROR_RETURN(mac_cl_speed_get(unit, port, &speed));
    525         SOC_IF_ERROR_RETURN(_mac_cl_timestamp_delay_set(unit, port, speed));
    526 
    527     } else {
    528         /* Disable MAC RX */
    529         SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl));
    530         soc_link_mask2_get(unit, &mask);
    531         SOC_PBMP_PORT_REMOVE(mask, port);
    532         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    533         /*
    534          * Disable MMU port
    535          * for some devices where EPC_LINK can not block the SOBMH from cpu and
    536          * no mechanism is avalible to reset EDATABUF.
    537          */
    538         SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, FALSE));
    539 
    540         /* Delay to ensure EOP is received at Ingress */
    541         sal_udelay(1000);
    542         /* Reset Ingress buffers */
    543         SOC_IF_ERROR_RETURN(soc_port_ingress_buffer_reset(unit, port, 1));
    544         SOC_IF_ERROR_RETURN(_mac_cl_drain_cells(unit, port, 1));
    545         /* Reset egress_buffer */
    546         SOC_IF_ERROR_RETURN(soc_port_egress_buffer_sft_reset(unit, port, 1));
    547         /* Put port into SOFT_RESET */
    548         soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 1); 
    549         SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl));
    550         SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventStop,
    551                                                PHY_STOP_MAC_DIS));
    552     }
    553 
    554     return SOC_E_NONE;
    555 }
    556 
    557 /*
    558  * Function:
    559  *      mac_cl_enable_get
    560  * Purpose:
    561  *      Get MAC enable state
    562  * Parameters:
    563  *      unit - XGS unit #.
    564  *      port - Port number on unit.
    565  *      enable - (OUT) TRUE if enabled, FALSE if disabled
    566  * Returns:
    567  *      SOC_E_XXX
    568  */
    569 STATIC int
    570 mac_cl_enable_get(int unit, soc_port_t port, int *enable)
    571 {
    572     uint64 ctrl;
    573 
    574     SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl));
    575 
    576     *enable = soc_reg64_field32_get(unit, CLMAC_CTRLr, ctrl, RX_ENf);
    577 
    578     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    579                 (BSL_META_U(unit,
    580                             "mac_cl_enable_get: unit %d port %s enable=%s\n"),
    581                             unit, SOC_PORT_NAME(unit, port),
    582                             *enable ? "True" : "False"));
    583 
    584     return SOC_E_NONE;
    585 }
    586 
    587 /*
    588  * Function:
    589  *      _mac_cl_timestamp_delay_set
    590  * Purpose:
    591  *      Set Timestamp delay for one-step to account for lane and pipeline delay.
    592  * Parameters:
    593  *      unit - XGS unit #.
    594  *      port - Port number on unit.
    595  *      speed - New port speed
    596  * Returns:
    597  *      SOC_E_XXX
    598  */
    599 STATIC int
    600 _mac_cl_timestamp_delay_set(int unit, soc_port_t port, int speed)
    601 {
    602     uint64 ctrl;
    603     int osts_delay = 0;
    604     uint32 tsts_delay = 0;
    605     uint32 field;
    606 
    607     LOG_VERBOSE(BSL_LS_SOC_10G,
    608                 (BSL_META_U(unit,
    609                  "mac_cl_timestamp_delay_set: unit %d port %s speed %d\n"),
    610                  unit, SOC_PORT_NAME(unit, port), speed));
    611 
    612     if (SOC_REG_IS_VALID(unit, CLMAC_TIMESTAMP_ADJUSTr)) {
    613         SOC_IF_ERROR_RETURN(READ_CLMAC_TIMESTAMP_ADJUSTr(unit, port, &ctrl));
    614 
    615         /*
    616          * CLMAC pipeline latency is : ( as in CLMAC specification)
    617          *          = (6 * TX line clock period + Timestamp clock period)
    618          */
    619         
    620         
    621         /* This is a signed value of pipeline delay in ns */
    622         osts_delay = soc_property_port_get(unit, port, spn_TIMESTAMP_ADJUST(speed),
    623                                            CLMAC_TSC_CLK_NS +
    624                                            (3 * CLMAC_TX_LINE_RATE_NS));
    625 
    626         if (SOC_E_NONE != soc_reg_signed_field_mask(unit, CLMAC_TIMESTAMP_ADJUSTr,
    627                               TS_OSTS_ADJUSTf, osts_delay, &field)) {
    628             LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit,
    629                 "%s osts property out of bounds (is %d)\n"),
    630                 spn_TIMESTAMP_ADJUST(speed), osts_delay));
    631             field = 0;
    632         }
    633         soc_reg64_field32_set(unit, CLMAC_TIMESTAMP_ADJUSTr, &ctrl,
    634                               TS_OSTS_ADJUSTf, field);
    635 
    636         /* Note:
    637            TSTS delay uses different SOC property as OSTS delay, in order to
    638            allow specification based on platform.  However, the resulting timestamps
    639            in the FIFO are only used by the application, so the application can make
    640            other timestamp adjustments as required.
    641            CLMAC CDC FIFO latency is :
    642                    = (2.5 * TX line clock period + Timestamp clock period)
    643            This is an unsigned value and the range is 0~63.
    644         */
    645         tsts_delay = soc_property_port_get(unit, port, spn_TIMESTAMP_TSTS_ADJUST(speed),
    646                                            CLMAC_TSC_CLK_NS +
    647                                            ((5 * CLMAC_TX_LINE_RATE_NS) / 4));
    648 
    649         if (SOC_E_NONE != soc_reg_unsigned_field_mask(unit, CLMAC_TIMESTAMP_ADJUSTr,
    650                               TS_TSTS_ADJUSTf, tsts_delay, &field)) {
    651             LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit,
    652                 "%s tsts property out of bounds (is %d)\n"),
    653                 spn_TIMESTAMP_TSTS_ADJUST(speed), tsts_delay));
    654             field = 0;
    655         }
    656         soc_reg64_field32_set(unit, CLMAC_TIMESTAMP_ADJUSTr, &ctrl,
    657                               TS_TSTS_ADJUSTf, field);
    658 
    659 
    660         SOC_IF_ERROR_RETURN(WRITE_CLMAC_TIMESTAMP_ADJUSTr(unit, port, ctrl));
    661     }
    662 
    663     return SOC_E_NONE;
    664 }
    665 
    666 /*
    667  * Function:
    668  *      mac_cl_duplex_set
    669  * Purpose:
    670  *      Set CLMAC in the specified duplex mode.
    671  * Parameters:
    672  *      unit - XGS unit #.
    673  *      port - XGS port # on unit.
    674  *      duplex - Boolean: true --> full duplex, false --> half duplex.
    675  * Returns:
    676  *      SOC_E_XXX
    677  * Notes:
    678  */
    679 STATIC int
    680 mac_cl_duplex_set(int unit, soc_port_t port, int duplex)
    681 {
    682     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    683                 (BSL_META_U(unit,
    684                             "mac_cl_duplex_set: unit %d port %s duplex=%s\n"),
    685                             unit, SOC_PORT_NAME(unit, port),
    686                             duplex ? "Full" : "Half"));
    687     return SOC_E_NONE;
    688 }
    689 
    690 /*
    691  * Function:
    692  *      mac_cl_duplex_get
    693  * Purpose:
    694  *      Get CLMAC duplex mode.
    695  * Parameters:
    696  *      unit - XGS unit #.
    697  *      duplex - (OUT) Boolean: true --> full duplex, false --> half duplex.
    698  * Returns:
    699  *      SOC_E_XXX
    700  */
    701 STATIC int
    702 mac_cl_duplex_get(int unit, soc_port_t port, int *duplex)
    703 {
    704     *duplex = TRUE; /* Always full duplex */
    705 
    706     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    707                 (BSL_META_U(unit,
    708                             "mac_cl_duplex_get: unit %d port %s duplex=%s\n"),
    709                             unit, SOC_PORT_NAME(unit, port),
    710                             *duplex ? "Full" : "Half"));
    711     return SOC_E_NONE;
    712 }
    713 
    714 /*
    715  * Function:
    716  *      mac_cl_pause_set
    717  * Purpose:
    718  *      Configure CLMAC to transmit/receive pause frames.
    719  * Parameters:
    720  *      unit - XGS unit #.
    721  *      port - XGS port # on unit.
    722  *      pause_tx - Boolean: transmit pause or -1 (don't change)
    723  *      pause_rx - Boolean: receive pause or -1 (don't change)
    724  * Returns:
    725  *      SOC_E_XXX
    726  */
    727 STATIC int
    728 mac_cl_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx)
    729 {
    730     soc_field_t fields[2] = { TX_PAUSE_ENf, RX_PAUSE_ENf };
    731     uint32 values[2];
    732 
    733     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    734                 (BSL_META_U(unit,
    735                             "mac_cl_pause_set: unit %d port %s TX=%s RX=%s\n"),
    736                             unit, SOC_PORT_NAME(unit, port),
    737                             pause_tx != FALSE ? "on" : "off",
    738                             pause_rx != FALSE ? "on" : "off"));
    739 
    740     values[0] = pause_tx != FALSE ? 1 : 0;
    741     values[1] = pause_rx != FALSE ? 1 : 0;
    742     return soc_reg_fields32_modify(unit, CLMAC_PAUSE_CTRLr, port, 2,
    743                                    fields, values);
    744 }
    745 
    746 /*
    747  * Function:
    748  *      mac_cl_pause_get
    749  * Purpose:
    750  *      Return the pause ability of CLMAC
    751  * Parameters:
    752  *      unit - XGS unit #.
    753  *      port - XGS port # on unit.
    754  *      pause_tx - Boolean: transmit pause
    755  *      pause_rx - Boolean: receive pause
    756  *      pause_mac - MAC address used for pause transmission.
    757  * Returns:
    758  *      SOC_E_XXX
    759  */
    760 STATIC int
    761 mac_cl_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx)
    762 {
    763     uint64 rval;
    764 
    765     SOC_IF_ERROR_RETURN(READ_CLMAC_PAUSE_CTRLr(unit, port, &rval));
    766     *pause_tx =
    767         soc_reg64_field32_get(unit, CLMAC_PAUSE_CTRLr, rval, TX_PAUSE_ENf);
    768     *pause_rx =
    769         soc_reg64_field32_get(unit, CLMAC_PAUSE_CTRLr, rval, RX_PAUSE_ENf);
    770     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    771                 (BSL_META_U(unit,
    772                             "mac_cl_pause_get: unit %d port %s TX=%s RX=%s\n"),
    773                              unit, SOC_PORT_NAME(unit, port),
    774                              *pause_tx ? "on" : "off",
    775                              *pause_rx ? "on" : "off"));
    776     return SOC_E_NONE;
    777 }
    778 
    779 /*
    780  * Function:
    781  *      mac_cl_speed_set
    782  * Purpose:
    783  *      Set CLMAC in the specified speed.
    784  * Parameters:
    785  *      unit - XGS unit #.
    786  *      port - XGS port # on unit.
    787  *      speed - 100000, 120000.
    788  * Returns:
    789  *      SOC_E_XXX
    790  */
    791 STATIC int
    792 mac_cl_speed_set(int unit, soc_port_t port, int speed)
    793 {
    794     int enable;
    795     uint32 rval;
    796     uint32 fault;
    797 
    798     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    799                 (BSL_META_U(unit,
    800                             "mac_cl_speed_set: unit %d port %s speed=%dMb\n"),
    801                             unit, SOC_PORT_NAME(unit, port),
    802                             speed));
    803 
    804     SOC_IF_ERROR_RETURN(mac_cl_enable_get(unit, port, &enable));
    805         
    806     if (enable) {
    807         /* Turn off TX/RX enable */
    808         SOC_IF_ERROR_RETURN(mac_cl_enable_set(unit, port, 0));
    809     }
    810 
    811     SOC_IF_ERROR_RETURN
    812         (soc_reg_field32_modify(unit, CLMAC_RX_CTRLr, port, STRICT_PREAMBLEf,
    813                                 speed >= 10000 &&
    814                                 IS_CL_PORT(unit, port) &&
    815                                 !IS_HG_PORT(unit, port) ? 1 : 0));
    816     /*
    817      * Set REMOTE_FAULT/LOCAL_FAULT for CL ports,
    818      * else HW Linkscan interrupt would be suppressed.
    819      */
    820     if (SOC_REG_IS_VALID(unit, CLPORT_FAULT_LINK_STATUSr)) {
    821         rval = 0;
    822         fault = speed <= 1000 ? 0 : 1;
    823 
    824         soc_reg_field_set(unit, CLPORT_FAULT_LINK_STATUSr, &rval,
    825                           REMOTE_FAULTf, fault);
    826         soc_reg_field_set(unit, CLPORT_FAULT_LINK_STATUSr, &rval,
    827                           LOCAL_FAULTf, fault);
    828         SOC_IF_ERROR_RETURN(WRITE_CLPORT_FAULT_LINK_STATUSr(unit,
    829                             port, rval));
    830     }
    831 
    832     /* Update port speed related setting in components other than MAC/SerDes*/
    833     SOC_IF_ERROR_RETURN(soc_port_speed_update(unit, port, speed));
    834 
    835     /*
    836      * Notify internal PHY driver of speed change in case it is being
    837      * used as pass-through to an external PHY.
    838      */
    839     if (!PHY_REPEATER(unit, port)) {
    840         SOC_IF_ERROR_RETURN
    841             (soc_phyctrl_notify(unit, port, phyEventSpeed, speed));
    842     }
    843 
    844     if (enable) {
    845         /* Re-enable transmitter and receiver */
    846         SOC_IF_ERROR_RETURN(mac_cl_enable_set(unit, port, 1));
    847     }
    848 
    849     /* Set Timestamp Mac Delays */
    850     SOC_IF_ERROR_RETURN(_mac_cl_timestamp_delay_set(unit, port, speed));
    851 
    852     return SOC_E_NONE;
    853 }
    854 
    855 /*
    856  * Function:
    857  *      mac_cl_speed_get
    858  * Purpose:
    859  *      Get CLMAC speed
    860  * Parameters:
    861  *      unit - XGS unit #.
    862  *      port - XGS port # on unit.
    863  *      speed - (OUT) speed in Mb
    864  * Returns:
    865  *      SOC_E_XXX
    866  */
    867 STATIC int
    868 mac_cl_speed_get(int unit, soc_port_t port, int *speed)
    869 {
    870     uint64 rval64;
    871     soc_error_t rc;
    872 
    873     SOC_IF_ERROR_RETURN(READ_CLMAC_MODEr(unit, port, &rval64));
    874     switch (soc_reg64_field32_get(unit, CLMAC_MODEr, rval64, SPEED_MODEf)) {
    875     case SOC_CLMAC_SPEED_1000:
    876         *speed = 1000;
    877         break;
    878     case SOC_CLMAC_SPEED_100000:
    879     default:
    880         /* Obtain fine grained port speed, since
    881          * SOC_CLMAC_SPEED_1000000 implies >= 10Gbps
    882          */
    883         rc = soc_granular_speed_get(unit, port, speed);
    884         if (SOC_FAILURE(rc)) {
    885             /* Error determining speed, set default value */
    886             *speed = 100000;
    887         }
    888         break;
    889     }
    890 
    891     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    892                 (BSL_META_U(unit,
    893                             "mac_cl_speed_get: unit %d port %s speed=%dMb\n"),
    894                             unit, SOC_PORT_NAME(unit, port),
    895                             *speed));
    896     return SOC_E_NONE;
    897 }
    898 
    899 /*
    900  * Function:
    901  *      mac_cl_loopback_set
    902  * Purpose:
    903  *      Set a CLMAC into/out-of loopback mode
    904  * Parameters:
    905  *      unit - XGS unit #.
    906  *      port - XGS unit # on unit.
    907  *      loopback - Boolean: true -> loopback mode, false -> normal operation
    908  * Note:
    909  *      On Clmac, when setting loopback, we enable the TX/RX function also.
    910  *      Note that to test the PHY, we use the remote loopback facility.
    911  * Returns:
    912  *      SOC_E_XXX
    913  */
    914 STATIC int
    915 mac_cl_loopback_set(int unit, soc_port_t port, int lb)
    916 {
    917     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    918                 (BSL_META_U(unit,
    919                             "mac_cl_loopback_set: unit %d port %s loopback=%s\n"),
    920                             unit, SOC_PORT_NAME(unit, port),
    921                             lb ? "local" : "no"));
    922 
    923     /* need to enable clock compensation for applicable serdes device */
    924     (void)soc_phyctrl_notify(unit, port, phyEventMacLoopback, lb? 1: 0);
    925 
    926     return soc_reg_field32_modify(unit, CLMAC_CTRLr, port, LOCAL_LPBKf,
    927                                   lb ? 1 : 0);
    928 
    929     return SOC_E_NONE;
    930 }
    931 
    932 /*
    933  * Function:
    934  *      mac_cl_loopback_get
    935  * Purpose:
    936  *      Get current CLMAC loopback mode setting.
    937  * Parameters:
    938  *      unit - XGS unit #.
    939  *      port - XGS port # on unit.
    940  *      loopback - (OUT) Boolean: true = loopback, false = normal
    941  * Returns:
    942  *      SOC_E_XXX
    943  */
    944 STATIC int
    945 mac_cl_loopback_get(int unit, soc_port_t port, int *lb)
    946 {
    947     uint64 ctrl;
    948 
    949     SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl));
    950 
    951     *lb = soc_reg64_field32_get(unit, CLMAC_CTRLr, ctrl, LOCAL_LPBKf);
    952 
    953     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    954                 (BSL_META_U(unit,
    955                             "mac_cl_loopback_get: unit %d port %s loopback=%s\n"),
    956                             unit, SOC_PORT_NAME(unit, port),
    957                             *lb ? "local" : "no"));
    958     return SOC_E_NONE;
    959 }
    960 
    961 /*
    962  * Function:
    963  *      mac_cl_pause_addr_set
    964  * Purpose:
    965  *      Configure PAUSE frame source address.
    966  * Parameters:
    967  *      unit - XGS unit #.
    968  *      port - XGS port # on unit.
    969  *      pause_mac - (OUT) MAC address used for pause transmission.
    970  * Returns:
    971  *      SOC_E_XXX
    972  */
    973 STATIC int
    974 mac_cl_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t mac)
    975 {
    976     static soc_field_t fields[2] = { SA_HIf, SA_LOf };
    977     uint32 values[2];
    978 
    979     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    980                 (BSL_META_U(unit,
    981                             "mac_cl_pause_addr_set: unit %d port %s MAC=<"
    982                             "%02x:%02x:%02x:%02x:%02x:%02x>\n"),
    983                             unit, SOC_PORT_NAME(unit, port),
    984                             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
    985 
    986     values[0] = (mac[0] << 8) | mac[1];
    987     values[1] = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
    988 
    989     SOC_IF_ERROR_RETURN
    990         (soc_reg_fields32_modify(unit, CLMAC_TX_MAC_SAr, port, 2, fields,
    991                                  values));
    992     SOC_IF_ERROR_RETURN
    993         (soc_reg_fields32_modify(unit, CLMAC_RX_MAC_SAr, port, 2, fields,
    994                                  values));
    995 
    996     return SOC_E_NONE;
    997 }
    998 
    999 /*
   1000  * Function:
   1001  *      mac_cl_pause_addr_get
   1002  * Purpose:
   1003  *      Retrieve PAUSE frame source address.
   1004  * Parameters:
   1005  *      unit - XGS unit #.
   1006  *      port - XGS port # on unit.
   1007  *      pause_mac - (OUT) MAC address used for pause transmission.
   1008  * Returns:
   1009  *      SOC_E_XXX
   1010  * NOTE: We always write the same thing to TX & RX SA
   1011  *       so, we just return the contects on RX_MAC_SA.
   1012  */
   1013 STATIC int
   1014 mac_cl_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t mac)
   1015 {
   1016     uint64 rval64;
   1017     uint32 values[2];
   1018 
   1019     SOC_IF_ERROR_RETURN(READ_CLMAC_RX_MAC_SAr(unit, port, &rval64));
   1020     values[0] = soc_reg64_field32_get(unit, CLMAC_RX_MAC_SAr, rval64, SA_HIf);
   1021     values[1] = soc_reg64_field32_get(unit, CLMAC_RX_MAC_SAr, rval64, SA_LOf);
   1022 
   1023     mac[0] = (values[0] & 0x0000ff00) >> 8;
   1024     mac[1] = values[0] & 0x000000ff;
   1025     mac[2] = (values[1] & 0xff000000) >> 24;
   1026     mac[3] = (values[1] & 0x00ff0000) >> 16;
   1027     mac[4] = (values[1] & 0x0000ff00) >> 8;
   1028     mac[5] = values[1] & 0x000000ff;
   1029 
   1030     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1031                 (BSL_META_U(unit,
   1032                             "mac_cl_pause_addr_get: unit %d port %s MAC=<"
   1033                             "%02x:%02x:%02x:%02x:%02x:%02x>\n"),
   1034                             unit, SOC_PORT_NAME(unit, port),
   1035                             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
   1036     return SOC_E_NONE;
   1037 }
   1038 
   1039 /*
   1040  * Function:
   1041  *      mac_cl_interface_set
   1042  * Purpose:
   1043  *      Set a CLMAC interface type
   1044  * Parameters:
   1045  *      unit - XGS unit #.
   1046  *      port - XGS port # on unit.
   1047  *      pif - one of SOC_PORT_IF_*
   1048  * Returns:
   1049  *      SOC_E_NONE
   1050  *      SOC_E_UNAVAIL - requested mode not supported.
   1051  * Notes:
   1052  */
   1053 STATIC int
   1054 mac_cl_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   1055 {
   1056 #ifdef BROADCOM_DEBUG
   1057     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1058                 (BSL_META_U(unit,
   1059                             "mac_cl_interface_set: unit %d port %s interface=%s\n"),
   1060                             unit, SOC_PORT_NAME(unit, port),
   1061                             mac_cl_port_if_names[pif]));
   1062 #endif
   1063     return SOC_E_NONE;
   1064 }
   1065 
   1066 /*
   1067  * Function:
   1068  *      mac_cl_interface_get
   1069  * Purpose:
   1070  *      Retrieve CLMAC interface type
   1071  * Parameters:
   1072  *      unit - XGS unit #.
   1073  *      port - XGS port # on unit.
   1074  *      pif - (OUT) one of SOC_PORT_IF_*
   1075  * Returns:
   1076  *      SOC_E_NONE
   1077  */
   1078 STATIC int
   1079 mac_cl_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   1080 {
   1081     COMPILER_REFERENCE(unit);
   1082     COMPILER_REFERENCE(port);
   1083 
   1084     *pif = SOC_PORT_IF_CGMII;
   1085 
   1086 #ifdef BROADCOM_DEBUG
   1087     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1088                 (BSL_META_U(unit,
   1089                             "mac_cl_interface_get: unit %d port %s interface=%s\n"),
   1090                              unit, SOC_PORT_NAME(unit, port),
   1091                              mac_cl_port_if_names[*pif]));
   1092 #endif
   1093     return SOC_E_NONE;
   1094 }
   1095 
   1096 /*
   1097  * Function:
   1098  *      mac_cl_frame_max_set
   1099  * Description:
   1100  *      Set the maximum receive frame size for the port
   1101  * Parameters:
   1102  *      unit - Device number
   1103  *      port - Port number
   1104  *      size - Maximum frame size in bytes
   1105  * Return Value:
   1106  *      BCM_E_XXX
   1107  */
   1108 STATIC int
   1109 mac_cl_frame_max_set(int unit, soc_port_t port, int size)
   1110 {
   1111     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1112                 (BSL_META_U(unit,
   1113                             "mac_cl_frame_max_set: unit %d port %s size=%d\n"),
   1114                             unit, SOC_PORT_NAME(unit, port),
   1115                             size));
   1116 
   1117     if (IS_CE_PORT(unit, port) || IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)) {
   1118         /* For VLAN tagged packets */
   1119         size += 4;
   1120     }
   1121     return soc_reg_field32_modify(unit, CLMAC_RX_MAX_SIZEr, port, RX_MAX_SIZEf,
   1122                                   size);
   1123 }
   1124 
   1125 /*
   1126  * Function:
   1127  *      mac_cl_frame_max_get
   1128  * Description:
   1129  *      Set the maximum receive frame size for the port
   1130  * Parameters:
   1131  *      unit - Device number
   1132  *      port - Port number
   1133  *      size - Maximum frame size in bytes
   1134  * Return Value:
   1135  *      BCM_E_XXX
   1136  */
   1137 STATIC int
   1138 mac_cl_frame_max_get(int unit, soc_port_t port, int *size)
   1139 {
   1140     uint64 rval;
   1141 
   1142     SOC_IF_ERROR_RETURN(READ_CLMAC_RX_MAX_SIZEr(unit, port, &rval));
   1143     *size = soc_reg64_field32_get(unit, CLMAC_RX_MAX_SIZEr, rval, RX_MAX_SIZEf);
   1144     if (IS_CE_PORT(unit, port) || IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)) {
   1145         /* For VLAN tagged packets */
   1146         *size -= 4;
   1147     }
   1148 
   1149     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1150                 (BSL_META_U(unit,
   1151                             "mac_cl_frame_max_get: unit %d port %s size=%d\n"),
   1152                             unit, SOC_PORT_NAME(unit, port),
   1153                             *size));
   1154     return SOC_E_NONE;
   1155 }
   1156 
   1157 /*
   1158  * Function:
   1159  *      mac_cl_ifg_set
   1160  * Description:
   1161  *      Sets the new ifg (Inter-frame gap) value
   1162  * Parameters:
   1163  *      unit   - Device number
   1164  *      port   - Port number
   1165  *      speed  - the speed for which the IFG is being set
   1166  *      duplex - the duplex for which the IFG is being set
   1167  *      ifg - number of bits to use for average inter-frame gap
   1168  * Return Value:
   1169  *      BCM_E_XXX
   1170  * Notes:
   1171  *      The function makes sure the IFG value makes sense and updates the
   1172  *      IPG register in case the speed/duplex match the current settings
   1173  */
   1174 STATIC int
   1175 mac_cl_ifg_set(int unit, soc_port_t port, int speed,
   1176                 soc_port_duplex_t duplex, int ifg)
   1177 {
   1178     int         cur_speed;
   1179     int         cur_duplex;
   1180     int         real_ifg;
   1181     soc_ipg_t  *si = &SOC_PERSIST(unit)->ipg[port];
   1182     uint64      rval, orval;
   1183     soc_port_ability_t ability;
   1184     uint32      pa_flag;
   1185 
   1186     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1187                 (BSL_META_U(unit,
   1188                             "mac_cl_ifg_set: unit %d port %s speed=%dMb duplex=%s "
   1189                             "ifg=%d\n"),
   1190                             unit, SOC_PORT_NAME(unit, port),
   1191                             speed, duplex ? "True" : "False", ifg));
   1192 
   1193     pa_flag = SOC_PA_SPEED(speed); 
   1194     sal_memset(&ability, 0, sizeof(ability));
   1195     soc_mac_cl.md_ability_local_get(unit, port, &ability);
   1196     if (!(pa_flag & ability.speed_full_duplex)) {
   1197         return SOC_E_PARAM;
   1198     }
   1199 
   1200     /* Silently adjust the specified ifp bits to valid value */
   1201     /* valid value: 8 to 64 bytes (i.e. multiple of 8 bits) */
   1202     real_ifg = ifg < 64 ? 64 : (ifg > 512 ? 512 : (ifg + 7) & (0x7f << 3));
   1203 
   1204     if (IS_CE_PORT(unit, port) || IS_XE_PORT(unit, port)) {
   1205         si->fd_xe = real_ifg;
   1206     } else {
   1207         si->fd_hg = real_ifg;
   1208     }
   1209 
   1210     SOC_IF_ERROR_RETURN(mac_cl_duplex_get(unit, port, &cur_duplex));
   1211     SOC_IF_ERROR_RETURN(mac_cl_speed_get(unit, port, &cur_speed));
   1212 
   1213     /* CLMAC_MODE supports only 4 speeds with 4 being max as LINK_10G_PLUS */
   1214     /* Unlike the corresponding XLMAC function call, mac_cl_speed_get()
   1215      * returns a fine grained speed value when CLMAC_MODE.SPEEDf=LINK_10G_PLUS
   1216      * Hence the check below uses cur_speed >= 10000, unlike the
   1217      * cur_speed == 10000 check used in xlmac */
   1218     if ((speed >= 10000) && (cur_speed >= 10000)) {
   1219         cur_speed = speed;
   1220     }
   1221 
   1222     if (cur_speed == speed &&
   1223         cur_duplex == (duplex == SOC_PORT_DUPLEX_FULL ? TRUE : FALSE)) {
   1224         SOC_IF_ERROR_RETURN(READ_CLMAC_TX_CTRLr(unit, port, &rval));
   1225         orval = rval;
   1226         soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, AVERAGE_IPGf,
   1227                               real_ifg / 8);
   1228         if (COMPILER_64_NE(rval, orval)) {
   1229             SOC_IF_ERROR_RETURN(WRITE_CLMAC_TX_CTRLr(unit, port, rval));
   1230         }
   1231     }
   1232 
   1233     return SOC_E_NONE;
   1234 }
   1235 
   1236 /*
   1237  * Function:
   1238  *      mac_cl_ifg_get
   1239  * Description:
   1240  *      Sets the new ifg (Inter-frame gap) value
   1241  * Parameters:
   1242  *      unit   - Device number
   1243  *      port   - Port number
   1244  *      speed  - the speed for which the IFG is being set
   1245  *      duplex - the duplex for which the IFG is being set
   1246  *      size - Maximum frame size in bytes
   1247  * Return Value:
   1248  *      BCM_E_XXX
   1249  * Notes:
   1250  *      The function makes sure the IFG value makes sense and updates the
   1251  *      IPG register in case the speed/duplex match the current settings
   1252  */
   1253 STATIC int
   1254 mac_cl_ifg_get(int unit, soc_port_t port, int speed,
   1255                 soc_port_duplex_t duplex, int *ifg)
   1256 {
   1257     soc_ipg_t  *si = &SOC_PERSIST(unit)->ipg[port];
   1258     soc_port_ability_t ability;
   1259     uint32      pa_flag;
   1260 
   1261     if (!duplex) {
   1262         return SOC_E_PARAM;
   1263     }
   1264 
   1265     pa_flag = SOC_PA_SPEED(speed); 
   1266     sal_memset(&ability, 0, sizeof(ability));
   1267     soc_mac_cl.md_ability_local_get(unit, port, &ability);
   1268     if (!(pa_flag & ability.speed_full_duplex)) {
   1269         return SOC_E_PARAM;
   1270     }
   1271 
   1272     if (IS_CE_PORT(unit, port) || IS_XE_PORT(unit, port)) {
   1273         *ifg = si->fd_xe;
   1274     } else {
   1275         *ifg = si->fd_hg;
   1276     }
   1277 
   1278     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1279                 (BSL_META_U(unit,
   1280                             "mac_cl_ifg_get: unit %d port %s speed=%dMb duplex=%s "
   1281                             "ifg=%d\n"),
   1282                             unit, SOC_PORT_NAME(unit, port),
   1283                             speed, duplex ? "True" : "False", *ifg));
   1284     return SOC_E_NONE;
   1285 }
   1286 
   1287 /*
   1288  * Function:
   1289  *      _mac_cl_port_mode_update
   1290  * Purpose:
   1291  *      Set the CLMAC port encapsulation mode.
   1292  * Parameters:
   1293  *      unit - XGS unit #.
   1294  *      port - XGS port # on unit.
   1295  *      hg_mode - SOC HG encap modes. value={HG/HG2/HG2-LITE}
   1296  * Returns:
   1297  *      SOC_E_XXX
   1298  */
   1299 STATIC int
   1300 _mac_cl_port_mode_update(int unit, soc_port_t port, int hg_mode)
   1301 {
   1302     uint32              rval;
   1303     uint64              val64, rval64, ctrl;
   1304     soc_pbmp_t          ctr_pbmp;
   1305     int                 speed = 0;
   1306     int                 rv = SOC_E_NONE;
   1307     int                 to_hg_port = 0 ;
   1308     int                 phy_enable = 0;
   1309     int                 encap_mode = 0;
   1310     int                 en_able = 0;
   1311 
   1312     /* The current encap mode */
   1313     SOC_IF_ERROR_RETURN(READ_CLMAC_MODEr(unit, port, &rval64));
   1314     encap_mode = soc_reg64_field32_get(unit, CLMAC_MODEr, rval64, HDR_MODEf);
   1315 
   1316     /* The current port enable status */
   1317     SOC_IF_ERROR_RETURN(mac_cl_enable_get(unit, port, &en_able));
   1318 
   1319     /* Pause linkscan */
   1320     soc_linkscan_pause(unit);
   1321 
   1322     /* Pause counter collection */
   1323     COUNTER_LOCK(unit);
   1324 
   1325     /* for original hg_mode parameter is at value={TRUE|FALSE} */
   1326     to_hg_port = (hg_mode != SOC_ENCAP_IEEE) ? TRUE : FALSE;
   1327     if (soc_feature(unit, soc_feature_hg2_light_in_portmacro)) {
   1328         soc_xport_type_mode_update(unit, port, hg_mode);
   1329     } else {
   1330         soc_xport_type_update(unit, port, to_hg_port);
   1331     }
   1332 
   1333     if (to_hg_port) {
   1334         SOC_IF_ERROR_RETURN(soc_port_hg_speed_get(unit, port, &speed));
   1335         SOC_IF_ERROR_RETURN(soc_phyctrl_set_speed_max(unit, port, speed));
   1336     } else {
   1337         speed = SOC_INFO(unit).port_init_speed[port];
   1338 #ifdef BCM_TOMAHAWK_SUPPORT
   1339         if (SOC_IS_TOMAHAWKX(unit)) {
   1340             SOC_IF_ERROR_RETURN(soc_th_port_ie_speed_get(unit, port, &speed));
   1341         }
   1342 #endif
   1343         SOC_IF_ERROR_RETURN(soc_phyctrl_set_speed_max(unit, port, speed));
   1344     }
   1345     rv = soc_phyctrl_enable_get(unit, port, &phy_enable);
   1346 
   1347     if (SOC_SUCCESS(rv)) {
   1348         rv = soc_phyctrl_init(unit, port);
   1349     }
   1350 
   1351     if (soc_feature(unit, soc_feature_port_enable_encap_restore)){
   1352         if (SOC_SUCCESS(rv)) {
   1353             rv = soc_phyctrl_enable_set(unit, port, phy_enable);
   1354         }
   1355     }
   1356 
   1357     if (SOC_SUCCESS(rv)) {
   1358         rv = mac_cl_init(unit, port);
   1359     } else {
   1360         goto  _failed;
   1361     }
   1362 
   1363     if (SOC_SUCCESS(rv)) {
   1364         if (soc_feature(unit, soc_feature_disable_rx_on_port) && (0 == en_able)) {
   1365             SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl));
   1366             /* Enable MAC TX if CPU sends packet out */
   1367             soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, TX_ENf, 1);
   1368             /* Disable MAC RX */
   1369             soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, RX_ENf, 0);
   1370             /* Put port into SOFT_RESET */
   1371             soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 1);
   1372             SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl));
   1373         } else {
   1374             rv = mac_cl_enable_set(unit, port, 0);
   1375         }
   1376     } else {
   1377         goto _failed;
   1378     }
   1379 
   1380     if (SOC_SUCCESS(rv)) {
   1381         SOC_PBMP_CLEAR(ctr_pbmp);
   1382         SOC_PBMP_PORT_SET(ctr_pbmp, port);
   1383         COMPILER_64_SET(val64, 0, 0);
   1384         rv = soc_counter_set_by_port(unit, ctr_pbmp, val64);
   1385     } else {
   1386         goto _failed;
   1387     }
   1388 
   1389     COUNTER_UNLOCK(unit);
   1390     soc_linkscan_continue(unit);
   1391     rval = 0;
   1392     
   1393     if (SOC_REG_IS_VALID(unit, CLPORT_CONFIGr)) {
   1394 
   1395     SOC_IF_ERROR_RETURN(READ_CLPORT_CONFIGr(unit, port, &rval));
   1396 #ifdef BCM_GREYHOUND2_SUPPORT
   1397         if (SOC_IS_GREYHOUND2(unit)) {
   1398             uint32  clp_hg_mode;
   1399 
   1400             /*
   1401              * CLPORT and PGW register
   1402              *  - for HIGIG_MODEf :
   1403              *    will be '1' for HG/HG+ setting only and '0' for other
   1404              *    encap modes{IEEE/HG2/HG2-LITE}
   1405              *  - for HGIGIG2_MODEf :
   1406              *    will be 1 for HG2 and will be 0 for other
   1407              *    encap modes{IEEE/HG/HG+/HG2-LITE}
   1408              */
   1409             clp_hg_mode = (hg_mode == SOC_ENCAP_HIGIG) ? 1 : 0;
   1410             SOC_IF_ERROR_RETURN
   1411                     (soc_greyhound2_pgw_encap_field_modify(unit, port,
   1412                                                            HIGIG_MODEf,
   1413                                                            clp_hg_mode));
   1414 
   1415             soc_reg_field_set(unit, CLPORT_CONFIGr, &rval, HIGIG_MODEf,
   1416                               clp_hg_mode);
   1417 
   1418             clp_hg_mode = (hg_mode == SOC_ENCAP_HIGIG2) ? 1 : 0;
   1419             soc_reg_field_set(unit, CLPORT_CONFIGr, &rval, HIGIG2_MODEf,
   1420                               clp_hg_mode);
   1421         } else 
   1422 #endif  /* GREYHOUND2 */
   1423         {
   1424     soc_reg_field_set(unit, CLPORT_CONFIGr, &rval, HIGIG2_MODEf,
   1425                       to_hg_port);
   1426         }
   1427 
   1428     SOC_IF_ERROR_RETURN(WRITE_CLPORT_CONFIGr(unit, port, rval));
   1429     }
   1430 
   1431 _failed:
   1432     if (SOC_FAILURE(rv)) {
   1433         COUNTER_UNLOCK(unit);
   1434         soc_linkscan_continue(unit);
   1435         if (soc_feature(unit, soc_feature_hg2_light_in_portmacro)) {
   1436             soc_xport_type_mode_update(unit, port, encap_mode);
   1437         } else {
   1438             soc_xport_type_update(unit, port, encap_mode);
   1439         }
   1440         SOC_IF_ERROR_RETURN(READ_CLMAC_MODEr(unit, port, &rval64));
   1441         soc_reg64_field32_set(unit, CLMAC_MODEr, &rval64, HDR_MODEf, encap_mode);
   1442         SOC_IF_ERROR_RETURN(WRITE_CLMAC_MODEr(unit, port, rval64));
   1443     }
   1444 
   1445     return rv;
   1446 }
   1447 
   1448 /*
   1449  * Function:
   1450  *      mac_cl_encap_set
   1451  * Purpose:
   1452  *      Set the CLMAC port encapsulation mode.
   1453  * Parameters:
   1454  *      unit - XGS unit #.
   1455  *      port - XGS port # on unit.
   1456  *      mode - (IN) encap bits (defined above)
   1457  * Returns:
   1458  *      SOC_E_XXX
   1459  */
   1460 STATIC int
   1461 mac_cl_encap_set(int unit, soc_port_t port, int mode)
   1462 {
   1463     int enable, encap, rv = SOC_E_NONE;
   1464     int runt;
   1465 
   1466 #ifdef BROADCOM_DEBUG
   1467     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1468                 (BSL_META_U(unit,
   1469                             "mac_cl_encap_set: unit %d port %s encapsulation=%s\n"),
   1470                             unit, SOC_PORT_NAME(unit, port),
   1471                             mac_cl_encap_mode[mode]));
   1472 #endif
   1473 
   1474     switch (mode) {
   1475     case SOC_ENCAP_IEEE:
   1476     case SOC_ENCAP_HIGIG2_LITE:
   1477         encap = 0;
   1478         break;
   1479     case SOC_ENCAP_HIGIG:
   1480         encap = 1;
   1481         break;
   1482     case SOC_ENCAP_HIGIG2:
   1483         encap = 2;
   1484         break;
   1485     default:
   1486         return SOC_E_PARAM;
   1487     }
   1488 
   1489     if (!soc_feature(unit, soc_feature_xport_convertible)) {
   1490         if ((IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) ||
   1491             (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE)) {
   1492             return SOC_E_PARAM;
   1493         }
   1494     }
   1495 
   1496     SOC_IF_ERROR_RETURN(mac_cl_enable_get(unit, port, &enable));
   1497     if (enable) {
   1498         /* Turn off TX/RX enable */
   1499         SOC_IF_ERROR_RETURN(mac_cl_enable_set(unit, port, 0));
   1500     }
   1501 
   1502     if (soc_feature(unit, soc_feature_hg2_light_in_portmacro)) {
   1503         /* mode update for all encap mode change! */
   1504         SOC_IF_ERROR_RETURN(_mac_cl_port_mode_update(unit, port, mode));
   1505     } else if ((IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) || 
   1506             (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE)) {
   1507         /* IEEE -> HG or HG -> IEEE */
   1508         SOC_IF_ERROR_RETURN(_mac_cl_port_mode_update(unit, port, mode));
   1509     }
   1510     
   1511     /* Update the encapsulation mode */
   1512     rv = soc_reg_field32_modify(unit, CLMAC_MODEr, port, HDR_MODEf, encap);
   1513 
   1514     runt = (mode == SOC_ENCAP_HIGIG2) ? CLMAC_RUNT_THRESHOLD_HG2 :
   1515            ((mode == SOC_ENCAP_HIGIG) ? CLMAC_RUNT_THRESHOLD_HG1 :
   1516                                         CLMAC_RUNT_THRESHOLD_IEEE);
   1517         SOC_IF_ERROR_RETURN
   1518             (soc_reg_field32_modify(unit, CLMAC_RX_CTRLr, port, RUNT_THRESHOLDf, runt));
   1519     
   1520     SOC_IF_ERROR_RETURN
   1521         (soc_reg_field32_modify(unit, CLMAC_RX_CTRLr, port, STRICT_PREAMBLEf,
   1522                                 mode == SOC_ENCAP_IEEE ? 1 : 0));
   1523 
   1524         if (enable) {
   1525             /* Re-enable transmitter and receiver */
   1526             SOC_IF_ERROR_RETURN(mac_cl_enable_set(unit, port, 1));
   1527         }
   1528 
   1529     return rv;
   1530 }
   1531 
   1532 /*
   1533  * Function:
   1534  *      mac_cl_encap_get
   1535  * Purpose:
   1536  *      Get the CLMAC port encapsulation mode.
   1537  * Parameters:
   1538  *      unit - XGS unit #.
   1539  *      port - XGS port # on unit.
   1540  *      mode - (INT) encap bits (defined above)
   1541  * Returns:
   1542  *      SOC_E_XXX
   1543  */
   1544 STATIC int
   1545 mac_cl_encap_get(int unit, soc_port_t port, int *mode)
   1546 {
   1547     uint64 rval;
   1548 
   1549     if (!mode) {
   1550         return SOC_E_PARAM;
   1551     }
   1552 
   1553     SOC_IF_ERROR_RETURN(READ_CLMAC_MODEr(unit, port, &rval));
   1554     switch (soc_reg64_field32_get(unit, CLMAC_MODEr, rval, HDR_MODEf)) {
   1555     case 0:
   1556         *mode = SOC_ENCAP_IEEE;
   1557         break;
   1558     case 1:
   1559         *mode = SOC_ENCAP_HIGIG;
   1560         break;
   1561     case 2:
   1562         *mode = SOC_ENCAP_HIGIG2;
   1563         break;
   1564     default:
   1565         *mode = SOC_ENCAP_COUNT;
   1566     }
   1567 
   1568 #ifdef BROADCOM_DEBUG
   1569     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1570                 (BSL_META_U(unit,
   1571                             "mac_cl_encap_get: unit %d port %s encapsulation=%s\n"),
   1572                             unit, SOC_PORT_NAME(unit, port),
   1573                             mac_cl_encap_mode[*mode]));
   1574 #endif
   1575     return SOC_E_NONE;
   1576 }
   1577 
   1578 /*
   1579  * Function:
   1580  *      mac_cl_expected_rx_latency_get
   1581  * Purpose:
   1582  *      Get the CLMAC port expected Rx latency
   1583  * Parameters:
   1584  *      unit - XGS unit #.
   1585  *      port - XGS port # on unit.
   1586  *      latency - (OUT) Latency in NS
   1587  * Returns:
   1588  *      SOC_E_XXX
   1589  */
   1590 STATIC int
   1591 mac_cl_expected_rx_latency_get(int unit, soc_port_t port, int *latency)
   1592 {
   1593     int speed = 0;
   1594     SOC_IF_ERROR_RETURN(mac_cl_speed_get(unit, port, &speed));
   1595 
   1596     
   1597     switch (speed) {
   1598     case 1000:  /* GigE */
   1599         *latency = 0;
   1600         break;
   1601 
   1602     case 10000:  /* 10G */
   1603         *latency = 0;
   1604         break;
   1605 
   1606     default:
   1607         *latency = 0;
   1608         break;
   1609     }
   1610 
   1611     return SOC_E_NONE;
   1612 }
   1613 
   1614 /*
   1615  * Function:
   1616  *      mac_cl_control_set
   1617  * Purpose:
   1618  *      To configure MAC control properties.
   1619  * Parameters:
   1620  *      unit - XGS unit #.
   1621  *      port - XGS port # on unit.
   1622  *      type - MAC control property to set.
   1623  *      int  - New setting for MAC control.
   1624  * Returns:
   1625  *      SOC_E_XXX
   1626  */
   1627 STATIC int
   1628 mac_cl_control_set(int unit, soc_port_t port, soc_mac_control_t type,
   1629                   int value)
   1630 {
   1631     uint64 rval, copy;
   1632     uint32 fval;
   1633     int    ver;
   1634 
   1635     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1636                 (BSL_META_U(unit,
   1637                             "mac_cl_control_set: unit %d port %s type=%d value=%d\n"),
   1638                             unit, SOC_PORT_NAME(unit, port),
   1639                             type, value));
   1640 
   1641     switch (type) {
   1642     case SOC_MAC_CONTROL_RX_SET:
   1643         SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &rval));
   1644         copy = rval;
   1645         soc_reg64_field32_set(unit, CLMAC_CTRLr, &rval, RX_ENf, value ? 1 : 0);
   1646         if (COMPILER_64_NE(rval, copy)) {
   1647             SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, rval));
   1648         }    
   1649         break;
   1650     case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH:
   1651         if (value < 0 || value > CLMAC_THROT_10G_TO_2P5G) {
   1652             return SOC_E_PARAM;
   1653         } else {
   1654             SOC_IF_ERROR_RETURN(READ_CLMAC_TX_CTRLr(unit, port, &rval));
   1655             if (value == CLMAC_THROT_10G_TO_5G) {
   1656                 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_DENOMf, 21);
   1657                 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_NUMf, 21);
   1658             } else if (value == CLMAC_THROT_10G_TO_2P5G) {
   1659                 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_DENOMf, 21);
   1660                 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_NUMf, 63);
   1661             } else if (value >= 8) {
   1662                 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_DENOMf,
   1663                                       value);
   1664                 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_NUMf,
   1665                                       1);
   1666             } else {
   1667                 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_DENOMf,
   1668                                       0);
   1669                 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_NUMf,
   1670                                       0);
   1671             }
   1672             SOC_IF_ERROR_RETURN(WRITE_CLMAC_TX_CTRLr(unit, port, rval));
   1673         }
   1674         return SOC_E_NONE;
   1675 
   1676     case SOC_MAC_PASS_CONTROL_FRAME:
   1677         SOC_IF_ERROR_RETURN(_clmac_gen_version_get(unit, port, &ver));
   1678         if (ver == CLMAC_VERSION_A030) {
   1679             SOC_IF_ERROR_RETURN(READ_CLMAC_RX_CTRLr(unit, port, &rval));
   1680             soc_reg64_field32_set (unit, CLMAC_RX_CTRLr, &rval,
   1681                     RX_PASS_PAUSEf, (value? 1:0));
   1682             SOC_IF_ERROR_RETURN(WRITE_CLMAC_RX_CTRLr(unit, port, rval));
   1683         }
   1684         break;
   1685 
   1686     case SOC_MAC_CONTROL_PFC_TYPE:
   1687         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CLMAC_PFC_TYPEr, port,
   1688                                                    PFC_ETH_TYPEf, value));
   1689         break;
   1690 
   1691     case SOC_MAC_CONTROL_PFC_OPCODE:
   1692         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CLMAC_PFC_OPCODEr,
   1693                                                    port, PFC_OPCODEf, value));
   1694         break;
   1695 
   1696     case SOC_MAC_CONTROL_PFC_CLASSES:
   1697         if (value != 8) {
   1698             return SOC_E_PARAM;
   1699         }
   1700         break;
   1701 
   1702     case SOC_MAC_CONTROL_PFC_MAC_DA_OUI:
   1703         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_DAr(unit, port, &rval));
   1704         fval = soc_reg64_field32_get(unit, CLMAC_PFC_DAr, rval, PFC_MACDA_LOf);
   1705         fval &= 0x00ffffff;
   1706         fval |= (value & 0xff) << 24;
   1707         soc_reg64_field32_set(unit, CLMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval);
   1708 
   1709         soc_reg64_field32_set(unit, CLMAC_PFC_DAr, &rval, PFC_MACDA_HIf,
   1710                               value >> 8);
   1711         SOC_IF_ERROR_RETURN(WRITE_CLMAC_PFC_DAr(unit, port, rval));
   1712         break;
   1713 
   1714     case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI:
   1715         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_DAr(unit, port, &rval));
   1716         fval = soc_reg64_field32_get(unit, CLMAC_PFC_DAr, rval, PFC_MACDA_LOf);
   1717         fval &= 0xff000000;
   1718         fval |= value;
   1719         soc_reg64_field32_set(unit, CLMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval);
   1720         SOC_IF_ERROR_RETURN(WRITE_CLMAC_PFC_DAr(unit, port, rval));
   1721         break;
   1722 
   1723     case SOC_MAC_CONTROL_PFC_RX_PASS:
   1724         if (!SOC_REG_FIELD_VALID(unit, CLMAC_PFC_CTRLr, RX_PASS_PFCf)) {
   1725             return SOC_E_UNAVAIL;
   1726         }
   1727 
   1728         SOC_IF_ERROR_RETURN
   1729             (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, RX_PASS_PFCf,
   1730                                     value ? 1 : 0));
   1731         break;
   1732 
   1733     case SOC_MAC_CONTROL_PFC_RX_ENABLE:
   1734         SOC_IF_ERROR_RETURN
   1735             (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, RX_PFC_ENf,
   1736                                     value ? 1 : 0));
   1737         break;
   1738 
   1739     case SOC_MAC_CONTROL_PFC_TX_ENABLE:
   1740         SOC_IF_ERROR_RETURN
   1741             (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, TX_PFC_ENf,
   1742                                     value ? 1 : 0));
   1743         break;
   1744 
   1745     case SOC_MAC_CONTROL_PFC_FORCE_XON:
   1746         SOC_IF_ERROR_RETURN
   1747             (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, FORCE_PFC_XONf,
   1748                                     value ? 1 : 0));
   1749         break;
   1750 
   1751     case SOC_MAC_CONTROL_PFC_STATS_ENABLE:
   1752         SOC_IF_ERROR_RETURN
   1753             (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, PFC_STATS_ENf,
   1754                                     value ? 1 : 0));
   1755         break;
   1756 
   1757     case SOC_MAC_CONTROL_PFC_REFRESH_TIME:
   1758         SOC_IF_ERROR_RETURN
   1759             (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, 
   1760                                     PFC_REFRESH_TIMERf, value));
   1761         break;
   1762 
   1763     case SOC_MAC_CONTROL_PFC_XOFF_TIME:
   1764         SOC_IF_ERROR_RETURN
   1765             (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, 
   1766                                     PFC_XOFF_TIMERf, value));
   1767         break;
   1768 
   1769     case SOC_MAC_CONTROL_LLFC_RX_ENABLE:
   1770         SOC_IF_ERROR_RETURN
   1771             (soc_reg_field32_modify(unit, CLMAC_LLFC_CTRLr, port, RX_LLFC_ENf,
   1772                                     value ? 1 : 0));
   1773         
   1774         /* Feature check inside the soc_llfc_xon_set() should take care
   1775          * of devices supporting this functionality.
   1776          */
   1777         SOC_IF_ERROR_RETURN 
   1778             (soc_llfc_xon_set(unit, port, value ? 1 : 0));
   1779         break;
   1780     
   1781     case SOC_MAC_CONTROL_LLFC_TX_ENABLE:
   1782         SOC_IF_ERROR_RETURN
   1783             (soc_reg_field32_modify(unit, CLMAC_LLFC_CTRLr, port, TX_LLFC_ENf,
   1784                                     value ? 1 : 0));
   1785         break;
   1786 
   1787     case SOC_MAC_CONTROL_EEE_ENABLE:
   1788         if (!soc_feature(unit, soc_feature_eee)) {
   1789             return SOC_E_UNAVAIL;
   1790         }
   1791         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CLMAC_EEE_CTRLr, 
   1792                                                    port, EEE_ENf, value));
   1793         break;
   1794 
   1795     case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME:
   1796         if (!soc_feature(unit, soc_feature_eee)) {
   1797             return SOC_E_UNAVAIL;
   1798         }
   1799         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CLMAC_EEE_TIMERSr, 
   1800                                     port, EEE_DELAY_ENTRY_TIMERf, value));
   1801         break;
   1802 
   1803     case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME:
   1804         if (!soc_feature(unit, soc_feature_eee)) {
   1805             return SOC_E_UNAVAIL;
   1806         }
   1807         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CLMAC_EEE_TIMERSr, 
   1808                                     port, EEE_WAKE_TIMERf, value));
   1809         break;
   1810 
   1811     case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE:
   1812         SOC_IF_ERROR_RETURN
   1813             (soc_reg_field32_modify(unit, CLMAC_RX_LSS_CTRLr, port,
   1814                                     LOCAL_FAULT_DISABLEf, value ? 0 : 1));
   1815         break;
   1816 
   1817     case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE:
   1818         SOC_IF_ERROR_RETURN
   1819             (soc_reg_field32_modify(unit, CLMAC_RX_LSS_CTRLr, port,
   1820                                     REMOTE_FAULT_DISABLEf, value ? 0 : 1));
   1821         break;
   1822 
   1823     case SOC_MAC_CONTROL_EGRESS_DRAIN:
   1824         SOC_IF_ERROR_RETURN(mac_cl_egress_queue_drain(unit, port));
   1825         break;
   1826 
   1827     case SOC_MAC_CONTROL_FAILOVER_RX_SET:
   1828         break;
   1829 
   1830     default:
   1831         return SOC_E_UNAVAIL;
   1832     }
   1833 
   1834     return SOC_E_NONE;
   1835 }
   1836 
   1837 /*
   1838  * Function:
   1839  *      mac_cl_control_get
   1840  * Purpose:
   1841  *      To get current MAC control setting.
   1842  * Parameters:
   1843  *      unit - XGS unit #.
   1844  *      port - XGS port # on unit.
   1845  *      type - MAC control property to set.
   1846  *      int  - New setting for MAC control.
   1847  * Returns:
   1848  *      SOC_E_XXX
   1849  */
   1850 STATIC int
   1851 mac_cl_control_get(int unit, soc_port_t port, soc_mac_control_t type,
   1852                   int *value)
   1853 {
   1854     int rv;
   1855     uint64 rval;
   1856     uint32 fval0, fval1;
   1857     int    ver;
   1858 
   1859     if (value == NULL) {
   1860         return SOC_E_PARAM;
   1861     }
   1862 
   1863     rv = SOC_E_NONE;
   1864     switch (type) {
   1865     case SOC_MAC_CONTROL_RX_SET:
   1866         SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &rval));
   1867         *value = soc_reg64_field32_get(unit, CLMAC_CTRLr, rval, RX_ENf);
   1868         break;
   1869     case SOC_MAC_CONTROL_SW_RESET:
   1870         SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &rval));
   1871         *value = soc_reg64_field32_get(unit, CLMAC_CTRLr, rval, SOFT_RESETf);
   1872         break;
   1873     case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH:
   1874         SOC_IF_ERROR_RETURN(READ_CLMAC_TX_CTRLr(unit, port, &rval));
   1875         *value = soc_reg64_field32_get(unit, CLMAC_TX_CTRLr, rval,
   1876                                        THROT_DENOMf);
   1877         rv = SOC_E_NONE;
   1878         break;
   1879 
   1880     case SOC_MAC_CONTROL_TIMESTAMP_TRANSMIT:
   1881         {
   1882             uint32  timestamp = 0;
   1883             if (soc_feature(unit, soc_feature_timestamp_counter) &&
   1884                 soc_property_get(unit, spn_SW_TIMESTAMP_FIFO_ENABLE, 1)) {
   1885                 if (soc_counter_timestamp_get(unit, port, &timestamp) !=
   1886                     SOC_E_NOT_FOUND) {
   1887                     *value = (int)timestamp;
   1888                     break;
   1889                 }
   1890             }
   1891 
   1892         SOC_IF_ERROR_RETURN
   1893             (READ_CLMAC_TX_TIMESTAMP_FIFO_STATUSr(unit, port, &rval));
   1894         if (soc_reg64_field32_get(unit, CLMAC_TX_TIMESTAMP_FIFO_STATUSr, rval,
   1895                                   ENTRY_COUNTf) == 0) {
   1896             return SOC_E_EMPTY;
   1897         }
   1898         SOC_IF_ERROR_RETURN
   1899             (READ_CLMAC_TX_TIMESTAMP_FIFO_DATAr(unit, port, &rval));
   1900         *value = soc_reg64_field32_get(unit, CLMAC_TX_TIMESTAMP_FIFO_DATAr,
   1901                                        rval, TIME_STAMPf);
   1902         }
   1903         break;
   1904 
   1905     case SOC_MAC_PASS_CONTROL_FRAME:
   1906         *value = TRUE;
   1907         SOC_IF_ERROR_RETURN(_clmac_gen_version_get(unit, port, &ver));
   1908         if (ver == CLMAC_VERSION_A030) {
   1909             SOC_IF_ERROR_RETURN(READ_CLMAC_RX_CTRLr(unit, port, &rval));
   1910             *value = soc_reg64_field32_get(unit, CLMAC_RX_CTRLr, rval, RX_PASS_CTRLf);
   1911         }
   1912         break;
   1913 
   1914     case SOC_MAC_CONTROL_PFC_TYPE:
   1915         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_TYPEr(unit, port, &rval));
   1916         *value = soc_reg64_field32_get(unit, CLMAC_PFC_TYPEr, rval,
   1917                                        PFC_ETH_TYPEf);
   1918         break;
   1919 
   1920     case SOC_MAC_CONTROL_PFC_OPCODE:
   1921         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_OPCODEr(unit, port, &rval));
   1922         *value = soc_reg64_field32_get(unit, CLMAC_PFC_OPCODEr, rval,
   1923                                        PFC_OPCODEf);
   1924         break;
   1925 
   1926     case SOC_MAC_CONTROL_PFC_CLASSES:
   1927         *value = 8;
   1928         break;
   1929 
   1930     case SOC_MAC_CONTROL_PFC_MAC_DA_OUI:
   1931         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_DAr(unit, port, &rval));
   1932         fval0 = soc_reg64_field32_get(unit, CLMAC_PFC_DAr, rval, PFC_MACDA_LOf);
   1933         fval1 = soc_reg64_field32_get(unit, CLMAC_PFC_DAr, rval, PFC_MACDA_HIf);
   1934         *value = (fval0 >> 24) | (fval1 << 8);
   1935         break;
   1936 
   1937     case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI:
   1938         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_DAr(unit, port, &rval));
   1939         *value = soc_reg64_field32_get(unit, CLMAC_PFC_DAr, rval,
   1940                                        PFC_MACDA_LOf) & 0x00ffffff;
   1941         break;
   1942 
   1943     case SOC_MAC_CONTROL_PFC_RX_PASS:
   1944         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval));
   1945         *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval,
   1946                                        RX_PASS_PFCf);
   1947         break;
   1948 
   1949     case SOC_MAC_CONTROL_PFC_RX_ENABLE:
   1950         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval));
   1951         *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval,
   1952                                        RX_PFC_ENf);
   1953         break;
   1954 
   1955     case SOC_MAC_CONTROL_PFC_TX_ENABLE:
   1956         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval));
   1957         *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval,
   1958                                        TX_PFC_ENf);
   1959         break;
   1960 
   1961     case SOC_MAC_CONTROL_PFC_FORCE_XON:
   1962         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval));
   1963         *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval,
   1964                                        FORCE_PFC_XONf);
   1965         break;
   1966 
   1967     case SOC_MAC_CONTROL_PFC_STATS_ENABLE:
   1968         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval));
   1969         *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval,
   1970                                        PFC_STATS_ENf);
   1971         break;
   1972 
   1973     case SOC_MAC_CONTROL_PFC_REFRESH_TIME:
   1974         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval));
   1975         *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval,
   1976                                        PFC_REFRESH_TIMERf);
   1977         break;
   1978 
   1979     case SOC_MAC_CONTROL_PFC_XOFF_TIME:
   1980         SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval));
   1981         *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval,
   1982                                        PFC_XOFF_TIMERf);
   1983         break;
   1984 
   1985     case SOC_MAC_CONTROL_LLFC_RX_ENABLE:
   1986         SOC_IF_ERROR_RETURN(READ_CLMAC_LLFC_CTRLr(unit, port, &rval));
   1987         *value = soc_reg64_field32_get(unit, CLMAC_LLFC_CTRLr, rval,
   1988                                        RX_LLFC_ENf);
   1989         break;
   1990 
   1991     case SOC_MAC_CONTROL_LLFC_TX_ENABLE:
   1992         SOC_IF_ERROR_RETURN(READ_CLMAC_LLFC_CTRLr(unit, port, &rval));
   1993         *value = soc_reg64_field32_get(unit, CLMAC_LLFC_CTRLr, rval,
   1994                                        TX_LLFC_ENf);
   1995         break;
   1996 
   1997     case SOC_MAC_CONTROL_EEE_ENABLE:
   1998         if (!soc_feature(unit, soc_feature_eee)) {
   1999             return SOC_E_UNAVAIL;
   2000         }
   2001         if (!soc_reg_field_valid(unit, CLMAC_EEE_CTRLr, EEE_ENf)) {
   2002             return SOC_E_UNAVAIL;
   2003         }
   2004         SOC_IF_ERROR_RETURN(READ_CLMAC_EEE_CTRLr(unit, port, &rval));
   2005         *value = soc_reg64_field32_get(unit, CLMAC_EEE_CTRLr, rval, EEE_ENf);
   2006         break;
   2007 
   2008     case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME:
   2009         if (!soc_feature(unit, soc_feature_eee)) {
   2010             return SOC_E_UNAVAIL;
   2011         }
   2012         if (!soc_reg_field_valid(unit, CLMAC_EEE_TIMERSr, EEE_DELAY_ENTRY_TIMERf)) {
   2013             return SOC_E_UNAVAIL;
   2014         }
   2015         SOC_IF_ERROR_RETURN(READ_CLMAC_EEE_TIMERSr(unit, port, &rval));
   2016         *value = soc_reg64_field32_get(unit, CLMAC_EEE_TIMERSr, rval,
   2017                 EEE_DELAY_ENTRY_TIMERf);
   2018         break;
   2019 
   2020     case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME:
   2021         if (!soc_feature(unit, soc_feature_eee)) {
   2022             return SOC_E_UNAVAIL;
   2023         }
   2024         if (!soc_reg_field_valid(unit, CLMAC_EEE_TIMERSr, EEE_WAKE_TIMERf)) {
   2025             return SOC_E_UNAVAIL;
   2026         }
   2027         SOC_IF_ERROR_RETURN(READ_CLMAC_EEE_TIMERSr(unit, port, &rval));
   2028         *value = soc_reg64_field32_get(unit, CLMAC_EEE_TIMERSr, rval,
   2029                 EEE_WAKE_TIMERf);
   2030         break;
   2031 
   2032     case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE:
   2033         SOC_IF_ERROR_RETURN(READ_CLMAC_RX_LSS_CTRLr(unit, port, &rval));
   2034         *value = soc_reg64_field32_get(unit, CLMAC_RX_LSS_CTRLr, rval,
   2035                                        LOCAL_FAULT_DISABLEf) ? 0 : 1;
   2036         break;
   2037 
   2038     case SOC_MAC_CONTROL_FAULT_LOCAL_STATUS:
   2039         SOC_IF_ERROR_RETURN(READ_CLMAC_RX_LSS_STATUSr(unit, port, &rval));
   2040         *value = soc_reg64_field32_get(unit, CLMAC_RX_LSS_STATUSr, rval,
   2041                                        LOCAL_FAULT_STATUSf);
   2042         break;
   2043 
   2044     case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE:
   2045         SOC_IF_ERROR_RETURN(READ_CLMAC_RX_LSS_CTRLr(unit, port, &rval));
   2046         *value = soc_reg64_field32_get(unit, CLMAC_RX_LSS_CTRLr, rval,
   2047                                        REMOTE_FAULT_DISABLEf) ? 0 : 1;
   2048         break;
   2049 
   2050     case SOC_MAC_CONTROL_FAULT_REMOTE_STATUS:
   2051         SOC_IF_ERROR_RETURN(READ_CLMAC_RX_LSS_STATUSr(unit, port, &rval));
   2052         *value = soc_reg64_field32_get(unit, CLMAC_RX_LSS_STATUSr, rval,
   2053                                        REMOTE_FAULT_STATUSf);
   2054         break;
   2055     case SOC_MAC_CONTROL_EXPECTED_RX_LATENCY:
   2056         SOC_IF_ERROR_RETURN(mac_cl_expected_rx_latency_get(unit, port, value));
   2057         break;
   2058 
   2059     default:
   2060         return SOC_E_UNAVAIL;
   2061     }
   2062 
   2063     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2064                 (BSL_META_U(unit,
   2065                             "mac_cl_control_get: unit %d port %s type=%d value=%d "
   2066                             "rv=%d\n"),
   2067                             unit, SOC_PORT_NAME(unit, port),
   2068                             type, *value, rv));
   2069     return rv;
   2070 }
   2071 
   2072 /*
   2073  * Function:
   2074  *      mac_cl_ability_local_get
   2075  * Purpose:
   2076  *      Return the abilities of CLMAC
   2077  * Parameters:
   2078  *      unit - XGS unit #.
   2079  *      port - XGS port # on unit.
   2080  *      mode - (OUT) Supported operating modes as a mask of abilities.
   2081  * Returns:
   2082  *      SOC_E_XXX
   2083  */
   2084 STATIC int
   2085 mac_cl_ability_local_get(int unit, soc_port_t port,
   2086                           soc_port_ability_t *ability)
   2087 {
   2088     soc_info_t *si = &SOC_INFO(unit);
   2089     int port_speed_max, use_hg_port_speeds = FALSE;
   2090 
   2091     if (NULL == ability) {
   2092         return SOC_E_PARAM;
   2093     }
   2094 
   2095     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   2096     ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   2097     ability->interface = SOC_PA_INTF_MII | SOC_PA_INTF_XGMII;
   2098     ability->medium    = SOC_PA_ABILITY_NONE;
   2099     ability->loopback  = SOC_PA_LB_MAC;
   2100     ability->flags     = SOC_PA_ABILITY_NONE;
   2101     ability->encap = SOC_PA_ENCAP_IEEE | SOC_PA_ENCAP_HIGIG |
   2102         SOC_PA_ENCAP_HIGIG2;
   2103 
   2104     /*
   2105      * portmap_* config variables allow users to specifiy a HG speed as the max
   2106      * speed for a port that initializes as an ethernet port. This allows the user
   2107      * to optionally set the port speed to a HG speed after an encap change is
   2108      * performed. Under such situations allow HG speeds to be part of the MAC
   2109      * ability mask for the ethernet port.
   2110      */
   2111     if (soc_feature(unit, soc_feature_flexport_based_speed_set)) {
   2112         use_hg_port_speeds = TRUE;
   2113     }
   2114     /* Adjust port_speed_max according to the port config */
   2115     port_speed_max = si->port_speed_max[port];
   2116     /* Use current number of lanes per port to determine the supported speeds */
   2117     if (use_hg_port_speeds || IS_HG_PORT(unit , port)) {
   2118         switch (port_speed_max) {
   2119         case 127000:
   2120             ability->speed_full_duplex |= SOC_PA_SPEED_127GB;
   2121             /* fall through */
   2122         case 120000:
   2123             ability->speed_full_duplex |= SOC_PA_SPEED_120GB;
   2124             /* fall through */
   2125         case 106000:
   2126             if (si->port_num_lanes[port] == 4)  {
   2127                 ability->speed_full_duplex |= SOC_PA_SPEED_106GB;
   2128             }
   2129             /* fall through */
   2130         case 100000:
   2131             if (si->port_num_lanes[port] == 4)  {
   2132                 ability->speed_full_duplex |= SOC_PA_SPEED_100GB;
   2133             }
   2134             /* fall through */
   2135         case 53000:
   2136             if (si->port_num_lanes[port] == 2)  {
   2137                 ability->speed_full_duplex |= SOC_PA_SPEED_53GB;
   2138             }
   2139             /* fall through */
   2140         case 50000:
   2141             if (si->port_num_lanes[port] == 2)  {
   2142                 ability->speed_full_duplex |= SOC_PA_SPEED_50GB;
   2143             }
   2144             /* fall through */
   2145         case 42000:
   2146             if (si->port_num_lanes[port] != 1)  {
   2147                 ability->speed_full_duplex |= SOC_PA_SPEED_42GB;
   2148             }
   2149             /* fall through */
   2150         case 40000:
   2151             if (si->port_num_lanes[port] != 1)  {
   2152                 ability->speed_full_duplex |= SOC_PA_SPEED_40GB;
   2153                 if(soc_feature(unit, soc_feature_higig_misc_speed_support)) {
   2154                     ability->speed_full_duplex |= SOC_PA_SPEED_42GB;
   2155                 }
   2156             }
   2157             /* fall through */
   2158         case 30000:
   2159             if (!SOC_IS_TOMAHAWKX(unit)) {
   2160                 ability->speed_full_duplex |= SOC_PA_SPEED_30GB;
   2161             }
   2162             /* fall through */
   2163         case 27000:
   2164             if (si->port_num_lanes[port] == 1)  {
   2165                 ability->speed_full_duplex |= SOC_PA_SPEED_27GB;
   2166             }
   2167             /* fall through */
   2168         case 25000:
   2169             if (si->port_num_lanes[port] == 1)  {
   2170                 ability->speed_full_duplex |= SOC_PA_SPEED_25GB;
   2171             }
   2172             /* fall through */
   2173         case 21000:
   2174             if (si->port_num_lanes[port] == 2) {
   2175                 ability->speed_full_duplex |= SOC_PA_SPEED_21GB;
   2176             }
   2177             /* fall through */
   2178         case 20000:
   2179             if (si->port_num_lanes[port] == 2) {
   2180                 ability->speed_full_duplex |= SOC_PA_SPEED_20GB;
   2181             }
   2182             /* fall through */
   2183         case 16000: 
   2184             if (!SOC_IS_TOMAHAWKX(unit)) {
   2185                 ability->speed_full_duplex |= SOC_PA_SPEED_16GB;
   2186             }
   2187             /* fall through */
   2188         case 15000: 
   2189             if (!SOC_IS_TOMAHAWKX(unit)) {
   2190                 ability->speed_full_duplex |= SOC_PA_SPEED_15GB;
   2191             }
   2192             /* fall through */
   2193         case 13000: 
   2194             if (!SOC_IS_TOMAHAWKX(unit)) {
   2195                 ability->speed_full_duplex |= SOC_PA_SPEED_13GB;
   2196             }
   2197             /* fall through */
   2198         case 12000: 
   2199             if (!SOC_IS_TOMAHAWKX(unit)) {
   2200                 ability->speed_full_duplex |= SOC_PA_SPEED_12GB;
   2201             }
   2202             /* fall through */
   2203         case 11000:
   2204             if (si->port_num_lanes[port] == 1)  {
   2205                 ability->speed_full_duplex |= SOC_PA_SPEED_11GB;
   2206             }
   2207             /* fall through */
   2208         case 10000:
   2209             if (si->port_num_lanes[port] == 1)  {
   2210                 ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   2211             }
   2212             /* fall through */
   2213         case 1000:
   2214             if (si->port_num_lanes[port] == 1)  {
   2215                 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   2216             }
   2217             break;
   2218         default:
   2219             break;
   2220         }
   2221     } else {
   2222         switch (port_speed_max) {
   2223         case 106000:
   2224             ability->speed_full_duplex |= SOC_PA_SPEED_106GB;
   2225             /* fall through */
   2226         case 100000:
   2227             if (si->port_num_lanes[port] == 4)  {
   2228                 ability->speed_full_duplex |= SOC_PA_SPEED_100GB;
   2229             }
   2230             /* fall through */
   2231         case 53000:
   2232         case 50000:
   2233             if (si->port_num_lanes[port] == 2)  {
   2234                 ability->speed_full_duplex |= SOC_PA_SPEED_50GB;
   2235             }
   2236             /* fall through */
   2237         case 42000:
   2238         case 40000:
   2239 
   2240             if (si->port_num_lanes[port] != 1)  {
   2241                 ability->speed_full_duplex |= SOC_PA_SPEED_40GB;
   2242             }
   2243             /* fall through */
   2244         case 25000:
   2245             if (si->port_num_lanes[port] == 1)  {
   2246                 ability->speed_full_duplex |= SOC_PA_SPEED_25GB;
   2247             }
   2248             /* fall through */
   2249         case 21000:
   2250         case 20000:
   2251             if (si->port_num_lanes[port] == 2)  {
   2252                 ability->speed_full_duplex |= SOC_PA_SPEED_20GB;
   2253             }
   2254             /* fall through */
   2255         case 11000:
   2256         case 10000:
   2257             if (si->port_num_lanes[port] == 1)  {
   2258                 ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   2259             }
   2260             /* fall through */
   2261         case 1000:
   2262             if (si->port_num_lanes[port] == 1)  {
   2263                 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   2264             }
   2265         default:
   2266             break;
   2267         }
   2268     }
   2269 
   2270     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2271                 (BSL_META_U(unit,
   2272                             "mac_cl_ability_local_get: unit %d port %s "
   2273                             "speed_half=0x%x speed_full=0x%x encap=0x%x pause=0x%x "
   2274                             "interface=0x%x medium=0x%x loopback=0x%x flags=0x%x\n"),
   2275                             unit, SOC_PORT_NAME(unit, port),
   2276                             ability->speed_half_duplex, ability->speed_full_duplex,
   2277                             ability->encap, ability->pause, ability->interface,
   2278                             ability->medium, ability->loopback, ability->flags));
   2279     return SOC_E_NONE;
   2280 }
   2281 
   2282 static int
   2283 mac_cl_timesync_tx_info_get (int unit, soc_port_t port,
   2284                                         soc_port_timesync_tx_info_t *tx_info)
   2285 {
   2286     uint64 rval;
   2287 
   2288     SOC_IF_ERROR_RETURN
   2289         (READ_CLMAC_TX_TIMESTAMP_FIFO_STATUSr(unit, port, &rval));
   2290     if (soc_reg64_field32_get(unit, CLMAC_TX_TIMESTAMP_FIFO_STATUSr, rval,
   2291                               ENTRY_COUNTf) == 0) {
   2292         return SOC_E_EMPTY;
   2293     }
   2294 
   2295     SOC_IF_ERROR_RETURN
   2296         (READ_CLMAC_TX_TIMESTAMP_FIFO_DATAr(unit, port, &rval));
   2297     tx_info->timestamps_in_fifo = soc_reg64_field32_get(unit,
   2298                      CLMAC_TX_TIMESTAMP_FIFO_DATAr, rval, TIME_STAMPf);
   2299 
   2300     tx_info->timestamps_in_fifo_hi = 0;
   2301 
   2302     tx_info->sequence_id = soc_reg64_field32_get(unit,
   2303                      CLMAC_TX_TIMESTAMP_FIFO_DATAr, rval, SEQUENCE_IDf);
   2304 
   2305     return (SOC_E_NONE);
   2306 }
   2307 
   2308 
   2309 /* Exported CLMAC driver structure */
   2310 mac_driver_t soc_mac_cl = {
   2311     "CLMAC Driver",               /* drv_name */
   2312     mac_cl_init,                  /* md_init  */
   2313     mac_cl_enable_set,            /* md_enable_set */
   2314     mac_cl_enable_get,            /* md_enable_get */
   2315     mac_cl_duplex_set,            /* md_duplex_set */
   2316     mac_cl_duplex_get,            /* md_duplex_get */
   2317     mac_cl_speed_set,             /* md_speed_set */
   2318     mac_cl_speed_get,             /* md_speed_get */
   2319     mac_cl_pause_set,             /* md_pause_set */
   2320     mac_cl_pause_get,             /* md_pause_get */
   2321     mac_cl_pause_addr_set,        /* md_pause_addr_set */
   2322     mac_cl_pause_addr_get,        /* md_pause_addr_get */
   2323     mac_cl_loopback_set,          /* md_lb_set */
   2324     mac_cl_loopback_get,          /* md_lb_get */
   2325     mac_cl_interface_set,         /* md_interface_set */
   2326     mac_cl_interface_get,         /* md_interface_get */
   2327     NULL,                         /* md_ability_get - Deprecated */
   2328     mac_cl_frame_max_set,         /* md_frame_max_set */
   2329     mac_cl_frame_max_get,         /* md_frame_max_get */
   2330     mac_cl_ifg_set,               /* md_ifg_set */
   2331     mac_cl_ifg_get,               /* md_ifg_get */
   2332     mac_cl_encap_set,             /* md_encap_set */
   2333     mac_cl_encap_get,             /* md_encap_get */
   2334     mac_cl_control_set,           /* md_control_set */
   2335     mac_cl_control_get,           /* md_control_get */
   2336     mac_cl_ability_local_get,     /* md_ability_local_get */
   2337     mac_cl_timesync_tx_info_get   /* md_timesync_tx_info_get */
   2338  };
   2339 
   2340 #endif /* BCM_CLMAC_SUPPORT */