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

cmac.c (60228B)


      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  * CMAC driver
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <sal/core/libc.h>
     13 #include <shared/alloc.h>
     14 #include <sal/core/spl.h>
     15 #include <sal/core/boot.h>
     16 
     17 #include <soc/drv.h>
     18 #include <soc/error.h>
     19 #include <soc/cmic.h>
     20 #include <soc/portmode.h>
     21 #include <soc/ll.h>
     22 #include <soc/counter.h>
     23 #include <soc/macutil.h>
     24 #include <soc/phyctrl.h>
     25 
     26 #ifdef BCM_CMAC_SUPPORT
     27 
     28 /*
     29  * CMAC Register field definitions.
     30  */
     31 
     32 /* Transmit CRC Modes (Receive has bit field definitions in register) */
     33 #define CMAC_CRC_APPEND          0x00   /* Append CRC (Default) */
     34 #define CMAC_CRC_KEEP            0x01   /* CRC Assumed correct */
     35 #define CMAC_CRC_REGEN           0x02   /* Replace CRC with a new one */
     36 #define CMAC_CRC_PER_PKT_MODE    0x03   /* Update CRC based on h/w signal
     37                                            from port block */
     38 
     39 #define JUMBO_MAXSZ              0x3fe8 /* Max legal value (per regsfile) */
     40 
     41 /* 
     42  * CMAC timestamp delay definitions
     43  * From Katana/triumph3 spec, Timestamp clock period is 4ns (125Mhz) and 
     44  *                            Tx Line Clock period CMAC (341.8Mhz) is 2.9ns
     45  */
     46 #define CMAC_TX_LINE_RATE_NS   0x3
     47 
     48 
     49 mac_driver_t soc_mac_c;
     50 
     51 #ifdef BROADCOM_DEBUG
     52 static char *mac_c_encap_mode[] = SOC_ENCAP_MODE_NAMES_INITIALIZER;
     53 static char *mac_c_port_if_names[] = SOC_PORT_IF_NAMES_INITIALIZER;
     54 #endif /* BROADCOM_DEBUG */
     55 
     56 #define SOC_CMAC_SPEED_10     0x0
     57 #define SOC_CMAC_SPEED_100    0x1
     58 #define SOC_CMAC_SPEED_1000   0x2
     59 #define SOC_CMAC_SPEED_2500   0x3
     60 #define SOC_CMAC_SPEED_10000  0x4
     61 
     62 
     63 /* Forward declarations */
     64 STATIC int mac_c_loopback_set(int unit, soc_port_t port, int lb);
     65 STATIC int mac_c_loopback_get(int unit, soc_port_t port, int *lb);
     66 STATIC int mac_c_frame_max_set(int unit, soc_port_t port, int size);
     67 STATIC int mac_c_frame_max_get(int unit, soc_port_t port, int *size);
     68 STATIC int mac_c_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx);
     69 STATIC int mac_c_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx);
     70 
     71 STATIC int
     72 _mac_c_drain_cells(int unit, soc_port_t port)
     73 {
     74     int         rv;
     75     int         pause_tx, pause_rx, pfc_rx, llfc_rx;
     76 
     77     rv  = SOC_E_NONE;
     78 
     79     if (SOC_IS_RELOADING(unit)) {
     80         return rv;
     81     }
     82 
     83     /* Drain cells in mmu/port before cells entering TX FIFO */
     84     SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, TRUE));
     85 
     86     /* Disable pause/pfc/llfc function */
     87     SOC_IF_ERROR_RETURN
     88         (soc_mac_c.md_pause_get(unit, port, &pause_tx, &pause_rx));
     89     SOC_IF_ERROR_RETURN
     90         (soc_mac_c.md_pause_set(unit, port, pause_tx, 0));
     91 
     92     SOC_IF_ERROR_RETURN
     93         (soc_mac_c.md_control_get(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE,
     94                                   &pfc_rx));
     95     SOC_IF_ERROR_RETURN
     96         (soc_mac_c.md_control_set(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE,
     97                                   0));
     98 
     99     SOC_IF_ERROR_RETURN
    100         (soc_mac_c.md_control_get(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE,
    101                                   &llfc_rx));
    102     SOC_IF_ERROR_RETURN
    103         (soc_mac_c.md_control_set(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE,
    104                                   0));
    105 
    106     /* Drain data in TX FIFO without egressing */
    107     SOC_IF_ERROR_RETURN
    108         (soc_reg_field32_modify(unit, CMAC_TX_CTRLr, port, DISCARDf, 1));
    109 
    110     /* Notify PHY driver */
    111     SOC_IF_ERROR_RETURN
    112         (soc_phyctrl_notify(unit, port, phyEventStop, PHY_STOP_DRAIN));
    113 
    114     /* Wait until mmu cell count is 0 */
    115     rv = soc_egress_drain_cells(unit, port, 250000);
    116     if (SOC_E_NONE == rv) {
    117         /* Wait until TX fifo cell count is 0 */
    118         rv = soc_txfifo_drain_cells(unit, port, 250000);
    119     }
    120 
    121     /* Notify PHY driver */
    122     SOC_IF_ERROR_RETURN
    123         (soc_phyctrl_notify(unit, port, phyEventResume, PHY_STOP_DRAIN));
    124   
    125     /* Stop TX FIFO drainging */
    126     SOC_IF_ERROR_RETURN
    127         (soc_reg_field32_modify(unit, CMAC_TX_CTRLr, port, DISCARDf, 0));
    128 
    129     /* Restore original pause/pfc/llfc configuration */
    130     SOC_IF_ERROR_RETURN
    131         (soc_mac_c.md_pause_set(unit, port, pause_tx, pause_rx));
    132     SOC_IF_ERROR_RETURN
    133         (soc_mac_c.md_control_set(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE,
    134                                   pfc_rx));
    135     SOC_IF_ERROR_RETURN
    136         (soc_mac_c.md_control_set(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE,
    137                                   llfc_rx));
    138     
    139     /* Stop draining cells in mmu/port */
    140     SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, FALSE));
    141 
    142     return rv;
    143 }
    144 
    145 /*
    146  * Function:
    147  *      mac_c_init
    148  * Purpose:
    149  *      Initialize Cmac into a known good state.
    150  * Parameters:
    151  *      unit - XGS unit #.
    152  *      port - Port number on unit.
    153  * Returns:
    154  *      SOC_E_XXX
    155  * Notes:
    156  */
    157 STATIC int
    158 mac_c_init(int unit, soc_port_t port)
    159 {
    160     soc_info_t *si;
    161     soc_reg_t reg;
    162     uint64 mac_ctrl, rx_ctrl, tx_ctrl, rval;
    163     int ipg;
    164     int mode;
    165 
    166     LOG_VERBOSE(BSL_LS_SOC_100G,
    167                 (BSL_META_U(unit,
    168                             "mac_c_init: unit %d port %s\n"),
    169                  unit, SOC_PORT_NAME(unit, port)));
    170 
    171     si = &SOC_INFO(unit);
    172 
    173     /* Disable Tx/Rx, assume that MAC is stable (or out of reset) */
    174     SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &mac_ctrl));
    175     soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0);
    176     soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, RX_ENf, 0);
    177     soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, TX_ENf, 0);
    178     if (soc_reg_field_valid(unit, CMAC_CTRLr, XLGMII_ALIGN_ENBf)) {
    179                 
    180         if (IS_HG_PORT(unit, port) && (si->port_speed_max[port] >= 106000)) {
    181 
    182             soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, 
    183                                   XLGMII_ALIGN_ENBf, 0);
    184             
    185         } else {
    186             soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, 
    187                                   XLGMII_ALIGN_ENBf, 1);
    188         }
    189 
    190     }
    191     soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl,
    192                           XGMII_IPG_CHECK_DISABLEf,
    193                           IS_HG_PORT(unit, port) ? 1 : 0);
    194 
    195     SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, mac_ctrl));
    196 
    197     
    198     if (SOC_REG_IS_VALID(unit, CPORT_MAC_MODEr)) {
    199         reg = CPORT_MAC_MODEr;
    200     } else {
    201         reg = PORT_CMAC_MODEr;
    202     }
    203     SOC_IF_ERROR_RETURN
    204         (soc_reg_field32_modify(unit, reg, port, CGMII_MODEf,
    205                                 si->port_speed_max[port] > 106000 ? 1 : 0));
    206 
    207     SOC_IF_ERROR_RETURN(READ_CMAC_RX_CTRLr(unit, port, &rx_ctrl));
    208     soc_reg64_field32_set(unit, CMAC_RX_CTRLr, &rx_ctrl, STRIP_CRCf, 0);
    209     SOC_IF_ERROR_RETURN(WRITE_CMAC_RX_CTRLr(unit, port, rx_ctrl));
    210 
    211     SOC_IF_ERROR_RETURN(READ_CMAC_TX_CTRLr(unit, port, &tx_ctrl));
    212     ipg = IS_HG_PORT(unit,port)?  SOC_PERSIST(unit)->ipg[port].fd_hg:
    213                                   SOC_PERSIST(unit)->ipg[port].fd_xe;
    214     soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &tx_ctrl, AVERAGE_IPGf,
    215                           (ipg / 8) & 0x1f);
    216 
    217     soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf,
    218                           CMAC_CRC_PER_PKT_MODE);
    219 
    220     SOC_IF_ERROR_RETURN(WRITE_CMAC_TX_CTRLr(unit, port, tx_ctrl));
    221 
    222     if (IS_ST_PORT(unit, port)) {
    223         soc_mac_c.md_pause_set(unit, port, FALSE, FALSE);
    224     } else {
    225         soc_mac_c.md_pause_set(unit, port, TRUE, TRUE);
    226     }
    227 
    228     SOC_IF_ERROR_RETURN
    229         (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, PFC_REFRESH_ENf,
    230                                 1));
    231 
    232     if (soc_property_port_get(unit, port, spn_PHY_WAN_MODE, FALSE)) {
    233         /* Max speed for WAN mode is 9.294Gbps.
    234          * This setting gives 10Gbps * (13/14) or 9.286 Gbps */
    235         SOC_IF_ERROR_RETURN
    236             (soc_mac_c.md_control_set(unit, port,
    237                                       SOC_MAC_CONTROL_FRAME_SPACING_STRETCH,
    238                                       13));
    239     }
    240 
    241     /* Set jumbo max size (8000 byte payload) */
    242     COMPILER_64_ZERO(rval);
    243 #ifdef BCM_XGS_SUPPORT
    244     if (SOC_IS_XGS(unit)) {
    245         soc_reg64_field32_set(unit, CMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf,
    246                               SOC_INFO(unit).max_mtu);
    247     } else
    248 #endif
    249     {
    250         soc_reg64_field32_set(unit, CMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf,
    251                               JUMBO_MAXSZ);
    252     }
    253     SOC_IF_ERROR_RETURN(WRITE_CMAC_RX_MAX_SIZEr(unit, port, rval));
    254 
    255     /* Setup header mode, check for property for higig2 mode */
    256     COMPILER_64_ZERO(rval);
    257     if (IS_HG_PORT(unit, port)) {
    258         mode = soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE, 0) ?
    259             2 : 1;
    260         soc_reg64_field32_set(unit, CMAC_MODEr, &rval, HDR_MODEf, mode);
    261     }
    262     soc_reg64_field32_set(unit, CMAC_MODEr, &rval, SPEED_MODEf, SOC_CMAC_SPEED_10000);
    263     SOC_IF_ERROR_RETURN(WRITE_CMAC_MODEr(unit, port, rval));
    264 
    265     /* Disable loopback and bring CMAC out of reset */
    266     soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, CORE_REMOTE_LPBKf, 0);
    267     if (soc_reg_field_valid(unit, CMAC_CTRLr, LINE_REMOTE_LPBKf)) {
    268         soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, LINE_REMOTE_LPBKf,
    269                               0);
    270     }
    271     soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, CORE_LOCAL_LPBKf, 0);
    272     soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, LINE_LOCAL_LPBKf, 0);
    273     soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, RX_ENf, 1);
    274     soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, TX_ENf, 1);
    275     SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, mac_ctrl));
    276 
    277     return SOC_E_NONE;
    278 }
    279 
    280 /*
    281  * Function:
    282  *      mac_c_enable_set
    283  * Purpose:
    284  *      Enable or disable MAC
    285  * Parameters:
    286  *      unit - XGS unit #.
    287  *      port - Port number on unit.
    288  *      enable - TRUE to enable, FALSE to disable
    289  * Returns:
    290  *      SOC_E_XXX
    291  */
    292 STATIC int
    293 mac_c_enable_set(int unit, soc_port_t port, int enable)
    294 {
    295     uint64 ctrl, octrl;
    296     pbmp_t mask;
    297 
    298     LOG_VERBOSE(BSL_LS_SOC_100G,
    299                 (BSL_META_U(unit,
    300                             "mac_c_enable_set: unit %d port %s enable=%s\n"),
    301                  unit, SOC_PORT_NAME(unit, port),
    302                  enable ? "True" : "False"));
    303 
    304     SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &ctrl));
    305     octrl = ctrl;
    306     /* Don't disable TX since it stops egress and hangs if CPU sends */
    307     soc_reg64_field32_set(unit, CMAC_CTRLr, &ctrl, TX_ENf, 1);
    308     soc_reg64_field32_set(unit, CMAC_CTRLr, &ctrl, RX_ENf, enable ? 1 : 0);
    309     if (COMPILER_64_NE(ctrl, octrl)) {
    310         SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, ctrl));
    311         sal_udelay(10);
    312     }
    313 
    314     /* Put the CMAC in a soft reset state when disabled to allow packets to
    315      * drain from the TX FIFO */ 
    316     soc_reg64_field32_set(unit, CMAC_CTRLr, &ctrl, SOFT_RESETf,
    317                           enable ? 0 : 1); 
    318     if (COMPILER_64_NE(ctrl, octrl)) {
    319         SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, ctrl));
    320     }
    321 
    322     if (enable) {
    323         soc_link_mask2_get(unit, &mask);
    324         SOC_PBMP_PORT_ADD(mask, port);
    325         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    326         SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventResume,
    327                                                PHY_STOP_MAC_DIS));
    328     } else {
    329         soc_link_mask2_get(unit, &mask);
    330         SOC_PBMP_PORT_REMOVE(mask, port);
    331         SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask));
    332         SOC_IF_ERROR_RETURN(_mac_c_drain_cells(unit, port));
    333         SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventStop,
    334                                                PHY_STOP_MAC_DIS));
    335     }
    336 
    337     return SOC_E_NONE;
    338 }
    339 
    340 /*
    341  * Function:
    342  *      mac_c_enable_get
    343  * Purpose:
    344  *      Get MAC enable state
    345  * Parameters:
    346  *      unit - XGS unit #.
    347  *      port - Port number on unit.
    348  *      enable - (OUT) TRUE if enabled, FALSE if disabled
    349  * Returns:
    350  *      SOC_E_XXX
    351  */
    352 STATIC int
    353 mac_c_enable_get(int unit, soc_port_t port, int *enable)
    354 {
    355     uint64 ctrl;
    356 
    357     SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &ctrl));
    358 
    359     *enable = soc_reg64_field32_get(unit, CMAC_CTRLr, ctrl, RX_ENf);
    360 
    361     LOG_VERBOSE(BSL_LS_SOC_100G,
    362                 (BSL_META_U(unit,
    363                             "mac_c_enable_get: unit %d port %s enable=%s\n"),
    364                  unit, SOC_PORT_NAME(unit, port),
    365                  *enable ? "True" : "False"));
    366 
    367     return SOC_E_NONE;
    368 }
    369 
    370 /*
    371  * Function:
    372  *      _mac_c_timestamp_delay_set
    373  * Purpose:
    374  *      Set Timestamp delay for one-step to account for lane and pipeline delay.
    375  * Parameters:
    376  *      unit - XGS unit #.
    377  *      port - Port number on unit.
    378  * Returns:
    379  *      SOC_E_XXX
    380  */
    381 STATIC int
    382 _mac_c_timestamp_delay_set(int unit, soc_port_t port, int speed)
    383 {
    384     uint64 ctrl;
    385     int osts_delay, tsts_delay, conversion_delay;
    386     uint32 field;
    387 
    388     LOG_VERBOSE(BSL_LS_SOC_100G,
    389                 (BSL_META_U(unit,
    390                             "mac_c_timestamp_delay_set: unit %d port %s\n"),
    391                  unit, SOC_PORT_NAME(unit, port)));
    392 
    393     if (SOC_REG_IS_VALID(unit, CMAC_TIMESTAMP_ADJUSTr)) {
    394         SOC_IF_ERROR_RETURN(READ_CMAC_TIMESTAMP_ADJUSTr(unit, port, &ctrl));
    395 
    396         /*
    397          * CMAC pipeline delay is : ( as in CMAC specification)
    398          *          = (7.5 * TX line clock period) + (Timestamp clock period)
    399          */
    400         
    401         
    402         /* 2's complement signed value of pipeline delay in ns */
    403         osts_delay = soc_property_port_get(unit, port, spn_TIMESTAMP_ADJUST(speed),
    404                                            SOC_TIMESYNC_PLL_CLOCK_NS(unit) -
    405                                            ((15 * CMAC_TX_LINE_RATE_NS ) / 2));
    406 
    407         if (SOC_E_NONE != soc_reg_signed_field_mask(unit, CMAC_TIMESTAMP_ADJUSTr,
    408                               TS_OSTS_ADJUSTf, osts_delay, &field)) {
    409             LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit,
    410                 "%s property out of bounds (is %d)\n"),
    411                 spn_TIMESTAMP_ADJUST(speed), osts_delay));
    412             field = 0;
    413         }
    414 
    415         soc_reg64_field32_set(unit, CMAC_TIMESTAMP_ADJUSTr, &ctrl,
    416                               TS_OSTS_ADJUSTf, field);
    417 
    418         /* Note: TSTS delay uses same SOC property as OSTS delay, in order to allow
    419            specification based on platform.  However, the resulting timestamps in
    420            the FIFO are only used by the application, so the application can make
    421            other timestamp adjustments as required.
    422         */
    423         tsts_delay = soc_property_port_get(unit, port, spn_TIMESTAMP_ADJUST(speed),
    424                                            SOC_TIMESYNC_PLL_CLOCK_NS(unit) -
    425                                            ((5 * CMAC_TX_LINE_RATE_NS ) / 2));
    426 
    427         if (SOC_E_NONE != soc_reg_signed_field_mask(unit, CMAC_TIMESTAMP_ADJUSTr,
    428                                                     TS_TSTS_ADJUSTf, tsts_delay, &field)) {
    429             LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit,
    430                 "%s property out of bounds (is %d)\n"),
    431                 spn_TIMESTAMP_ADJUST(speed), tsts_delay));
    432             field = 0;
    433         }
    434 
    435         soc_reg64_field32_set(unit, CMAC_TIMESTAMP_ADJUSTr, &ctrl,
    436                               TS_TSTS_ADJUSTf, field);
    437 
    438         /* 5x mode delay for cmac: 1 * TX line clock period */
    439         conversion_delay = 1 * CMAC_TX_LINE_RATE_NS;
    440         soc_reg64_field32_set(unit, CMAC_TIMESTAMP_ADJUSTr, &ctrl,
    441                               TS_OSTS_ADJUST_CONVERSION_DELAYf, conversion_delay);
    442 
    443         SOC_IF_ERROR_RETURN(WRITE_CMAC_TIMESTAMP_ADJUSTr(unit, port, ctrl));
    444     }
    445 
    446     return SOC_E_NONE;
    447 }
    448 
    449 /*
    450  * Function:
    451  *      mac_c_duplex_set
    452  * Purpose:
    453  *      Set CMAC in the specified duplex mode.
    454  * Parameters:
    455  *      unit - XGS unit #.
    456  *      port - XGS port # on unit.
    457  *      duplex - Boolean: true --> full duplex, false --> half duplex.
    458  * Returns:
    459  *      SOC_E_XXX
    460  * Notes:
    461  */
    462 STATIC int
    463 mac_c_duplex_set(int unit, soc_port_t port, int duplex)
    464 {
    465     LOG_VERBOSE(BSL_LS_SOC_100G,
    466                 (BSL_META_U(unit,
    467                             "mac_c_duplex_set: unit %d port %s duplex=%s\n"),
    468                  unit, SOC_PORT_NAME(unit, port),
    469                  duplex ? "Full" : "Half"));
    470     return SOC_E_NONE;
    471 }
    472 
    473 /*
    474  * Function:
    475  *      mac_c_duplex_get
    476  * Purpose:
    477  *      Get CMAC duplex mode.
    478  * Parameters:
    479  *      unit - XGS unit #.
    480  *      duplex - (OUT) Boolean: true --> full duplex, false --> half duplex.
    481  * Returns:
    482  *      SOC_E_XXX
    483  */
    484 STATIC int
    485 mac_c_duplex_get(int unit, soc_port_t port, int *duplex)
    486 {
    487     *duplex = TRUE; /* Always full duplex */
    488 
    489     LOG_VERBOSE(BSL_LS_SOC_100G,
    490                 (BSL_META_U(unit,
    491                             "mac_c_duplex_get: unit %d port %s duplex=%s\n"),
    492                  unit, SOC_PORT_NAME(unit, port),
    493                  *duplex ? "Full" : "Half"));
    494     return SOC_E_NONE;
    495 }
    496 
    497 /*
    498  * Function:
    499  *      mac_c_pause_set
    500  * Purpose:
    501  *      Configure CMAC to transmit/receive pause frames.
    502  * Parameters:
    503  *      unit - XGS unit #.
    504  *      port - XGS port # on unit.
    505  *      pause_tx - Boolean: transmit pause or -1 (don't change)
    506  *      pause_rx - Boolean: receive pause or -1 (don't change)
    507  * Returns:
    508  *      SOC_E_XXX
    509  */
    510 STATIC int
    511 mac_c_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx)
    512 {
    513     soc_field_t fields[2] = { TX_PAUSE_ENf, RX_PAUSE_ENf };
    514     uint32 values[2];
    515 
    516     LOG_VERBOSE(BSL_LS_SOC_100G,
    517                 (BSL_META_U(unit,
    518                             "mac_c_pause_set: unit %d port %s TX=%s RX=%s\n"),
    519                  unit, SOC_PORT_NAME(unit, port),
    520                  pause_tx != FALSE ? "on" : "off",
    521                  pause_rx != FALSE ? "on" : "off"));
    522 
    523     values[0] = pause_tx != FALSE ? 1 : 0;
    524     values[1] = pause_rx != FALSE ? 1 : 0;
    525     return soc_reg_fields32_modify(unit, CMAC_PAUSE_CTRLr, port, 2,
    526                                    fields, values);
    527 }
    528 
    529 /*
    530  * Function:
    531  *      mac_c_pause_get
    532  * Purpose:
    533  *      Return the pause ability of CMAC
    534  * Parameters:
    535  *      unit - XGS unit #.
    536  *      port - XGS port # on unit.
    537  *      pause_tx - Boolean: transmit pause
    538  *      pause_rx - Boolean: receive pause
    539  *      pause_mac - MAC address used for pause transmission.
    540  * Returns:
    541  *      SOC_E_XXX
    542  */
    543 STATIC int
    544 mac_c_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx)
    545 {
    546     uint64 rval;
    547 
    548     SOC_IF_ERROR_RETURN(READ_CMAC_PAUSE_CTRLr(unit, port, &rval));
    549     *pause_tx =
    550         soc_reg64_field32_get(unit, CMAC_PAUSE_CTRLr, rval, TX_PAUSE_ENf);
    551     *pause_rx =
    552         soc_reg64_field32_get(unit, CMAC_PAUSE_CTRLr, rval, RX_PAUSE_ENf);
    553     LOG_VERBOSE(BSL_LS_SOC_100G,
    554                 (BSL_META_U(unit,
    555                             "mac_c_pause_get: unit %d port %s TX=%s RX=%s\n"),
    556                  unit, SOC_PORT_NAME(unit, port),
    557                  *pause_tx ? "on" : "off",
    558                  *pause_rx ? "on" : "off"));
    559     return SOC_E_NONE;
    560 }
    561 
    562 /*
    563  * Function:
    564  *      mac_c_speed_set
    565  * Purpose:
    566  *      Set CMAC in the specified speed.
    567  * Parameters:
    568  *      unit - XGS unit #.
    569  *      port - XGS port # on unit.
    570  *      speed - 100000, 120000.
    571  * Returns:
    572  *      SOC_E_XXX
    573  */
    574 STATIC int
    575 mac_c_speed_set(int unit, soc_port_t port, int speed)
    576 {
    577     soc_reg_t reg;
    578     int loopback, frame_max;
    579     int pause_rx, pause_tx;
    580 
    581     LOG_VERBOSE(BSL_LS_SOC_100G,
    582                 (BSL_META_U(unit,
    583                             "mac_c_speed_set: unit %d port %s speed=%dMb\n"),
    584                  unit, SOC_PORT_NAME(unit, port),
    585                  speed));
    586 
    587     /* Save MAC state before reset */
    588     SOC_IF_ERROR_RETURN(mac_c_loopback_get(unit, port, &loopback));
    589     SOC_IF_ERROR_RETURN(mac_c_frame_max_get(unit, port, &frame_max));
    590     SOC_IF_ERROR_RETURN(mac_c_pause_get(unit, port, &pause_tx, &pause_rx));
    591 
    592     /* mac init */
    593     
    594     SOC_IF_ERROR_RETURN(mac_c_init(unit,port));
    595 
    596     /* Restore MAC state after reset */
    597     SOC_IF_ERROR_RETURN(mac_c_loopback_set(unit, port, loopback));
    598     SOC_IF_ERROR_RETURN(mac_c_frame_max_set(unit, port, frame_max));
    599     SOC_IF_ERROR_RETURN(mac_c_pause_set(unit, port, pause_tx, pause_rx));
    600 
    601     /* Set cmac timestamp delay */
    602     SOC_IF_ERROR_RETURN(_mac_c_timestamp_delay_set(unit,port, speed));
    603 
    604     /* program the XLGMII field */
    605     if (soc_reg_field_valid(unit, CMAC_CTRLr, XLGMII_ALIGN_ENBf)) {
    606         if (IS_HG_PORT(unit, port) && (speed >= 106000)) {
    607             SOC_IF_ERROR_RETURN
    608                 (soc_reg_field32_modify(unit, CMAC_CTRLr, port, 
    609                                         XLGMII_ALIGN_ENBf, 0));
    610             
    611         } else {
    612             SOC_IF_ERROR_RETURN
    613                 (soc_reg_field32_modify(unit, CMAC_CTRLr, port, XLGMII_ALIGN_ENBf,
    614                                         speed >= 100000 ? 1 : 0));
    615         }
    616     }
    617 
    618     /* And the PORT CGMII field */
    619     
    620     if (SOC_REG_IS_VALID(unit, CPORT_MAC_MODEr)) {
    621         reg = CPORT_MAC_MODEr;
    622     } else {
    623         reg = PORT_CMAC_MODEr;
    624     }
    625     SOC_IF_ERROR_RETURN
    626         (soc_reg_field32_modify(unit, reg, port, CGMII_MODEf,
    627                                 speed > 106000 ? 1 : 0));
    628 
    629     return SOC_E_NONE;
    630 }
    631 
    632 /*
    633  * Function:
    634  *      mac_c_speed_get
    635  * Purpose:
    636  *      Get CMAC speed
    637  * Parameters:
    638  *      unit - XGS unit #.
    639  *      port - XGS port # on unit.
    640  *      speed - (OUT) speed in Mb
    641  * Returns:
    642  *      SOC_E_XXX
    643  */
    644 STATIC int
    645 mac_c_speed_get(int unit, soc_port_t port, int *speed)
    646 {
    647     uint64 rval;
    648 
    649     SOC_IF_ERROR_RETURN(READ_CMAC_MODEr(unit, port, &rval));
    650     switch (soc_reg64_field32_get(unit, CMAC_MODEr, rval, SPEED_MODEf)) {
    651     case SOC_CMAC_SPEED_10:
    652         *speed = 10;
    653         break;
    654     case SOC_CMAC_SPEED_100:
    655         *speed = 100;
    656         break;
    657     case SOC_CMAC_SPEED_1000:
    658         *speed = 1000;
    659         break;
    660     case SOC_CMAC_SPEED_2500:
    661         *speed = 2500;
    662         break;
    663     case SOC_CMAC_SPEED_10000:
    664     default:
    665         *speed = 10000;
    666     }
    667 
    668     LOG_VERBOSE(BSL_LS_SOC_100G,
    669                 (BSL_META_U(unit,
    670                             "mac_c_speed_get: unit %d port %s speed=%dMb\n"),
    671                  unit, SOC_PORT_NAME(unit, port),
    672                  *speed));
    673     return SOC_E_NONE;
    674 }
    675 
    676 /*
    677  * Function:
    678  *      mac_c_loopback_set
    679  * Purpose:
    680  *      Set a CMAC into/out-of loopback mode
    681  * Parameters:
    682  *      unit - XGS unit #.
    683  *      port - XGS unit # on unit.
    684  *      loopback - Boolean: true -> loopback mode, false -> normal operation
    685  * Note:
    686  *      On Cmac, when setting loopback, we enable the TX/RX function also.
    687  *      Note that to test the PHY, we use the remote loopback facility.
    688  * Returns:
    689  *      SOC_E_XXX
    690  */
    691 STATIC int
    692 mac_c_loopback_set(int unit, soc_port_t port, int lb)
    693 {
    694     LOG_VERBOSE(BSL_LS_SOC_100G,
    695                 (BSL_META_U(unit,
    696                             "mac_c_loopback_set: unit %d port %s loopback=%s\n"),
    697                  unit, SOC_PORT_NAME(unit, port),
    698                  lb ? "local" : "no"));
    699 
    700     /* need to enable clock compensation for applicable serdes device */
    701     (void)soc_phyctrl_notify(unit, port, phyEventMacLoopback, lb? 1: 0);
    702 
    703     return soc_reg_field32_modify(unit, CMAC_CTRLr, port, LINE_LOCAL_LPBKf,
    704                                   lb ? 1 : 0);
    705 
    706     return SOC_E_NONE;
    707 }
    708 
    709 /*
    710  * Function:
    711  *      mac_c_loopback_get
    712  * Purpose:
    713  *      Get current CMAC loopback mode setting.
    714  * Parameters:
    715  *      unit - XGS unit #.
    716  *      port - XGS port # on unit.
    717  *      loopback - (OUT) Boolean: true = loopback, false = normal
    718  * Returns:
    719  *      SOC_E_XXX
    720  */
    721 STATIC int
    722 mac_c_loopback_get(int unit, soc_port_t port, int *lb)
    723 {
    724     uint64 ctrl;
    725     int local, remote;
    726 
    727     SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &ctrl));
    728 
    729     remote = soc_reg64_field32_get(unit, CMAC_CTRLr, ctrl, CORE_REMOTE_LPBKf);
    730     if (soc_reg_field_valid(unit, CMAC_CTRLr, LINE_REMOTE_LPBKf)) {
    731         remote |= soc_reg64_field32_get(unit, CMAC_CTRLr, ctrl,
    732                                         LINE_REMOTE_LPBKf);
    733     }
    734     local = soc_reg64_field32_get(unit, CMAC_CTRLr, ctrl, CORE_LOCAL_LPBKf) |
    735         soc_reg64_field32_get(unit, CMAC_CTRLr, ctrl, LINE_LOCAL_LPBKf);
    736     *lb = local | remote;
    737 
    738     LOG_VERBOSE(BSL_LS_SOC_100G,
    739                 (BSL_META_U(unit,
    740                             "mac_c_loopback_get: unit %d port %s loopback=%s\n"),
    741                  unit, SOC_PORT_NAME(unit, port),
    742                  *lb ? (remote ? "remote" : "local") : "no"));
    743     return SOC_E_NONE;
    744 }
    745 
    746 /*
    747  * Function:
    748  *      mac_c_pause_addr_set
    749  * Purpose:
    750  *      Configure PAUSE frame source address.
    751  * Parameters:
    752  *      unit - XGS unit #.
    753  *      port - XGS port # on unit.
    754  *      pause_mac - (OUT) MAC address used for pause transmission.
    755  * Returns:
    756  *      SOC_E_XXX
    757  */
    758 STATIC int
    759 mac_c_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t m)
    760 {
    761     uint64 r, tmp;
    762     int i;
    763 
    764     LOG_VERBOSE(BSL_LS_SOC_100G,
    765                 (BSL_META_U(unit,
    766                             "mac_c_pause_addr_set: unit %d port %s MAC=<"
    767                              "%02x:%02x:%02x:%02x:%02x:%02x>\n"),
    768                  unit, SOC_PORT_NAME(unit, port),
    769                  m[0], m[1], m[2], m[3], m[4], m[5]));
    770 
    771     COMPILER_64_ZERO(r);
    772     for (i = 0; i< 6; i++) {
    773         COMPILER_64_SET(tmp, 0, m[i]);
    774         COMPILER_64_SHL(r, 8);
    775         COMPILER_64_OR(r, tmp);
    776     }
    777 
    778     SOC_IF_ERROR_RETURN(WRITE_CMAC_TX_MAC_SAr(unit, port, r));
    779     SOC_IF_ERROR_RETURN(WRITE_CMAC_RX_MAC_SAr(unit, port, r));
    780 
    781     return SOC_E_NONE;
    782 }
    783 
    784 /*
    785  * Function:
    786  *      mac_c_pause_addr_get
    787  * Purpose:
    788  *      Retrieve PAUSE frame source address.
    789  * Parameters:
    790  *      unit - XGS unit #.
    791  *      port - XGS port # on unit.
    792  *      pause_mac - (OUT) MAC address used for pause transmission.
    793  * Returns:
    794  *      SOC_E_XXX
    795  * NOTE: We always write the same thing to TX & RX SA
    796  *       so, we just return the contects on RX_MAC_SA.
    797  */
    798 STATIC int
    799 mac_c_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t m)
    800 {
    801     uint64 reg;
    802     uint32 msw;
    803     uint32 lsw;
    804 
    805     SOC_IF_ERROR_RETURN(READ_CMAC_RX_MAC_SAr(unit, port, &reg));
    806     COMPILER_64_TO_32_HI(msw, reg);
    807     COMPILER_64_TO_32_LO(lsw, reg);
    808 
    809     m[0] = (uint8) ( ( msw & 0x0000ff00 ) >> 8 );
    810     m[1] = (uint8) ( msw & 0x000000ff );
    811 
    812     m[2] = (uint8)  ( ( lsw & 0xff000000) >> 24 );
    813     m[3] = (uint8)  ( ( lsw & 0x00ff0000) >> 16 );
    814     m[4] = (uint8)  ( ( lsw & 0x0000ff00) >> 8 );
    815     m[5] = (uint8)  ( lsw & 0x000000ff );
    816 
    817     LOG_VERBOSE(BSL_LS_SOC_100G,
    818                 (BSL_META_U(unit,
    819                             "mac_c_pause_addr_get: unit %d port %s MAC=<"
    820                              "%02x:%02x:%02x:%02x:%02x:%02x>\n"),
    821                  unit, SOC_PORT_NAME(unit, port),
    822                  m[0], m[1], m[2], m[3], m[4], m[5]));
    823     return SOC_E_NONE;
    824 }
    825 
    826 /*
    827  * Function:
    828  *      mac_c_interface_set
    829  * Purpose:
    830  *      Set a CMAC interface type
    831  * Parameters:
    832  *      unit - XGS unit #.
    833  *      port - XGS port # on unit.
    834  *      pif - one of SOC_PORT_IF_*
    835  * Returns:
    836  *      SOC_E_NONE
    837  *      SOC_E_UNAVAIL - requested mode not supported.
    838  * Notes:
    839  */
    840 STATIC int
    841 mac_c_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
    842 {
    843 #ifdef BROADCOM_DEBUG
    844     LOG_VERBOSE(BSL_LS_SOC_100G,
    845                 (BSL_META_U(unit,
    846                             "mac_c_interface_set: unit %d port %s interface=%s\n"),
    847                  unit, SOC_PORT_NAME(unit, port),
    848                  mac_c_port_if_names[pif]));
    849 #endif
    850     return SOC_E_NONE;
    851 }
    852 
    853 /*
    854  * Function:
    855  *      mac_c_interface_get
    856  * Purpose:
    857  *      Retrieve CMAC interface type
    858  * Parameters:
    859  *      unit - XGS unit #.
    860  *      port - XGS port # on unit.
    861  *      pif - (OUT) one of SOC_PORT_IF_*
    862  * Returns:
    863  *      SOC_E_NONE
    864  */
    865 STATIC int
    866 mac_c_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
    867 {
    868     COMPILER_REFERENCE(unit);
    869     COMPILER_REFERENCE(port);
    870 
    871     *pif = SOC_PORT_IF_CGMII;
    872 
    873 #ifdef BROADCOM_DEBUG
    874     LOG_VERBOSE(BSL_LS_SOC_100G,
    875                 (BSL_META_U(unit,
    876                             "mac_c_interface_get: unit %d port %s interface=%s\n"),
    877                  unit, SOC_PORT_NAME(unit, port),
    878                  mac_c_port_if_names[*pif]));
    879 #endif
    880     return SOC_E_NONE;
    881 }
    882 
    883 /*
    884  * Function:
    885  *      mac_c_frame_max_set
    886  * Description:
    887  *      Set the maximum receive frame size for the port
    888  * Parameters:
    889  *      unit - Device number
    890  *      port - Port number
    891  *      size - Maximum frame size in bytes
    892  * Return Value:
    893  *      BCM_E_XXX
    894  */
    895 STATIC int
    896 mac_c_frame_max_set(int unit, soc_port_t port, int size)
    897 {
    898     uint64 rval;
    899 
    900     LOG_VERBOSE(BSL_LS_SOC_100G,
    901                 (BSL_META_U(unit,
    902                             "mac_c_frame_max_set: unit %d port %s size=%d\n"),
    903                  unit, SOC_PORT_NAME(unit, port),
    904                  size));
    905 
    906     if (IS_CE_PORT(unit, port)) {
    907         /* For VLAN tagged packets */
    908         size += 4;
    909     }
    910     COMPILER_64_ZERO(rval);
    911     soc_reg64_field32_set(unit, CMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf, size);
    912     SOC_IF_ERROR_RETURN(WRITE_CMAC_RX_MAX_SIZEr(unit, port, rval));
    913 
    914     return SOC_E_NONE;
    915 }
    916 
    917 /*
    918  * Function:
    919  *      mac_c_frame_max_get
    920  * Description:
    921  *      Set the maximum receive frame size for the port
    922  * Parameters:
    923  *      unit - Device number
    924  *      port - Port number
    925  *      size - Maximum frame size in bytes
    926  * Return Value:
    927  *      BCM_E_XXX
    928  */
    929 STATIC int
    930 mac_c_frame_max_get(int unit, soc_port_t port, int *size)
    931 {
    932     uint64 rval;
    933 
    934     SOC_IF_ERROR_RETURN(READ_CMAC_RX_MAX_SIZEr(unit, port, &rval));
    935     *size = soc_reg64_field32_get(unit, CMAC_RX_MAX_SIZEr, rval, RX_MAX_SIZEf);
    936     if (IS_CE_PORT(unit, port)) {
    937         /* For VLAN tagged packets */
    938         *size -= 4;
    939     }
    940 
    941     LOG_VERBOSE(BSL_LS_SOC_100G,
    942                 (BSL_META_U(unit,
    943                             "mac_c_frame_max_get: unit %d port %s size=%d\n"),
    944                  unit, SOC_PORT_NAME(unit, port),
    945                  *size));
    946     return SOC_E_NONE;
    947 }
    948 
    949 /*
    950  * Function:
    951  *      mac_c_ifg_set
    952  * Description:
    953  *      Sets the new ifg (Inter-frame gap) value
    954  * Parameters:
    955  *      unit   - Device number
    956  *      port   - Port number
    957  *      speed  - the speed for which the IFG is being set
    958  *      duplex - the duplex for which the IFG is being set
    959  *      ifg - number of bits to use for average inter-frame gap
    960  * Return Value:
    961  *      BCM_E_XXX
    962  * Notes:
    963  *      The function makes sure the IFG value makes sense and updates the
    964  *      IPG register in case the speed/duplex match the current settings
    965  */
    966 STATIC int
    967 mac_c_ifg_set(int unit, soc_port_t port, int speed,
    968                 soc_port_duplex_t duplex, int ifg)
    969 {
    970     int         cur_speed;
    971     int         cur_duplex;
    972     int         real_ifg;
    973     soc_ipg_t  *si = &SOC_PERSIST(unit)->ipg[port];
    974     uint64      rval, orval;
    975     soc_port_ability_t ability;
    976     uint32      pa_flag;
    977 
    978     LOG_VERBOSE(BSL_LS_SOC_100G,
    979                 (BSL_META_U(unit,
    980                             "mac_c_ifg_set: unit %d port %s speed=%dMb duplex=%s "
    981                              "ifg=%d\n"),
    982                  unit, SOC_PORT_NAME(unit, port),
    983                  speed, duplex ? "True" : "False", ifg));
    984 
    985     pa_flag = SOC_PA_SPEED(speed); 
    986     soc_mac_c.md_ability_local_get(unit, port, &ability);
    987     if (!(pa_flag & ability.speed_full_duplex)) {
    988         return SOC_E_PARAM;
    989     }
    990 
    991     /* Silently adjust the specified ifp bits to valid value */
    992     /* valid value: 8 to 31 bytes (i.e. multiple of 8 bits) */
    993     real_ifg = ifg < 64 ? 64 : (ifg + 7) & (0x1f << 3);
    994 
    995     if (IS_CE_PORT(unit, port)) {
    996         si->fd_xe = real_ifg;
    997     } else {
    998         si->fd_hg = real_ifg;
    999     }
   1000 
   1001     SOC_IF_ERROR_RETURN(mac_c_duplex_get(unit, port, &cur_duplex));
   1002     SOC_IF_ERROR_RETURN(mac_c_speed_get(unit, port, &cur_speed));
   1003 
   1004     if (cur_speed == speed &&
   1005         cur_duplex == (duplex == SOC_PORT_DUPLEX_FULL ? TRUE : FALSE)) {
   1006         SOC_IF_ERROR_RETURN(READ_CMAC_TX_CTRLr(unit, port, &rval));
   1007         orval = rval;
   1008         soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &rval, AVERAGE_IPGf,
   1009                               real_ifg / 8);
   1010         if (COMPILER_64_NE(rval, orval)) {
   1011             SOC_IF_ERROR_RETURN(WRITE_CMAC_TX_CTRLr(unit, port, rval));
   1012         }
   1013     }
   1014 
   1015     return SOC_E_NONE;
   1016 }
   1017 
   1018 /*
   1019  * Function:
   1020  *      mac_c_ifg_get
   1021  * Description:
   1022  *      Sets the new ifg (Inter-frame gap) value
   1023  * Parameters:
   1024  *      unit   - Device number
   1025  *      port   - Port number
   1026  *      speed  - the speed for which the IFG is being set
   1027  *      duplex - the duplex for which the IFG is being set
   1028  *      size - Maximum frame size in bytes
   1029  * Return Value:
   1030  *      BCM_E_XXX
   1031  * Notes:
   1032  *      The function makes sure the IFG value makes sense and updates the
   1033  *      IPG register in case the speed/duplex match the current settings
   1034  */
   1035 STATIC int
   1036 mac_c_ifg_get(int unit, soc_port_t port, int speed,
   1037                 soc_port_duplex_t duplex, int *ifg)
   1038 {
   1039     soc_ipg_t  *si = &SOC_PERSIST(unit)->ipg[port];
   1040     soc_port_ability_t ability;
   1041     uint32      pa_flag;
   1042 
   1043     if (!duplex) {
   1044         return SOC_E_PARAM;
   1045     }
   1046 
   1047     pa_flag = SOC_PA_SPEED(speed); 
   1048     soc_mac_c.md_ability_local_get(unit, port, &ability);
   1049     if (!(pa_flag & ability.speed_full_duplex)) {
   1050         return SOC_E_PARAM;
   1051     }
   1052 
   1053     if (IS_CE_PORT(unit, port)) {
   1054         *ifg = si->fd_xe;
   1055     } else {
   1056         *ifg = si->fd_hg;
   1057     }
   1058 
   1059     LOG_VERBOSE(BSL_LS_SOC_100G,
   1060                 (BSL_META_U(unit,
   1061                             "mac_c_ifg_get: unit %d port %s speed=%dMb duplex=%s "
   1062                              "ifg=%d\n"),
   1063                  unit, SOC_PORT_NAME(unit, port),
   1064                  speed, duplex ? "True" : "False", *ifg));
   1065     return SOC_E_NONE;
   1066 }
   1067 
   1068 /*
   1069  * Function:
   1070  *      mac_c_loopback_remote_set
   1071  * Purpose:
   1072  *      Set the CMAC into remote-loopback state.
   1073  * Parameters:
   1074  *      unit - XGS unit #.
   1075  *      port - XGS port # on unit.
   1076  *      mode - (INT) loopback enable state
   1077  * Returns:
   1078  *      SOC_E_XXX
   1079  */
   1080 int
   1081 mac_c_loopback_remote_set(int unit, soc_port_t port, int lb)
   1082 {
   1083     LOG_VERBOSE(BSL_LS_SOC_100G,
   1084                 (BSL_META_U(unit,
   1085                             "mac_c_loopback_remote_set: unit %d port %s loopback=%s\n"),
   1086                  unit, SOC_PORT_NAME(unit, port),
   1087                  lb ? "remote" : "no"));
   1088 
   1089     return soc_reg_field32_modify(unit, CMAC_CTRLr, port, CORE_REMOTE_LPBKf,
   1090                                   lb ? 1 : 0);
   1091 }
   1092 
   1093 /*
   1094  * Function:
   1095  *      _mac_c_port_mode_update
   1096  * Purpose:
   1097  *      Set the CMAC port encapsulation mode.
   1098  * Parameters:
   1099  *      unit - XGS unit #.
   1100  *      port - XGS port # on unit.
   1101  *      to_hg_port - (TRUE/FALSE)
   1102  * Returns:
   1103  *      SOC_E_XXX
   1104  */
   1105 STATIC int
   1106 _mac_c_port_mode_update(int unit, soc_port_t port, int to_hg_port)
   1107 {
   1108     uint32              rval;
   1109     uint64              val64;
   1110     soc_pbmp_t          ctr_pbmp;
   1111     int                 rv = SOC_E_NONE;
   1112 
   1113     /* Pause linkscan */
   1114     soc_linkscan_pause(unit);
   1115 
   1116     /* Pause counter collection */
   1117     COUNTER_LOCK(unit);
   1118 
   1119     soc_xport_type_update(unit, port, to_hg_port);
   1120 
   1121 #if defined (BCM_TRIUMPH3_SUPPORT)
   1122     if (SOC_IS_TRIUMPH3(unit)) {
   1123        /* no need to hard reset the Warpcore serdes device. Soft init
   1124         * should be good enough.  Hard reset brings
   1125         * down all other ports using the same Warpcore in quad-port mode. 
   1126         */
   1127     } else 
   1128 #endif /* BCM_TRIUMPH3_SUPPORT */
   1129     {
   1130         rv = soc_xgxs_reset(unit, port);
   1131     }
   1132 
   1133     if (SOC_SUCCESS(rv)) {
   1134         rv = soc_phyctrl_init(unit, port);
   1135     }
   1136 
   1137     if (SOC_SUCCESS(rv)) {
   1138         rv = mac_c_init(unit, port);
   1139     }
   1140 
   1141     if (SOC_SUCCESS(rv)) {
   1142         rv = mac_c_enable_set(unit, port, 0);
   1143     }
   1144 
   1145     if (SOC_SUCCESS(rv)) {
   1146         SOC_PBMP_CLEAR(ctr_pbmp);
   1147         SOC_PBMP_PORT_SET(ctr_pbmp, port);
   1148         COMPILER_64_SET(val64, 0, 0);
   1149         rv = soc_counter_set_by_port(unit, ctr_pbmp, val64);
   1150     }
   1151 
   1152     COUNTER_UNLOCK(unit);
   1153     soc_linkscan_continue(unit);
   1154     rval = 0;
   1155     SOC_IF_ERROR_RETURN(READ_PORT_CONFIGr(unit, port, &rval));
   1156     if (to_hg_port) {
   1157         soc_reg_field_set(unit, PORT_CONFIGr, &rval, HIGIG_MODEf, 1);
   1158         if (soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE, 0)) {
   1159             soc_reg_field_set(unit, PORT_CONFIGr, &rval, HIGIG2_MODEf, 1);
   1160         }
   1161     } else {
   1162         soc_reg_field_set(unit, PORT_CONFIGr, &rval, HIGIG_MODEf, 0);
   1163     }
   1164     SOC_IF_ERROR_RETURN(WRITE_PORT_CONFIGr(unit, port, rval));
   1165     return rv;
   1166 }
   1167 
   1168 /*
   1169  * Function:
   1170  *      mac_c_encap_set
   1171  * Purpose:
   1172  *      Set the CMAC port encapsulation mode.
   1173  * Parameters:
   1174  *      unit - XGS unit #.
   1175  *      port - XGS port # on unit.
   1176  *      mode - (IN) encap bits (defined above)
   1177  * Returns:
   1178  *      SOC_E_XXX
   1179  */
   1180 STATIC int
   1181 mac_c_encap_set(int unit, soc_port_t port, int mode)
   1182 {
   1183     int enable, encap, rv;
   1184 
   1185 #ifdef BROADCOM_DEBUG
   1186     LOG_VERBOSE(BSL_LS_SOC_100G,
   1187                 (BSL_META_U(unit,
   1188                             "mac_c_encap_set: unit %d port %s encapsulation=%s\n"),
   1189                  unit, SOC_PORT_NAME(unit, port),
   1190                  mac_c_encap_mode[mode]));
   1191 #endif
   1192 
   1193     switch (mode) {
   1194     case SOC_ENCAP_IEEE:
   1195         encap = 0;
   1196         break;
   1197     case SOC_ENCAP_HIGIG:
   1198         encap = 1;
   1199         break;
   1200     case SOC_ENCAP_HIGIG2:
   1201         encap = 2;
   1202         break;
   1203     default:
   1204         return SOC_E_PARAM;
   1205     }
   1206 
   1207     if (!soc_feature(unit, soc_feature_xport_convertible)) {
   1208         if ((IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) ||
   1209             (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE)) {
   1210             return SOC_E_PARAM;
   1211         }
   1212     }
   1213 
   1214     SOC_IF_ERROR_RETURN(mac_c_enable_get(unit, port, &enable));
   1215 
   1216     if (enable) {
   1217         /* Turn off TX/RX enable */
   1218         SOC_IF_ERROR_RETURN(mac_c_enable_set(unit, port, 0));
   1219     }
   1220 
   1221     if (IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) {
   1222         /* CE -> HG */
   1223         SOC_IF_ERROR_RETURN(_mac_c_port_mode_update(unit, port, TRUE));
   1224     } else if (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE) {
   1225         /* HG -> CE */
   1226         SOC_IF_ERROR_RETURN(_mac_c_port_mode_update(unit, port, FALSE));
   1227     }
   1228 
   1229     /* Update the encapsulation mode */
   1230     rv = soc_reg_field32_modify(unit, CMAC_MODEr, port, HDR_MODEf, encap);
   1231 
   1232     if (enable) {
   1233         /* Re-enable transmitter and receiver */
   1234         SOC_IF_ERROR_RETURN(mac_c_enable_set(unit, port, 1));
   1235     }
   1236 
   1237     return rv;
   1238 }
   1239 
   1240 /*
   1241  * Function:
   1242  *      mac_c_encap_get
   1243  * Purpose:
   1244  *      Get the CMAC port encapsulation mode.
   1245  * Parameters:
   1246  *      unit - XGS unit #.
   1247  *      port - XGS port # on unit.
   1248  *      mode - (INT) encap bits (defined above)
   1249  * Returns:
   1250  *      SOC_E_XXX
   1251  */
   1252 STATIC int
   1253 mac_c_encap_get(int unit, soc_port_t port, int *mode)
   1254 {
   1255     uint64 rval;
   1256 
   1257     if (!mode) {
   1258         return SOC_E_PARAM;
   1259     }
   1260 
   1261     SOC_IF_ERROR_RETURN(READ_CMAC_MODEr(unit, port, &rval));
   1262     switch (soc_reg64_field32_get(unit, CMAC_MODEr, rval, HDR_MODEf)) {
   1263     case 0:
   1264         *mode = SOC_ENCAP_IEEE;
   1265         break;
   1266     case 1:
   1267         *mode = SOC_ENCAP_HIGIG;
   1268         break;
   1269     case 2:
   1270         *mode = SOC_ENCAP_HIGIG2;
   1271         break;
   1272     default:
   1273         *mode = SOC_ENCAP_COUNT;
   1274     }
   1275 
   1276 #ifdef BROADCOM_DEBUG
   1277     LOG_VERBOSE(BSL_LS_SOC_100G,
   1278                 (BSL_META_U(unit,
   1279                             "mac_c_encap_get: unit %d port %s encapsulation=%s\n"),
   1280                  unit, SOC_PORT_NAME(unit, port),
   1281                  mac_c_encap_mode[*mode]));
   1282 #endif
   1283     return SOC_E_NONE;
   1284 }
   1285 
   1286 /*
   1287  * Function:
   1288  *      mac_c_expected_rx_latency_get
   1289  * Purpose:
   1290  *      Get the CMAC port expected Rx latency
   1291  * Parameters:
   1292  *      unit - XGS unit #.
   1293  *      port - XGS port # on unit.
   1294  *      latency - (OUT) Latency in NS
   1295  * Returns:
   1296  *      SOC_E_XXX
   1297  */
   1298 STATIC int
   1299 mac_c_expected_rx_latency_get(int unit, soc_port_t port, int *latency)
   1300 {
   1301     int speed = 0;
   1302     SOC_IF_ERROR_RETURN(mac_c_speed_get(unit, port, &speed));
   1303 
   1304     
   1305     switch (speed) {
   1306     case 1000:  /* GigE */
   1307         *latency = 0;
   1308         break;
   1309 
   1310     case 10000:  /* 10G */
   1311         *latency = 0;
   1312         break;
   1313 
   1314     case 100000:  /* 100G */
   1315         *latency = 0;
   1316         break;
   1317 
   1318     default:
   1319         *latency = 0;
   1320         break;
   1321     }
   1322 
   1323     return SOC_E_NONE;
   1324 }
   1325 
   1326 /*
   1327  * Function:
   1328  *      mac_c_control_set
   1329  * Purpose:
   1330  *      To configure MAC control properties.
   1331  * Parameters:
   1332  *      unit - XGS unit #.
   1333  *      port - XGS port # on unit.
   1334  *      type - MAC control property to set.
   1335  *      int  - New setting for MAC control.
   1336  * Returns:
   1337  *      SOC_E_XXX
   1338  */
   1339 STATIC int
   1340 mac_c_control_set(int unit, soc_port_t port, soc_mac_control_t type,
   1341                   int value)
   1342 {
   1343     uint64 rval, copy;
   1344     uint32 fval;
   1345 
   1346     LOG_VERBOSE(BSL_LS_SOC_100G,
   1347                 (BSL_META_U(unit,
   1348                             "mac_c_control_set: unit %d port %s type=%d value=%d\n"),
   1349                  unit, SOC_PORT_NAME(unit, port),
   1350                  type, value));
   1351 
   1352     switch (type) {
   1353     case SOC_MAC_CONTROL_RX_SET:
   1354         SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &rval));
   1355         copy = rval;
   1356         soc_reg64_field32_set(unit, CMAC_CTRLr, &rval, RX_ENf, value ? 1 : 0);
   1357         if (COMPILER_64_NE(rval, copy)) {
   1358             SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, rval));
   1359         }    
   1360         break;
   1361     case SOC_MAC_CONTROL_TX_SET:
   1362         SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &rval));
   1363         copy = rval;
   1364         soc_reg64_field32_set(unit, CMAC_CTRLr, &rval, TX_ENf, value ? 1 : 0);
   1365         if (COMPILER_64_NE(rval, copy)) {
   1366             SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, rval));
   1367         }    
   1368         break;
   1369     case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH:
   1370         if (value < 0 || value > 255) {
   1371             return SOC_E_PARAM;
   1372         } else {
   1373             SOC_IF_ERROR_RETURN(READ_CMAC_TX_CTRLr(unit, port, &rval));
   1374             if (value >= 8) {
   1375                 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &rval, THROT_DENOMf,
   1376                                       value);
   1377                 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &rval, THROT_NUMf,
   1378                                       1);
   1379             } else {
   1380                 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &rval, THROT_DENOMf,
   1381                                       0);
   1382                 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &rval, THROT_NUMf,
   1383                                       0);
   1384             }
   1385             SOC_IF_ERROR_RETURN(WRITE_CMAC_TX_CTRLr(unit, port, rval));
   1386         }
   1387         return SOC_E_NONE;
   1388 
   1389     case SOC_MAC_PASS_CONTROL_FRAME:
   1390         SOC_IF_ERROR_RETURN(READ_CMAC_RX_CTRLr(unit, port, &rval));
   1391         soc_reg64_field32_set(unit, CMAC_RX_CTRLr, &rval, RX_PASS_CTRLf,
   1392                               value ? 1 : 0);
   1393         SOC_IF_ERROR_RETURN(WRITE_CMAC_RX_CTRLr(unit, port, rval));
   1394         break;
   1395 
   1396     case SOC_MAC_CONTROL_PFC_TYPE:
   1397         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CMAC_PFC_TYPEr, port,
   1398                                                    PFC_ETH_TYPEf, value));
   1399         break;
   1400 
   1401     case SOC_MAC_CONTROL_PFC_OPCODE:
   1402         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CMAC_PFC_OPCODEr,
   1403                                                    port, PFC_OPCODEf, value));
   1404         break;
   1405 
   1406     case SOC_MAC_CONTROL_PFC_CLASSES:
   1407         if (value != 8) {
   1408             return SOC_E_PARAM;
   1409         }
   1410         break;
   1411 
   1412     case SOC_MAC_CONTROL_PFC_MAC_DA_OUI:
   1413         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_DAr(unit, port, &rval));
   1414         fval = soc_reg64_field32_get(unit, CMAC_PFC_DAr, rval, PFC_MACDA_LOf);
   1415         fval &= 0x00ffffff;
   1416         fval |= (value & 0xff) << 24;
   1417         soc_reg64_field32_set(unit, CMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval);
   1418 
   1419         soc_reg64_field32_set(unit, CMAC_PFC_DAr, &rval, PFC_MACDA_HIf,
   1420                               value >> 8);
   1421         SOC_IF_ERROR_RETURN(WRITE_CMAC_PFC_DAr(unit, port, rval));
   1422         break;
   1423 
   1424     case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI:
   1425         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_DAr(unit, port, &rval));
   1426         fval = soc_reg64_field32_get(unit, CMAC_PFC_DAr, rval, PFC_MACDA_LOf);
   1427         fval &= 0xff000000;
   1428         fval |= value;
   1429         soc_reg64_field32_set(unit, CMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval);
   1430         SOC_IF_ERROR_RETURN(WRITE_CMAC_PFC_DAr(unit, port, rval));
   1431         break;
   1432 
   1433     case SOC_MAC_CONTROL_PFC_RX_PASS:
   1434         SOC_IF_ERROR_RETURN
   1435             (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, RX_PASS_PFCf,
   1436                                     value ? 1 : 0));
   1437         break;
   1438 
   1439     case SOC_MAC_CONTROL_PFC_RX_ENABLE:
   1440         SOC_IF_ERROR_RETURN
   1441             (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, RX_PFC_ENf,
   1442                                     value ? 1 : 0));
   1443         break;
   1444 
   1445     case SOC_MAC_CONTROL_PFC_TX_ENABLE:
   1446         SOC_IF_ERROR_RETURN
   1447             (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, TX_PFC_ENf,
   1448                                     value ? 1 : 0));
   1449         break;
   1450 
   1451     case SOC_MAC_CONTROL_PFC_FORCE_XON:
   1452         SOC_IF_ERROR_RETURN
   1453             (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, FORCE_PFC_XONf,
   1454                                     value ? 1 : 0));
   1455         break;
   1456 
   1457     case SOC_MAC_CONTROL_PFC_STATS_ENABLE:
   1458         SOC_IF_ERROR_RETURN
   1459             (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, PFC_STATS_ENf,
   1460                                     value ? 1 : 0));
   1461         break;
   1462 
   1463     case SOC_MAC_CONTROL_PFC_REFRESH_TIME:
   1464         SOC_IF_ERROR_RETURN
   1465             (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, 
   1466                                     PFC_REFRESH_TIMERf, value));
   1467         break;
   1468 
   1469     case SOC_MAC_CONTROL_PFC_XOFF_TIME:
   1470         SOC_IF_ERROR_RETURN
   1471             (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, 
   1472                                     PFC_XOFF_TIMERf, value));
   1473         break;
   1474 
   1475     case SOC_MAC_CONTROL_LLFC_RX_ENABLE:
   1476         SOC_IF_ERROR_RETURN
   1477             (soc_reg_field32_modify(unit, CMAC_LLFC_CTRLr, port, RX_LLFC_ENf,
   1478                                     value ? 1 : 0));
   1479         break;
   1480     
   1481     case SOC_MAC_CONTROL_LLFC_TX_ENABLE:
   1482         SOC_IF_ERROR_RETURN
   1483             (soc_reg_field32_modify(unit, CMAC_LLFC_CTRLr, port, TX_LLFC_ENf,
   1484                                     value ? 1 : 0));
   1485         break;
   1486 
   1487     case SOC_MAC_CONTROL_EEE_ENABLE:
   1488         if (!soc_feature(unit, soc_feature_eee)) {
   1489             return SOC_E_UNAVAIL;
   1490         }
   1491         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CMAC_EEE_CTRLr, 
   1492                                                    port, EEE_ENf, value));
   1493         break;
   1494 
   1495     case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME:
   1496         if (!soc_feature(unit, soc_feature_eee)) {
   1497             return SOC_E_UNAVAIL;
   1498         }
   1499         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CMAC_EEE_TIMERSr, 
   1500                                     port, EEE_DELAY_ENTRY_TIMERf, value));
   1501         break;
   1502 
   1503     case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME:
   1504         if (!soc_feature(unit, soc_feature_eee)) {
   1505             return SOC_E_UNAVAIL;
   1506         }
   1507         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CMAC_EEE_TIMERSr, 
   1508                                     port, EEE_WAKE_TIMERf, value));
   1509         break;
   1510 
   1511     case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE:
   1512         SOC_IF_ERROR_RETURN
   1513             (soc_reg_field32_modify(unit, CMAC_RX_LSS_CTRLr, port,
   1514                                     LOCAL_FAULT_DISABLEf, value ? 0 : 1));
   1515         break;
   1516 
   1517     case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE:
   1518         SOC_IF_ERROR_RETURN
   1519             (soc_reg_field32_modify(unit, CMAC_RX_LSS_CTRLr, port,
   1520                                     REMOTE_FAULT_DISABLEf, value ? 0 : 1));
   1521         break;
   1522 
   1523 
   1524     case SOC_MAC_CONTROL_FAILOVER_RX_SET:
   1525         break;
   1526 
   1527     default:
   1528         return SOC_E_UNAVAIL;
   1529     }
   1530 
   1531     return SOC_E_NONE;
   1532 }
   1533 
   1534 /*
   1535  * Function:
   1536  *      mac_c_control_get
   1537  * Purpose:
   1538  *      To get current MAC control setting.
   1539  * Parameters:
   1540  *      unit - XGS unit #.
   1541  *      port - XGS port # on unit.
   1542  *      type - MAC control property to set.
   1543  *      int  - New setting for MAC control.
   1544  * Returns:
   1545  *      SOC_E_XXX
   1546  */
   1547 STATIC int
   1548 mac_c_control_get(int unit, soc_port_t port, soc_mac_control_t type,
   1549                   int *value)
   1550 {
   1551     int rv;
   1552     uint64 rval;
   1553     uint32 fval0, fval1;
   1554 
   1555     if (value == NULL) {
   1556         return SOC_E_PARAM;
   1557     }
   1558 
   1559     rv = SOC_E_NONE;
   1560     switch (type) {
   1561     case SOC_MAC_CONTROL_RX_SET:
   1562         SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &rval));
   1563         *value = soc_reg64_field32_get(unit, CMAC_CTRLr, rval, RX_ENf);
   1564         break;
   1565     case SOC_MAC_CONTROL_TX_SET:
   1566         SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &rval));
   1567         *value = soc_reg64_field32_get(unit, CMAC_CTRLr, rval, TX_ENf);
   1568         break;
   1569     case SOC_MAC_CONTROL_SW_RESET:
   1570         SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &rval));
   1571         *value = soc_reg64_field32_get(unit, CMAC_CTRLr, rval, SOFT_RESETf);
   1572         break;
   1573     case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH:
   1574         SOC_IF_ERROR_RETURN(READ_CMAC_TX_CTRLr(unit, port, &rval));
   1575         *value = soc_reg64_field32_get(unit, CMAC_TX_CTRLr, rval,
   1576                                        THROT_DENOMf);
   1577         rv = SOC_E_NONE;
   1578         break;
   1579 
   1580     case SOC_MAC_CONTROL_TIMESTAMP_TRANSMIT:
   1581         {
   1582             uint32  timestamp = 0;
   1583             if (soc_feature(unit, soc_feature_timestamp_counter) &&
   1584                 soc_property_get(unit, spn_SW_TIMESTAMP_FIFO_ENABLE, 1)) {
   1585                 if (soc_counter_timestamp_get(unit, port, &timestamp) !=
   1586                     SOC_E_NOT_FOUND) {
   1587                     *value = (int)timestamp;
   1588                     break;
   1589                 }
   1590             }
   1591 
   1592             SOC_IF_ERROR_RETURN
   1593                 (READ_CMAC_TX_TIMESTAMP_FIFO_STATUSr(unit, port, &rval));
   1594             if (soc_reg64_field32_get(unit, CMAC_TX_TIMESTAMP_FIFO_STATUSr, rval,
   1595                                       ENTRY_COUNTf) == 0) {
   1596                 return SOC_E_EMPTY;
   1597             }
   1598             SOC_IF_ERROR_RETURN
   1599                 (READ_CMAC_TX_TIMESTAMP_FIFO_DATAr(unit, port, &rval));
   1600             *value = soc_reg64_field32_get(unit, CMAC_TX_TIMESTAMP_FIFO_DATAr,
   1601                                            rval, TIME_STAMPf);
   1602         }
   1603         break;
   1604 
   1605     case SOC_MAC_PASS_CONTROL_FRAME:
   1606         SOC_IF_ERROR_RETURN(READ_CMAC_RX_CTRLr(unit, port, &rval));
   1607         *value = soc_reg64_field32_get(unit, CMAC_RX_CTRLr, rval,
   1608                                        RX_PASS_CTRLf);
   1609         break;
   1610 
   1611     case SOC_MAC_CONTROL_PFC_TYPE:
   1612         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_TYPEr(unit, port, &rval));
   1613         *value = soc_reg64_field32_get(unit, CMAC_PFC_TYPEr, rval,
   1614                                        PFC_ETH_TYPEf);
   1615         break;
   1616 
   1617     case SOC_MAC_CONTROL_PFC_OPCODE:
   1618         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_OPCODEr(unit, port, &rval));
   1619         *value = soc_reg64_field32_get(unit, CMAC_PFC_OPCODEr, rval,
   1620                                        PFC_OPCODEf);
   1621         break;
   1622 
   1623     case SOC_MAC_CONTROL_PFC_CLASSES:
   1624         *value = 8;
   1625         break;
   1626 
   1627     case SOC_MAC_CONTROL_PFC_MAC_DA_OUI:
   1628         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_DAr(unit, port, &rval));
   1629         fval0 = soc_reg64_field32_get(unit, CMAC_PFC_DAr, rval, PFC_MACDA_LOf);
   1630         fval1 = soc_reg64_field32_get(unit, CMAC_PFC_DAr, rval, PFC_MACDA_HIf);
   1631         *value = (fval0 >> 24) | (fval1 << 8);
   1632         break;
   1633 
   1634     case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI:
   1635         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_DAr(unit, port, &rval));
   1636         *value = soc_reg64_field32_get(unit, CMAC_PFC_DAr, rval,
   1637                                        PFC_MACDA_LOf) & 0x00ffffff;
   1638         break;
   1639 
   1640     case SOC_MAC_CONTROL_PFC_RX_PASS:
   1641         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval));
   1642         *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval,
   1643                                        RX_PASS_PFCf);
   1644         break;
   1645 
   1646     case SOC_MAC_CONTROL_PFC_RX_ENABLE:
   1647         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval));
   1648         *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval,
   1649                                        RX_PFC_ENf);
   1650         break;
   1651 
   1652     case SOC_MAC_CONTROL_PFC_TX_ENABLE:
   1653         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval));
   1654         *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval,
   1655                                        TX_PFC_ENf);
   1656         break;
   1657 
   1658     case SOC_MAC_CONTROL_PFC_FORCE_XON:
   1659         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval));
   1660         *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval,
   1661                                        FORCE_PFC_XONf);
   1662         break;
   1663 
   1664     case SOC_MAC_CONTROL_PFC_STATS_ENABLE:
   1665         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval));
   1666         *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval,
   1667                                        PFC_STATS_ENf);
   1668         break;
   1669 
   1670     case SOC_MAC_CONTROL_PFC_REFRESH_TIME:
   1671         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval));
   1672         *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval,
   1673                                        PFC_REFRESH_TIMERf);
   1674         break;
   1675 
   1676     case SOC_MAC_CONTROL_PFC_XOFF_TIME:
   1677         SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval));
   1678         *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval,
   1679                                        PFC_XOFF_TIMERf);
   1680         break;
   1681 
   1682     case SOC_MAC_CONTROL_LLFC_RX_ENABLE:
   1683         SOC_IF_ERROR_RETURN(READ_CMAC_LLFC_CTRLr(unit, port, &rval));
   1684         *value = soc_reg64_field32_get(unit, CMAC_LLFC_CTRLr, rval,
   1685                                        RX_LLFC_ENf);
   1686         break;
   1687 
   1688     case SOC_MAC_CONTROL_LLFC_TX_ENABLE:
   1689         SOC_IF_ERROR_RETURN(READ_CMAC_LLFC_CTRLr(unit, port, &rval));
   1690         *value = soc_reg64_field32_get(unit, CMAC_LLFC_CTRLr, rval,
   1691                                        TX_LLFC_ENf);
   1692         break;
   1693 
   1694     case SOC_MAC_CONTROL_EEE_ENABLE:
   1695         if (!soc_feature(unit, soc_feature_eee)) {
   1696             return SOC_E_UNAVAIL;
   1697         }
   1698         if (!soc_reg_field_valid(unit, CMAC_EEE_CTRLr, EEE_ENf)) {
   1699             return SOC_E_UNAVAIL;
   1700         }
   1701         SOC_IF_ERROR_RETURN(READ_CMAC_EEE_CTRLr(unit, port, &rval));
   1702         *value = soc_reg64_field32_get(unit, CMAC_EEE_CTRLr, rval, EEE_ENf);
   1703         break;
   1704 
   1705     case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME:
   1706         if (!soc_feature(unit, soc_feature_eee)) {
   1707             return SOC_E_UNAVAIL;
   1708         }
   1709         if (!soc_reg_field_valid(unit, CMAC_EEE_TIMERSr, EEE_DELAY_ENTRY_TIMERf)) {
   1710             return SOC_E_UNAVAIL;
   1711         }
   1712         SOC_IF_ERROR_RETURN(READ_CMAC_EEE_TIMERSr(unit, port, &rval));
   1713         *value = soc_reg64_field32_get(unit, CMAC_EEE_TIMERSr, rval,
   1714                 EEE_DELAY_ENTRY_TIMERf);
   1715         break;
   1716 
   1717     case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME:
   1718         if (!soc_feature(unit, soc_feature_eee)) {
   1719             return SOC_E_UNAVAIL;
   1720         }
   1721         if (!soc_reg_field_valid(unit, CMAC_EEE_TIMERSr, EEE_WAKE_TIMERf)) {
   1722             return SOC_E_UNAVAIL;
   1723         }
   1724         SOC_IF_ERROR_RETURN(READ_CMAC_EEE_TIMERSr(unit, port, &rval));
   1725         *value = soc_reg64_field32_get(unit, CMAC_EEE_TIMERSr, rval,
   1726                 EEE_WAKE_TIMERf);
   1727         break;
   1728 
   1729     case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE:
   1730         SOC_IF_ERROR_RETURN(READ_CMAC_RX_LSS_CTRLr(unit, port, &rval));
   1731         *value = soc_reg64_field32_get(unit, CMAC_RX_LSS_CTRLr, rval,
   1732                                        LOCAL_FAULT_DISABLEf) ? 0 : 1;
   1733         break;
   1734 
   1735     case SOC_MAC_CONTROL_FAULT_LOCAL_STATUS:
   1736         SOC_IF_ERROR_RETURN(READ_CMAC_RX_LSS_STATUSr(unit, port, &rval));
   1737         *value = soc_reg64_field32_get(unit, CMAC_RX_LSS_STATUSr, rval,
   1738                                        LOCAL_FAULT_STATUSf);
   1739         break;
   1740 
   1741     case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE:
   1742         SOC_IF_ERROR_RETURN(READ_CMAC_RX_LSS_CTRLr(unit, port, &rval));
   1743         *value = soc_reg64_field32_get(unit, CMAC_RX_LSS_CTRLr, rval,
   1744                                        REMOTE_FAULT_DISABLEf) ? 0 : 1;
   1745         break;
   1746 
   1747     case SOC_MAC_CONTROL_FAULT_REMOTE_STATUS:
   1748         SOC_IF_ERROR_RETURN(READ_CMAC_RX_LSS_STATUSr(unit, port, &rval));
   1749         *value = soc_reg64_field32_get(unit, CMAC_RX_LSS_STATUSr, rval,
   1750                                        REMOTE_FAULT_STATUSf);
   1751         break;
   1752     case SOC_MAC_CONTROL_EXPECTED_RX_LATENCY:
   1753         SOC_IF_ERROR_RETURN(mac_c_expected_rx_latency_get(unit, port, value));;
   1754         break;
   1755 
   1756     default:
   1757         return SOC_E_UNAVAIL;
   1758     }
   1759 
   1760     LOG_VERBOSE(BSL_LS_SOC_100G,
   1761                 (BSL_META_U(unit,
   1762                             "mac_c_control_get: unit %d port %s type=%d value=%d "
   1763                              "rv=%d\n"),
   1764                  unit, SOC_PORT_NAME(unit, port),
   1765                  type, *value, rv));
   1766     return rv;
   1767 }
   1768 
   1769 /*
   1770  * Function:
   1771  *      mac_c_ability_local_get
   1772  * Purpose:
   1773  *      Return the abilities of CMAC
   1774  * Parameters:
   1775  *      unit - XGS unit #.
   1776  *      port - XGS port # on unit.
   1777  *      mode - (OUT) Supported operating modes as a mask of abilities.
   1778  * Returns:
   1779  *      SOC_E_XXX
   1780  */
   1781 STATIC int
   1782 mac_c_ability_local_get(int unit, soc_port_t port,
   1783                           soc_port_ability_t *ability)
   1784 {
   1785     if (NULL == ability) {
   1786         return SOC_E_PARAM;
   1787     }
   1788 
   1789     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   1790     ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   1791     ability->interface = SOC_PA_INTF_MII | SOC_PA_INTF_XGMII;
   1792     ability->medium    = SOC_PA_ABILITY_NONE;
   1793     ability->loopback  = SOC_PA_LB_MAC;
   1794     ability->flags     = SOC_PA_ABILITY_NONE;
   1795     ability->encap = SOC_PA_ENCAP_IEEE | SOC_PA_ENCAP_HIGIG |
   1796         SOC_PA_ENCAP_HIGIG2;
   1797 
   1798     if (IS_HG_PORT(unit , port)) {
   1799         switch (SOC_INFO(unit).port_speed_max[port]) {
   1800         case 127000:
   1801             ability->speed_full_duplex |= SOC_PA_SPEED_127GB;
   1802             /* fall through */
   1803         case 120000:
   1804             ability->speed_full_duplex |= SOC_PA_SPEED_120GB;
   1805             /* fall through */
   1806         case 106000:
   1807             ability->speed_full_duplex |= SOC_PA_SPEED_106GB;
   1808             /* fall through */
   1809         case 100000:
   1810             ability->speed_full_duplex |= SOC_PA_SPEED_100GB;
   1811             /* fall through */
   1812         default:
   1813             break;
   1814         }
   1815     } else {
   1816         switch (SOC_INFO(unit).port_speed_max[port]) {
   1817         case 106000:
   1818             ability->speed_full_duplex |= SOC_PA_SPEED_106GB;
   1819             /* fall through */
   1820         case 100000:
   1821             ability->speed_full_duplex |= SOC_PA_SPEED_100GB;
   1822             /* fall through */
   1823         default:
   1824             break;
   1825         }
   1826     }
   1827 
   1828     LOG_VERBOSE(BSL_LS_SOC_100G,
   1829                 (BSL_META_U(unit,
   1830                             "mac_c_ability_local_get: unit %d port %s "
   1831                              "speed_half=0x%x speed_full=0x%x encap=0x%x pause=0x%x "
   1832                              "interface=0x%x medium=0x%x loopback=0x%x flags=0x%x\n"),
   1833                  unit, SOC_PORT_NAME(unit, port),
   1834                  ability->speed_half_duplex, ability->speed_full_duplex,
   1835                  ability->encap, ability->pause, ability->interface,
   1836                  ability->medium, ability->loopback, ability->flags));
   1837     return SOC_E_NONE;
   1838 }
   1839 
   1840 /* Exported CMAC driver structure */
   1841 mac_driver_t soc_mac_c = {
   1842     "CMAC Driver",                /* drv_name */
   1843     mac_c_init,                   /* md_init  */
   1844     mac_c_enable_set,             /* md_enable_set */
   1845     mac_c_enable_get,             /* md_enable_get */
   1846     mac_c_duplex_set,             /* md_duplex_set */
   1847     mac_c_duplex_get,             /* md_duplex_get */
   1848     mac_c_speed_set,              /* md_speed_set */
   1849     mac_c_speed_get,              /* md_speed_get */
   1850     mac_c_pause_set,              /* md_pause_set */
   1851     mac_c_pause_get,              /* md_pause_get */
   1852     mac_c_pause_addr_set,         /* md_pause_addr_set */
   1853     mac_c_pause_addr_get,         /* md_pause_addr_get */
   1854     mac_c_loopback_set,           /* md_lb_set */
   1855     mac_c_loopback_get,           /* md_lb_get */
   1856     mac_c_interface_set,          /* md_interface_set */
   1857     mac_c_interface_get,          /* md_interface_get */
   1858     NULL,                         /* md_ability_get - Deprecated */
   1859     mac_c_frame_max_set,          /* md_frame_max_set */
   1860     mac_c_frame_max_get,          /* md_frame_max_get */
   1861     mac_c_ifg_set,                /* md_ifg_set */
   1862     mac_c_ifg_get,                /* md_ifg_get */
   1863     mac_c_encap_set,              /* md_encap_set */
   1864     mac_c_encap_get,              /* md_encap_get */
   1865     mac_c_control_set,            /* md_control_set */
   1866     mac_c_control_get,            /* md_control_get */
   1867     mac_c_ability_local_get,      /* md_ability_local_get */
   1868     NULL                          /* md_timesync_tx_info_get */
   1869  };
   1870 
   1871 #endif /* BCM_CMAC_SUPPORT */