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

xgxs16g1l.c (114554B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        xgxs16g.c
      8  * Purpose:     Broadcom 1000 Mbps SerDes 
      9  *              (XGXS-16G1L)
     10  *
     11  *  supported speed modes in independent channel mode for these three devices.
     12  *
     13  *                XGXS_16G          XGXS_13G                    Quad SGMII
     14  *   CL37         lane0 only        lane0 only                  lane0 only
     15  *   CL37 BAM     no                no                          no
     16  *   CL73         lane0 only        all four lanes              all four lanes
     17  *   CL73 BAM     no                no                          no
     18  *   Forced 2.5G  yes               yes                         yes
     19  *   Forced 1G    yes               yes                         yes
     20  *   100FX        no                yes                         yes
     21  *   SGMII        yes               yes                         yes
     22  *
     23  * Each channel has to run the same rate. 
     24  * Invalid combination: 
     25  *    lane0 1G and lane1 2.5G, lane2 SGMII and lane1 2.5G
     26  * Valid combination:
     27  *    lane0 1G and lane1 SGMII, lane0 autoneg 1G and lane2 forced 1G.
     28  */
     29 
     30 #include <sal/types.h>
     31 
     32 #include <sal/types.h>
     33 #include <sal/core/spl.h>
     34 #include <shared/bsl.h>
     35 #include <soc/drv.h>
     36 #include <soc/debug.h>
     37 #include <soc/error.h>
     38 #include <soc/phyreg.h>
     39 #include <soc/port_ability.h>
     40 
     41 #include <soc/phy.h>
     42 #include <soc/phy/phyctrl.h>
     43 #include <soc/phy/drv.h>
     44 
     45 #include "phydefs.h"      /* Must include before other phy related includes */ 
     46 
     47 
     48 #if defined(INCLUDE_XGXS_16G)
     49 #include "phyconfig.h"     /* Must include before other phy related includes */
     50 #include "phyident.h"
     51 #include "phyreg.h"
     52 #include "phynull.h"
     53 #include "xgxs.h"
     54 #include "serdesid.h"
     55 #include "xgxs16g.h"
     56 
     57 #define PHY_XGXS16G_LANEPRBS_LANE_SHIFT   4
     58 
     59 
     60 #define XGXS16G_PLL_WAIT  250000
     61 
     62 STATIC int phy_xgxs16g1l_interface_get(int unit, soc_port_t port, 
     63                                        soc_port_if_t *pif);
     64 STATIC int phy_xgxs16g1l_master_get(int unit, soc_port_t port, int *master);
     65 STATIC int phy_xgxs16g1l_an_set(int unit, soc_port_t port, int an);
     66 STATIC int phy_xgxs16g1l_an_get(int unit, soc_port_t port,
     67                               int *an, int *an_done);
     68 STATIC int phy_xgxs16g1l_speed_get(int unit, soc_port_t port, int *speed);
     69 STATIC int phy_xgxs16g1l_ability_advert_set(int unit, soc_port_t port, 
     70                                          soc_port_ability_t *ability);
     71 STATIC int phy_xgxs16g1l_ability_advert_get(int unit, soc_port_t port,
     72                                          soc_port_ability_t *ability);
     73 STATIC int phy_xgxs16g1l_ability_local_get(int unit, soc_port_t port,
     74                                    soc_port_ability_t *ability); 
     75 STATIC int phy_xgxs16g1l_medium_config_set(int unit, soc_port_t port,
     76                                    soc_port_medium_t medium,  soc_phy_config_t *cfg);
     77 STATIC int phy_xgxs16g1l_medium_get(int unit, soc_port_t port, soc_port_medium_t *medium);
     78 
     79 /* Notify event forward declaration */
     80 STATIC int 
     81 _phy_xgxs16g1l_notify_duplex(int unit, soc_port_t port, uint32 duplex);
     82 STATIC int 
     83 _phy_xgxs16g1l_notify_speed(int unit, soc_port_t port, uint32 speed);
     84 STATIC int 
     85 _phy_xgxs16g1l_notify_stop(int unit, soc_port_t port, uint32 flags);
     86 STATIC int 
     87 _phy_xgxs16g1l_notify_resume(int unit, soc_port_t port, uint32 flags);
     88 STATIC int 
     89 _phy_xgxs16g1l_notify_interface(int unit, soc_port_t port, uint32 intf);
     90 STATIC int
     91 _phy_xgxs16g1l_control_vco_disturbed_set(int unit, soc_port_t port);
     92 STATIC int
     93 _phy_xgxs16g1l_control_vco_disturbed_get(int unit, soc_port_t port, uint32 *value);
     94 
     95 STATIC int
     96 _phy_xgxs16g1l_pll_lock_wait(int unit, soc_port_t port)
     97 {
     98     uint16           data16;
     99     phy_ctrl_t      *pc;
    100     soc_timeout_t    to;
    101     int              rv;
    102 
    103     pc = INT_PHY_SW_STATE(unit, port);
    104     _phy_xgxs16g1l_control_vco_disturbed_set(unit, port);
    105     soc_timeout_init(&to, XGXS16G_PLL_WAIT, 0);
    106     while (!soc_timeout_check(&to)) {
    107         rv = READ_XGXS16G_XGXSBLK0_XGXSSTATUSr(unit, pc, &data16);
    108         if ((data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK) ||
    109             SOC_FAILURE(rv)) {
    110             break;
    111         }
    112     }
    113     if ((data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK) == 0) {
    114         LOG_WARN(BSL_LS_SOC_PHY,
    115                  (BSL_META_U(unit,
    116                              "XGXS_16G : TXPLL did not lock: u=%d p=%d\n"),
    117                   unit, port));
    118         return (SOC_E_TIMEOUT);
    119     }
    120     return (SOC_E_NONE);
    121 }
    122 
    123 STATIC int
    124 _phy_xgxs16g1l_lane_swap(int unit, soc_port_t port)
    125 {
    126     phy_ctrl_t *pc;
    127     int i;
    128     uint16 lane_map;
    129     uint16 lane, hw_map, chk_map;
    130 
    131     pc = INT_PHY_SW_STATE(unit, port);
    132 
    133     /* Update RX lane map */
    134 
    135     if (soc_property_port_get_str(unit, port, spn_XGXS_RX_LANE_MAP)) {
    136         lane_map = soc_property_port_get(unit, port,
    137                                     spn_XGXS_RX_LANE_MAP, 0x0123) & 0xffff;
    138         hw_map  = 0;
    139         chk_map = 0;
    140 
    141         /* contruct lane swap map in register format */
    142         for (hw_map=0, i = 3; i >= 0; i--) {
    143             lane  = (lane_map >> (i * 4)) & 0xf;
    144             hw_map  |= lane << ((3 - i) * 2);
    145             chk_map |= 1 << lane;
    146         }
    147         
    148         /* check if valid configuration */
    149         if (chk_map == 0xf) {
    150                 SOC_IF_ERROR_RETURN     /* Enable RX Lane swap */
    151                    (MODIFY_XGXS16G_XGXSBLK8_RXLNSWAP1r(unit, pc,
    152                        hw_map,
    153                        XGXSBLK2_RXLNSWAP_RX_LNSWAP_EN_MASK |
    154                        XGXSBLK8_RXLNSWAP1_RX0_LNSWAP_SEL_MASK |
    155                        XGXSBLK8_RXLNSWAP1_RX1_LNSWAP_SEL_MASK |
    156                        XGXSBLK8_RXLNSWAP1_RX2_LNSWAP_SEL_MASK |
    157                        XGXSBLK8_RXLNSWAP1_RX3_LNSWAP_SEL_MASK));
    158         } else {
    159             LOG_WARN(BSL_LS_SOC_PHY,
    160                      (BSL_META_U(unit,
    161                                  "unit %d port %s: Invalid RX lane map 0x%04x.\n"),
    162                       unit, SOC_PORT_NAME(unit, port), lane_map));
    163         }
    164     }
    165 
    166     /* Update TX lane map */
    167     if (soc_property_port_get_str(unit, port, spn_XGXS_TX_LANE_MAP)) {
    168         lane_map = soc_property_port_get(unit, port,
    169                                         spn_XGXS_TX_LANE_MAP, 0x0123) & 0xffff;
    170         hw_map  = 0;
    171         chk_map = 0;
    172 
    173         /* contruct lane swap map in register format */
    174         for (hw_map=0, i = 3; i >= 0; i--) {
    175             lane  = (lane_map >> (i * 4)) & 0xf;
    176             hw_map  |= lane << ((3 - i) * 2);
    177             chk_map |= 1 << lane;
    178         }
    179         if (chk_map == 0xf) {
    180             SOC_IF_ERROR_RETURN     /* Enable TX Lane swap */
    181                (MODIFY_XGXS16G_XGXSBLK8_TXLNSWAP1r(unit, pc,
    182                     hw_map,
    183                     XGXSBLK8_TXLNSWAP1_TX3_LNSWAP_SEL_MASK |
    184                     XGXSBLK8_TXLNSWAP1_TX2_LNSWAP_SEL_MASK |
    185                     XGXSBLK8_TXLNSWAP1_TX1_LNSWAP_SEL_MASK |
    186                     XGXSBLK8_TXLNSWAP1_TX0_LNSWAP_SEL_MASK));
    187         } else {
    188             LOG_WARN(BSL_LS_SOC_PHY,
    189                      (BSL_META_U(unit,
    190                                  "unit %d port %s: Invalid TX lane map 0x%04x.\n"),
    191                       unit, SOC_PORT_NAME(unit, port), lane_map));
    192         }
    193     }
    194     return SOC_E_NONE;
    195 }
    196 
    197 STATIC int
    198 _phy_xgxs16g1l_polarity_flip(int unit, soc_port_t port)
    199 {
    200     uint16      data16;
    201     uint16      mask16;
    202     phy_ctrl_t *pc;
    203     uint32      phy_xaui_polarity_flip;
    204 
    205     pc = INT_PHY_SW_STATE(unit, port);
    206 
    207     if (soc_property_port_get_str(unit, port, spn_PHY_XAUI_TX_POLARITY_FLIP)) {
    208         phy_xaui_polarity_flip = soc_property_port_get(unit, port,
    209                                               spn_PHY_XAUI_TX_POLARITY_FLIP, 0);
    210         /* Flip TX polarity */
    211         mask16 = TX0_TX_ACONTROL0_TXPOL_FLIP_MASK;
    212         data16 = phy_xaui_polarity_flip? mask16:0;
    213         LOG_INFO(BSL_LS_SOC_PHY,
    214                  (BSL_META_U(unit,
    215                              "unit %d port %s: TX Polarity swap 0x%04x.\n"),
    216                   unit, SOC_PORT_NAME(unit, port), data16));
    217         if (pc->lane_num == 0) {
    218             SOC_IF_ERROR_RETURN
    219               (MODIFY_XGXS16G_TX0_TX_ACONTROL0r(unit, pc, data16, mask16));
    220         } else if (pc->lane_num == 1) {
    221             SOC_IF_ERROR_RETURN
    222               (MODIFY_XGXS16G_TX1_TX_ACONTROL0r(unit, pc, data16, mask16));
    223         } else if (pc->lane_num == 2) {
    224             SOC_IF_ERROR_RETURN
    225               (MODIFY_XGXS16G_TX2_TX_ACONTROL0r(unit, pc, data16, mask16));
    226         } else {
    227             SOC_IF_ERROR_RETURN
    228               (MODIFY_XGXS16G_TX3_TX_ACONTROL0r(unit, pc, data16, mask16));
    229         }
    230     }
    231 
    232     if (soc_property_port_get_str(unit, port, spn_PHY_XAUI_RX_POLARITY_FLIP)) {
    233         phy_xaui_polarity_flip = soc_property_port_get(unit, port,
    234                                               spn_PHY_XAUI_RX_POLARITY_FLIP, 0);
    235         /* Flip RX polarity. */
    236         /*XXX hardcoded for now */
    237         mask16 = 0xc;
    238         data16 = phy_xaui_polarity_flip? mask16 :0;
    239         LOG_INFO(BSL_LS_SOC_PHY,
    240                  (BSL_META_U(unit,
    241                              "unit %d port %s: RX Polarity swap 0x%04x.\n"),
    242                   unit, SOC_PORT_NAME(unit, port), data16));
    243 
    244         SOC_IF_ERROR_RETURN
    245             (XGXS16G_REG_MODIFY(unit,pc,0x0, 0x80ba + (0x10 * pc->lane_num),
    246                  data16, mask16));
    247     }
    248     return SOC_E_NONE;
    249 }
    250 
    251 /*
    252  * Function:
    253  *      phy_xgxs16g1l_init
    254  * Purpose:     
    255  *      Initialize xgxs6 phys
    256  * Parameters:
    257  *      unit - StrataSwitch unit #.
    258  *      port - StrataSwitch port #. 
    259  * Returns:     
    260  *      SOC_E_NONE
    261  */
    262 
    263 STATIC int
    264 phy_xgxs16g1l_init(int unit, soc_port_t port)
    265 {
    266     uint16              data16;
    267     uint16              mask16;
    268     uint16             mode_1000x;
    269     int                 preemph, idriver, pdriver;
    270     phy_ctrl_t         *pc;
    271     soc_port_ability_t  ability;
    272     XGXS16G_DEV_DESC *pDesc;
    273     soc_phy_info_t *pi;
    274     int len;
    275     int serdes_id0;
    276     int asymmetric_speed_mode = 0;
    277     uint16              rx_los = 0;
    278     uint16              rx_los_invert = 0;
    279 
    280 
    281     pc = INT_PHY_SW_STATE(unit, port);
    282     pDesc = (XGXS16G_DEV_DESC *)(pc + 1);
    283 
    284     asymmetric_speed_mode = soc_property_port_get(unit, port, spn_SERDES_ASYMMETRIC_SPEED_MODE, 0);
    285 
    286     SOC_IF_ERROR_RETURN
    287         (READ_XGXS16G_SERDESID_SERDESID0r(unit, pc, &pDesc->serdes_id0));
    288     serdes_id0 = pDesc->serdes_id0;
    289     SOC_IF_ERROR_RETURN
    290         (READ_XGXS16G_SERDESID_SERDESID2r(unit, pc, &pDesc->serdes_id2));
    291 
    292     /* compose device name/instance/lane information for display
    293      * XGXS_16G device uses existing method
    294      */
    295     if (XGXS16G_13G_ID(pc) || XGXS16G_2p5G_ID(pc)) {
    296         if (XGXS16G_13G_ID(pc)) {
    297         /* 
    298          * COVERITY
    299          *
    300          * Buffer will not happen as destination string is of length 30.
    301          */
    302         /* coverity[secure_coding] */
    303 
    304             sal_strcpy(pDesc->name,"XGXS13G-");
    305         } else {
    306             sal_strcpy(pDesc->name,"QS-");
    307         }
    308         len = sal_strlen(pDesc->name);
    309         /* add rev letter */
    310         pDesc->name[len++] = 'A' + ((serdes_id0 >>
    311                           SERDESID_SERDESID0_REV_LETTER_SHIFT) & 0x3);
    312         /* add rev number */
    313         pDesc->name[len++] = '0' + ((serdes_id0 >>
    314                           SERDESID_SERDESID0_REV_NUMBER_SHIFT) & 0x7);
    315         pDesc->name[len++] = '/';
    316         pDesc->name[len++] = (pc->chip_num/10)%10 + '0';
    317         pDesc->name[len++] = pc->chip_num%10 + '0';
    318         pDesc->name[len++] = '/';
    319         pDesc->name[len++] = pc->lane_num + '0';
    320         pDesc->name[len] = 0;  /* string terminator */
    321 
    322         if (len > XGXS16G_LANE_NAME_LEN) {
    323             LOG_ERROR(BSL_LS_SOC_PHY,
    324                       (BSL_META_U(unit,
    325                                   "XGXS13G info string length %d exceeds max length 0x%x: u=%d p=%d\n"),
    326                        len,XGXS16G_LANE_NAME_LEN,unit, port));
    327             return SOC_E_MEMORY;
    328         }
    329 
    330         pi = &SOC_PHY_INFO(unit, port);
    331         if (!PHY_EXTERNAL_MODE(unit, port)) {
    332             pi->phy_name = pDesc->name;
    333         }
    334 
    335     }
    336 
    337     /* Initialize software state */
    338     pc->fiber.autoneg_enable = TRUE;
    339 
    340     if ((!PHY_FLAGS_TST(unit, port, PHY_FLAGS_INIT_DONE)) &&
    341        (pc->lane_num == 0)) {
    342 
    343         /* Reset the core */
    344 
    345         /* Stop PLL Sequencer and configure the core into correct mode */
    346         data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane <<
    347                     XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) |
    348                  XGXSBLK0_XGXSCONTROL_HSTL_MASK |
    349                  XGXSBLK0_XGXSCONTROL_CDET_EN_MASK |
    350                  XGXSBLK0_XGXSCONTROL_EDEN_MASK |
    351                  XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK |
    352                  XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK;
    353         SOC_IF_ERROR_RETURN
    354             (WRITE_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, data16)); 
    355 
    356         /* Disable IEEE block select auto-detect. 
    357          * The driver will select desired block as necessary.
    358          * By default, the driver keeps the XAUI block in
    359          * IEEE address space.
    360          */
    361         if (XGXS16G_2p5G_ID(pc)) {
    362             data16 = 0;
    363         } else {
    364             data16 = XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK;
    365         }
    366         SOC_IF_ERROR_RETURN
    367             (MODIFY_XGXS16G_XGXSBLK0_MISCCONTROL1r(unit, pc, 
    368                            data16,
    369                            XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK |
    370                            XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK));
    371 
    372         if (XGXS16G_13G_ID(pc)) {  
    373             data16 = XGXSBLK0_MMDSELECT_MULTIPRTS_EN_MASK |
    374                      XGXSBLK0_MMDSELECT_MULTIMMDS_EN_MASK;
    375             mask16 = data16;
    376 #ifdef BCM_KATANA_SUPPORT
    377             if (SOC_IS_KATANA(unit)) {
    378                 if ((25 == port) || (26 == port)) {
    379                     data16 &= ~XGXSBLK0_MMDSELECT_MULTIPRTS_EN_MASK;
    380                 }
    381             }
    382 #endif
    383             SOC_IF_ERROR_RETURN
    384                 (MODIFY_XGXS16G_XGXSBLK0_MMDSELECTr(unit, pc,
    385                            data16, mask16));
    386         }
    387 
    388         /* disable in-band MDIO. PHY-443 */
    389         SOC_IF_ERROR_RETURN
    390             (XGXS16G_REG_MODIFY(unit, pc, 0x00, 0x8111, 1 << 3, 1 << 3));
    391 
    392 
    393         if (XGXS16G_13G_REV_B0(pc) && asymmetric_speed_mode) { 
    394         
    395             /* FORCE ASYMMETRIC SPEED MODES. Refer sect 4.3.2 product brief. */
    396             
    397             /*
    398                1. Force VCO at 3.125GHz by configuring 
    399                   Misc1 register (0x8308) so that 
    400                   Misc1[12] = 1'b1; 
    401                   Misc[11:8] = 4'h1.
    402              */
    403             SOC_IF_ERROR_RETURN
    404                (MODIFY_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, 
    405                           SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_SEL_MASK
    406                             | (0x1 << SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_SHIFT),
    407                           SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_SEL_MASK
    408                             | SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_MASK));
    409             /*
    410                2. Enable the asymmetric_enable 
    411                   bit[BIT8] within the xgxsBlk8txLnSwap1 register (0x8169)
    412              */
    413 
    414             SOC_IF_ERROR_RETURN
    415                (MODIFY_XGXS16G_XGXSBLK8_TXLNSWAP1r(unit, pc, 
    416                           XGXSBLK8_TXLNSWAP1_ASYMM_EN_MASK,
    417                           XGXSBLK8_TXLNSWAP1_ASYMM_EN_MASK));
    418 
    419            } 
    420 
    421     }
    422 
    423     if (XGXS16G_13G_ID(pc)) {  
    424         SOC_IF_ERROR_RETURN
    425             (MODIFY_XGXS16G_REMOTEPHY_MISC3r(unit, pc,
    426                                              0, (1 << 6)));
    427     }
    428 
    429     /* check if need to do lane swap */
    430     if (FEATURE_NEW_LANESWAP(pc)) {
    431         SOC_IF_ERROR_RETURN
    432             (_phy_xgxs16g1l_lane_swap(unit,port)); 
    433     }
    434 
    435     /* check if need to polarity flip */
    436     SOC_IF_ERROR_RETURN
    437         (_phy_xgxs16g1l_polarity_flip(unit,port)); 
    438 
    439     if (soc_property_port_get(unit, port,
    440                           spn_PHY_AN_C73, FALSE)) {
    441          PHY_FLAGS_SET(unit, port, PHY_FLAGS_C73);
    442     }
    443 
    444     /* disable CL73 BAM */
    445     SOC_IF_ERROR_RETURN
    446         (MODIFY_XGXS16G_AN_CL73_REG(unit,pc,0x8372,
    447                0,
    448                CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK));
    449 
    450     if (!PHY_CLAUSE73_MODE(unit, port)) {
    451         /* disable CL73 AN device*/
    452         SOC_IF_ERROR_RETURN
    453             (WRITE_XGXS16G_AN_CL73_REG(unit,pc,MII_CTRL_REG,0));
    454     }
    455 
    456     /* Set Local Advertising Configuration */
    457     SOC_IF_ERROR_RETURN
    458         (phy_xgxs16g1l_ability_local_get(unit, port, &ability));
    459     /* Do not advertise 2.5G. 1Gbps vs 2.5 Gbps AN is not supported */
    460     ability.speed_full_duplex &= SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB |
    461                                  SOC_PA_SPEED_1000MB;
    462     pc->fiber.advert_ability = ability;
    463     SOC_IF_ERROR_RETURN
    464         (phy_xgxs16g1l_ability_advert_set(unit, port, &ability));
    465                                                                                 
    466     /* Disable BAM in Independent Lane mode. Over1G AN not supported  */
    467     SOC_IF_ERROR_RETURN
    468         (WRITE_XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr(unit, pc, 0));
    469     SOC_IF_ERROR_RETURN
    470         (WRITE_XGXS16G_BAM_NEXTPAGE_UD_FIELDr(unit, pc, 0));
    471                                                                                 
    472     data16 = SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK |
    473              SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK;
    474     SOC_IF_ERROR_RETURN
    475         (WRITE_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, data16));
    476 
    477     mask16 = SERDESDIGITAL_CONTROL1000X1_AUTODET_EN_MASK |
    478              SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK |
    479              SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
    480     /*
    481      * Configure signal auto-detection between SGMII and fiber.
    482      * This detection only works if auto-negotiation is enabled.
    483      */
    484     if (soc_property_port_get(unit, port, 
    485                               spn_SERDES_AUTOMEDIUM, FALSE)) {
    486         data16 |= SERDESDIGITAL_CONTROL1000X1_AUTODET_EN_MASK;
    487     }
    488 
    489     /*
    490      * Put the Serdes in Fiber or SGMII mode
    491      */
    492     mode_1000x = 0;
    493     if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) ||
    494         PHY_PASSTHRU_MODE(unit, port)) {
    495         mode_1000x = SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
    496     }
    497     /* Allow property to override */
    498     if (soc_property_port_get(unit, port,
    499                               spn_SERDES_FIBER_PREF, mode_1000x)) {
    500         data16 |= SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
    501     } else {
    502         data16 &= ~SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
    503     }
    504 
    505     SOC_IF_ERROR_RETURN
    506         (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, data16, mask16));   
    507     if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) ||
    508         PHY_PASSTHRU_MODE(unit, port) ||
    509         PHY_SGMII_AUTONEG_MODE(unit, port)) {
    510         /* Enable 1000X parallel detect */
    511         data16 = SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK;
    512         mask16 = SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK;
    513     } else {
    514         data16 = 0;
    515         mask16 = SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK |
    516                  SERDESDIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_MASK;
    517     }
    518     SOC_IF_ERROR_RETURN
    519         (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc, data16, mask16));
    520 
    521     /* Initialialize autoneg and fullduplex */
    522     data16 = MII_CTRL_FD | MII_CTRL_SS_1000;
    523     if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) ||
    524         PHY_PASSTHRU_MODE(unit, port) ||
    525         PHY_SGMII_AUTONEG_MODE(unit, port)) {
    526         data16 |= MII_CTRL_AE | MII_CTRL_RAN;
    527     }
    528     SOC_IF_ERROR_RETURN
    529         (WRITE_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, data16));
    530 
    531     if (PHY_CLAUSE73_MODE(unit, port)) {
    532         SOC_IF_ERROR_RETURN
    533             (MODIFY_XGXS16G_AN_CL73_REG(unit, pc,MII_CTRL_REG,
    534                                           data16,
    535                                           MII_CTRL_AE | MII_CTRL_RAN));
    536     }
    537 
    538     /* Disable 10G parallel detect */
    539     SOC_IF_ERROR_RETURN
    540         (WRITE_XGXS16G_AN73_PDET_PARDET10GCONTROLr(unit, pc, 0));
    541 
    542     /* Disable BAM mode and Teton mode */
    543     SOC_IF_ERROR_RETURN
    544         (WRITE_XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr(unit, pc, 0));
    545 
    546     /* Initialize XAUI to reasonable default settings */
    547     if (XGXS16G_13G_ID(pc) || XGXS16G_2p5G_ID(pc)){
    548         preemph = 0;
    549         idriver = 4;
    550         preemph = soc_property_port_get(unit, port, spn_XGXS_PREEMPHASIS, preemph);
    551         idriver = soc_property_port_get(unit, port, spn_XGXS_DRIVER_CURRENT, idriver);
    552         data16  = ((preemph & 0xf) << TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_SHIFT) |
    553                   ((idriver & 0x7) << TX_ALL_040_TX_DRIVER_IDRIVER_SHIFT);
    554         mask16  = TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_MASK |
    555                   TX_ALL_040_TX_DRIVER_IDRIVER_MASK;
    556         switch(pc->lane_num){
    557             case 0:
    558                 SOC_IF_ERROR_RETURN
    559                     (MODIFY_XGXS13G_040_TX0_ACONTROL1r(unit, pc, data16, mask16));
    560                 break;
    561             case 1:
    562                 SOC_IF_ERROR_RETURN
    563                     (MODIFY_XGXS13G_040_TX1_ACONTROL1r(unit, pc, data16, mask16));
    564                 break;
    565             case 2:
    566                 SOC_IF_ERROR_RETURN
    567                     (MODIFY_XGXS13G_040_TX2_ACONTROL1r(unit, pc, data16, mask16));
    568                 break;
    569             case 3:
    570                 SOC_IF_ERROR_RETURN
    571                     (MODIFY_XGXS13G_040_TX3_ACONTROL1r(unit, pc, data16, mask16));
    572                 break;
    573             default:
    574                 SOC_IF_ERROR_RETURN
    575                     (MODIFY_XGXS13G_040_TX_ALL_ACONTROL1r(unit, pc, data16, mask16));
    576                 break;
    577         }
    578     } else {
    579         preemph = 0;
    580         idriver = 9;
    581         pdriver = 9;
    582         preemph = soc_property_port_get(unit, port, spn_XGXS_PREEMPHASIS, preemph);
    583         idriver = soc_property_port_get(unit, port, spn_XGXS_DRIVER_CURRENT, idriver);
    584         pdriver = soc_property_port_get(unit, port, spn_XGXS_PRE_DRIVER_CURRENT, pdriver);
    585         data16  = ((preemph & 0xf) << TX_ALL_TX_DRIVER_PREEMPHASIS_SHIFT) |
    586                   ((idriver & 0xf) << TX_ALL_TX_DRIVER_IDRIVER_SHIFT) |
    587                   ((pdriver & 0xf) << TX_ALL_TX_DRIVER_IPREDRIVER_SHIFT);
    588         mask16  = TX_ALL_TX_DRIVER_PREEMPHASIS_MASK |
    589                   TX_ALL_TX_DRIVER_IDRIVER_MASK |
    590                   TX_ALL_TX_DRIVER_IPREDRIVER_MASK;
    591         switch(pc->lane_num){
    592             case 0:
    593                 SOC_IF_ERROR_RETURN
    594                     (MODIFY_XGXS16G_TX0_TX_DRIVERr(unit, pc, data16, mask16));
    595                 break;
    596             case 1:
    597                 SOC_IF_ERROR_RETURN
    598                     (MODIFY_XGXS16G_TX1_TX_DRIVERr(unit, pc, data16, mask16));
    599                 break;
    600             case 2:
    601                 SOC_IF_ERROR_RETURN
    602                     (MODIFY_XGXS16G_TX2_TX_DRIVERr(unit, pc, data16, mask16));
    603                 break;
    604             case 3:
    605                 SOC_IF_ERROR_RETURN
    606                     (MODIFY_XGXS16G_TX3_TX_DRIVERr(unit, pc, data16, mask16));
    607                 break;
    608             default:
    609                 SOC_IF_ERROR_RETURN
    610                     (MODIFY_XGXS16G_TX_ALL_TX_DRIVERr(unit, pc, data16, mask16));
    611                 break;
    612         }
    613     }
    614 
    615     /* Enable lanes */
    616     mask16 = XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK |
    617              XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK;
    618     data16 = mask16;
    619     SOC_IF_ERROR_RETURN
    620       (MODIFY_XGXS16G_XGXSBLK1_LANECTRL0r(unit, pc, data16, mask16));
    621 
    622     /* set elasticity fifo size to 13.5k to support 12k jumbo pkt size*/
    623     SOC_IF_ERROR_RETURN
    624         (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X3r(unit,pc,
    625                    (1 << 2),
    626                    SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK));
    627 
    628     /* Enabble LPI passthru' for native mode EEE */
    629     if (pc->dev_name && !(sal_strcmp(pc->dev_name, "XGXS13G1l") && sal_strcmp(pc->dev_name, "QS40"))) {
    630         /* Enabble LPI passthru' for native mode EEE */
    631         SOC_IF_ERROR_RETURN
    632              (MODIFY_XGXS16G_REMOTEPHY_MISC5r(unit, pc, 0xc000, 0xc000));
    633         SOC_IF_ERROR_RETURN
    634              (MODIFY_XGXS16G_XGXSBLK7_EEECONTROLr(unit, pc, 0x0007, 0x0007));
    635     }
    636 
    637     if ((!PHY_FLAGS_TST(unit, port, PHY_FLAGS_INIT_DONE)) && 
    638         (pc->lane_num == 0)) {
    639         /* Start PLL Sequencer and wait for PLL to lock */
    640         SOC_IF_ERROR_RETURN
    641             (MODIFY_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc,
    642                                  XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK,
    643                                  XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK));
    644         (void) _phy_xgxs16g1l_pll_lock_wait(unit, port);
    645     }
    646 
    647  /* PRBS Polynomial for all lanes: 0x8019=0x0000 */
    648 
    649     SOC_IF_ERROR_RETURN
    650         (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, 0));
    651 
    652     /* ************************************************************************/
    653     /* Speical case handling for KT2:OLP port(MXQ10:lane2).Lane0,1,3 not used */
    654     /* ************************************************************************/
    655 
    656 #ifdef BCM_KATANA2_SUPPORT
    657     if ((SOC_IS_KATANA2(unit)) && 
    658         (SOC_INFO(unit).olp_port[0]) && 
    659         (port == 40) && /* OLP PORT surely */
    660         (!(soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE))) {
    661         /* Set Broadcast mode */
    662         SOC_IF_ERROR_RETURN(WRITE_XGXS16G_AERBLK_AERr(unit, pc, 0x1F));
    663         /* Disable PLL */
    664         SOC_IF_ERROR_RETURN(
    665                      WRITE_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, 0x062f));
    666         /* Put serdes in 4 * 2.5G symmetric mode then */
    667         SOC_IF_ERROR_RETURN(
    668                      WRITE_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, 0x6010));
    669         /* Enable PLL */
    670         SOC_IF_ERROR_RETURN(
    671                      WRITE_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, 0x262f));
    672     }
    673 #endif
    674     /* Check if HW rx los is configured */
    675     data16 = 0;
    676     mask16 = SERDESDIGITAL_CONTROL1000X1_SIGNAL_DETECT_EN_MASK |
    677              SERDESDIGITAL_CONTROL1000X1_INVERT_SIGNAL_DETECT_MASK;
    678     if (soc_property_port_get(unit, port,
    679                               spn_SERDES_RX_LOS, rx_los)) {
    680         data16 = SERDESDIGITAL_CONTROL1000X1_SIGNAL_DETECT_EN_MASK;
    681     }
    682     if (soc_property_port_get(unit, port,
    683                               spn_SERDES_RX_LOS_INVERT, rx_los_invert)) {
    684         data16 |= SERDESDIGITAL_CONTROL1000X1_INVERT_SIGNAL_DETECT_MASK;
    685     } 
    686     SOC_IF_ERROR_RETURN(
    687         MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, data16, mask16));
    688 
    689     return (SOC_E_NONE);
    690 }
    691 
    692 /*
    693  * Function:
    694  *      phy_xgxs16g1l_link_get
    695  * Purpose:
    696  *      Get layer2 connection status.
    697  * Parameters:
    698  *      unit - StrataSwitch unit #.
    699  *      port - StrataSwitch port #. 
    700  *      link - address of memory to store link up/down state.
    701  * Returns:     
    702  *      SOC_E_NONE
    703  */
    704 
    705 STATIC int
    706 phy_xgxs16g1l_link_get(int unit, soc_port_t port, int *link)
    707 {
    708     phy_ctrl_t *pc;
    709     uint16  mii_serdes_stat;
    710 
    711     if (PHY_DISABLED_MODE(unit, port)) {
    712         *link = FALSE;
    713         return (SOC_E_NONE);
    714     }
    715 
    716     pc = INT_PHY_SW_STATE(unit, port);
    717 
    718     SOC_IF_ERROR_RETURN
    719         (READ_XGXS16G_COMBO_IEEE0_MIISTATr(unit, pc, &mii_serdes_stat));
    720 
    721     *link = ((mii_serdes_stat & MII_STAT_LA) != 0);
    722 
    723     return (SOC_E_NONE);
    724 }
    725 
    726 /*
    727  * Function:
    728  *      phy_xgxs16g1l_enable_set
    729  * Purpose:
    730  *      Enable/Disable phy 
    731  * Parameters:
    732  *      unit - StrataSwitch unit #.
    733  *      port - StrataSwitch port #. 
    734  *      enable - on/off state to set
    735  * Returns:     
    736  *      SOC_E_NONE
    737  */
    738 
    739 STATIC int
    740 phy_xgxs16g1l_enable_set(int unit, soc_port_t port, int enable)
    741 {
    742     int rv;
    743 
    744     if (enable) {
    745         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
    746         rv = _phy_xgxs16g1l_notify_resume(unit, port, PHY_STOP_PHY_DIS);
    747     } else {
    748         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
    749         rv = _phy_xgxs16g1l_notify_stop(unit, port, PHY_STOP_PHY_DIS);
    750     }
    751 
    752     return (rv);
    753 }
    754 
    755 /*
    756  * Function:
    757  *      phy_xgxs16g1l_speed_set
    758  * Purpose:
    759  *      Set PHY speed
    760  * Parameters:
    761  *      unit - StrataSwitch unit #.
    762  *      port - StrataSwitch port #. 
    763  *      speed - link speed in Mbps
    764  * Returns:     
    765  *      SOC_E_NONE
    766  */
    767 
    768 STATIC int
    769 phy_xgxs16g1l_speed_set(int unit, soc_port_t port, int speed)
    770 {
    771     phy_ctrl_t  *pc;
    772     phy_ctrl_t  *local_pc;
    773     uint16      speed_val, mask;
    774     uint16      sgmii_status = 0, data16, temp16;
    775     uint16      speed_mii;
    776     int asymmetric_speed_mode = 0;
    777     int blk_num = 0;
    778     soc_pbmp_t blk_pbmp;
    779     soc_port_t local_port = 0;
    780 
    781     pc = INT_PHY_SW_STATE(unit, port);
    782                                                                                
    783     if (speed > 2500) {
    784         return (SOC_E_CONFIG);
    785     }
    786 
    787     speed_val = 0;
    788     speed_mii = 0;
    789     mask      = SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK |
    790                 SERDESDIGITAL_MISC1_FORCE_SPEED_MASK;
    791 
    792     asymmetric_speed_mode = soc_property_port_get(unit, port, spn_SERDES_ASYMMETRIC_SPEED_MODE, 0);
    793     
    794     switch (speed) {
    795     case 0:
    796         /* Do not change speed */
    797         return SOC_E_NONE;
    798     case 10:
    799         speed_mii = MII_CTRL_SS_10;
    800         break;
    801     case 100:
    802         speed_mii = MII_CTRL_SS_100;
    803         break;
    804     case 1000:
    805         speed_mii = MII_CTRL_SS_1000;
    806         break;
    807     case 2500:
    808         speed_val = 0;
    809         break;
    810     default:
    811         return SOC_E_PARAM;
    812     }
    813 
    814     /* 2.5G only valid in fiber mode */
    815     if (speed == 2500) {
    816         speed_val |= SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK;
    817     }
    818 
    819     /* Hold rxSeqStart */
    820     SOC_IF_ERROR_RETURN
    821         (MODIFY_XGXS16G_RX0_RX_CONTROLr(unit, pc,
    822                                   DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK,
    823                                   DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK));
    824                                                                                
    825     /* hold TX FIFO in reset */
    826     SOC_IF_ERROR_RETURN
    827         (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X3r(unit, pc,
    828                            SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK,
    829                            SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK));
    830 
    831     if(XGXS16G_13G_REV_B0(pc) && asymmetric_speed_mode) {
    832 
    833         /*  FORCE ASYMMETRIC SPEED MODES. Refer sect 4.3.2 product brief.
    834             Initial setup is done under init()
    835 
    836             (RESET TX and RX lane) 
    837 
    838            1. Set anaTxAControl1 7th bit 
    839            (Lane0 - 0x8065[6]; 
    840             Lane1 - 0x8075[6]; 
    841             Lane2 - 0x8085[6]; 
    842             Lane3 - 0x8095[6]; 
    843             All lanes - 0x80A5[6];) 
    844            if rates are 1G or less than 1G. 
    845            Keep this bit at the default value 1'b0, if the rate is 2.5G.
    846         
    847            2. Set anaRxAControl1 7th bit 
    848            (Lane0 - 0x80BC[6];
    849             Lane1 - 0x80CC[6]; 
    850             Lane2 - 0x80DC[6]; 
    851             Lane3 - 0x80EC[6]; 
    852             All lanes - 0x80FC[6];) 
    853             if rates are 1G or less than 1G. 
    854             Keep this bit at the default value 1'b0, if the rate is 2.5G.
    855 
    856            3. Set laneCtrl1 (0x8016), so that each lane is in OS1 mode.
    857               For OS1, set mode value = 2'b11 = 0x3
    858 
    859       */
    860         temp16 = 0x0;
    861         if( speed <= 1000) {
    862             temp16 = 0x1 << 6;
    863         }
    864         
    865         /* Reset lane - tx & rx */
    866         SOC_IF_ERROR_RETURN
    867             (MODIFY_XGXS16G_XGXSBLK2_LANERESETr(unit, pc,
    868                                  ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT)
    869                                | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT),
    870                                  ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT)
    871                                | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT)));
    872 
    873         switch(pc->lane_num) {
    874             case 0:
    875                 SOC_IF_ERROR_RETURN
    876                     (MODIFY_XGXS16G_TX0_TX_BGVCMr(unit, pc,
    877                                              temp16,
    878                                              TX0_TX_BGVCM_TICKSEL_MASK));
    879                 SOC_IF_ERROR_RETURN
    880                     (MODIFY_XGXS16G_RX0_RX_ANALOGBIAS0r(unit, pc,
    881                                              temp16,
    882                                              RX0_RX_ANALOGBIAS0_SIG_PWRDN_MASK));
    883                 SOC_IF_ERROR_RETURN
    884                     (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc,
    885                                             0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN0_SHIFT
    886                                           | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN0_SHIFT,
    887                                             XGXSBLK1_LANECTRL1_RX1G_MODE_LN0_MASK
    888                                           | XGXSBLK1_LANECTRL1_TX1G_MODE_LN0_MASK));
    889                 break;
    890             case 1:
    891                 SOC_IF_ERROR_RETURN
    892                     (MODIFY_XGXS16G_TX1_TX_BGVCMr(unit, pc,
    893                                              temp16,
    894                                              TX1_TX_BGVCM_TICKSEL_MASK));
    895                 SOC_IF_ERROR_RETURN
    896                     (MODIFY_XGXS16G_RX1_RX_ANALOGBIAS0r(unit, pc,
    897                                              temp16,
    898                                              RX1_RX_ANALOGBIAS0_SIG_PWRDN_MASK));
    899                 SOC_IF_ERROR_RETURN
    900                     (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc,
    901                                             0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN1_SHIFT
    902                                           | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN1_SHIFT,
    903                                             XGXSBLK1_LANECTRL1_RX1G_MODE_LN1_MASK
    904                                           | XGXSBLK1_LANECTRL1_TX1G_MODE_LN1_MASK));
    905                 break;
    906             case 2:
    907                 SOC_IF_ERROR_RETURN
    908                     (MODIFY_XGXS16G_TX2_TX_BGVCMr(unit, pc,
    909                                              temp16,
    910                                              TX2_TX_BGVCM_TICKSEL_MASK));
    911                 SOC_IF_ERROR_RETURN
    912                     (MODIFY_XGXS16G_RX2_RX_ANALOGBIAS0r(unit, pc,
    913                                              temp16,
    914                                              RX2_RX_ANALOGBIAS0_SIG_PWRDN_MASK));
    915                 SOC_IF_ERROR_RETURN
    916                     (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc,
    917                                             0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN2_SHIFT
    918                                           | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN2_SHIFT,
    919                                             XGXSBLK1_LANECTRL1_RX1G_MODE_LN2_MASK
    920                                           | XGXSBLK1_LANECTRL1_TX1G_MODE_LN2_MASK));
    921                 break;
    922             case 3:
    923                 SOC_IF_ERROR_RETURN
    924                     (MODIFY_XGXS16G_TX3_TX_BGVCMr(unit, pc,
    925                                              temp16,
    926                                              TX3_TX_BGVCM_TICKSEL_MASK));
    927                 SOC_IF_ERROR_RETURN
    928                     (MODIFY_XGXS16G_RX3_RX_ANALOGBIAS0r(unit, pc,
    929                                              temp16,
    930                                              RX3_RX_ANALOGBIAS0_SIG_PWRDN_MASK));
    931                 SOC_IF_ERROR_RETURN
    932                     (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc,
    933                                             0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN3_SHIFT
    934                                           | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN3_SHIFT,
    935                                             XGXSBLK1_LANECTRL1_RX1G_MODE_LN3_MASK
    936                                           | XGXSBLK1_LANECTRL1_TX1G_MODE_LN3_MASK));
    937                 break;
    938             default:
    939                return SOC_E_FAIL;
    940         }               
    941 
    942         if (speed <= 1000) {
    943             speed_val |= SERDESDIGITAL_MISC1_FORCE_LN_MODE_MASK;
    944             mask |= SERDESDIGITAL_MISC1_FORCE_LN_MODE_MASK;
    945         }
    946     }
    947 
    948     if (FEATURE_SPEED_100FX(pc)
    949         && IF_XGXS16G_13G_B0_IS_SYMMETRIC_MODE(pc, asymmetric_speed_mode)) {
    950         /* disable 100FX and 100FX auto-detect */
    951         SOC_IF_ERROR_RETURN
    952             (MODIFY_XGXS16G_FX100_CONTROL1r(unit,pc,
    953                               0,
    954                               FX100_CONTROL1_AUTODET_EN_MASK |
    955                               FX100_CONTROL1_ENABLE_MASK));
    956 
    957         /* disable 100FX idle detect */
    958         SOC_IF_ERROR_RETURN
    959             (MODIFY_XGXS16G_FX100_CONTROL3r(unit,pc,
    960                               FX100_CONTROL3_CORRELATOR_DISABLE_MASK,
    961                               FX100_CONTROL3_CORRELATOR_DISABLE_MASK));
    962         SOC_IF_ERROR_RETURN
    963             (READ_XGXS16G_SERDESDIGITAL_STATUS1000X1r(unit, pc, &sgmii_status));
    964 
    965         sgmii_status &= SERDESDIGITAL_STATUS1000X1_SGMII_MODE_MASK;
    966     }
    967 
    968     SOC_IF_ERROR_RETURN
    969         (MODIFY_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, speed_val, mask));
    970     
    971     if ( FEATURE_SPEED_100FX(pc)
    972          && (!sgmii_status && (speed == 100))
    973          && IF_XGXS16G_13G_B0_IS_SYMMETRIC_MODE(pc, asymmetric_speed_mode)) {
    974 		/* fiber mode 100fx, enable */
    975 		SOC_IF_ERROR_RETURN
    976 			(MODIFY_XGXS16G_FX100_CONTROL1r(unit,pc,
    977 						  FX100_CONTROL1_FAR_END_FAULT_EN_MASK |
    978 						  FX100_CONTROL1_ENABLE_MASK,
    979 						  FX100_CONTROL1_FAR_END_FAULT_EN_MASK |
    980 						  FX100_CONTROL1_ENABLE_MASK));
    981 
    982 		/* enable 100fx extended packet size */
    983 		SOC_IF_ERROR_RETURN
    984 			(MODIFY_XGXS16G_FX100_CONTROL2r(unit,pc,
    985 						FX100_CONTROL2_EXTEND_PKT_SIZE_MASK,
    986 						FX100_CONTROL2_EXTEND_PKT_SIZE_MASK));
    987 
    988     } else {
    989         SOC_IF_ERROR_RETURN
    990             (READ_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, &data16));
    991         data16 &= ~(MII_CTRL_SS_LSB | MII_CTRL_SS_MSB);
    992         data16 |= speed_mii;
    993         SOC_IF_ERROR_RETURN
    994             (WRITE_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, data16));
    995     }
    996 
    997 
    998     if(XGXS16G_13G_REV_B0(pc) && asymmetric_speed_mode) {
    999         /* Release Rx and Tx lane reset  */
   1000         SOC_IF_ERROR_RETURN
   1001             (MODIFY_XGXS16G_XGXSBLK2_LANERESETr(unit, pc, 0,
   1002                                  ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT)
   1003                                | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT)));
   1004 
   1005     }
   1006 
   1007 
   1008     /* release rxSeqStart */
   1009     SOC_IF_ERROR_RETURN
   1010         (MODIFY_XGXS16G_RX0_RX_CONTROLr(unit, pc,
   1011                               0,
   1012                               DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK));
   1013                                                                                
   1014     /* release TX FIFO reset */
   1015     SOC_IF_ERROR_RETURN
   1016         (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X3r(unit, pc,
   1017                            0,
   1018                            SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK));
   1019     
   1020     if (SOC_IS_KATANA(unit)) {
   1021         blk_num = SOC_PORT_BLOCK(unit, port);
   1022         SOC_PBMP_ASSIGN(blk_pbmp,SOC_BLOCK_BITMAP(unit,blk_num));
   1023         SOC_PBMP_ITER(blk_pbmp,local_port) {
   1024             local_pc = INT_PHY_SW_STATE(unit, local_port);
   1025             if (local_pc == NULL) {
   1026                 continue;
   1027             }
   1028             if ((local_pc->lane_num == 0) && !SOC_PORT_VALID(unit, local_port)) {
   1029                 SOC_IF_ERROR_RETURN(WRITE_XGXS16G_AERBLK_AERr(unit, pc, 0x1f));
   1030                 break;
   1031             }
   1032         }
   1033     }
   1034     
   1035     return (SOC_E_NONE);
   1036 }
   1037 
   1038 /*
   1039  * Function:
   1040  *      phy_xgxs16g1l_speed_get
   1041  * Purpose:
   1042  *      Get PHY speed
   1043  * Parameters:
   1044  *      unit - StrataSwitch unit #.
   1045  *      port - StrataSwitch port #. 
   1046  *      speed - current link speed in Mbps
   1047  * Returns:     
   1048  *      SOC_E_NONE
   1049  */
   1050 STATIC int
   1051 phy_xgxs16g1l_speed_get(int unit, soc_port_t port, int *speed)
   1052 {
   1053     uint16 data16;
   1054     phy_ctrl_t  *pc;
   1055 
   1056     pc = INT_PHY_SW_STATE(unit, port);
   1057 
   1058     if (NULL == speed) {
   1059         return (SOC_E_PARAM);
   1060     }
   1061  
   1062     SOC_IF_ERROR_RETURN
   1063         (READ_XGXS16G_SERDESDIGITAL_STATUS1000X1r(unit, pc, &data16));
   1064 
   1065     data16 &= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK;
   1066     data16 >>= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT;
   1067 
   1068     if (data16 == 3) {
   1069         *speed= 2500;
   1070     } else if (data16 == 2) {
   1071         *speed= 1000;
   1072     } else if (data16 == 1) {
   1073         *speed= 100;
   1074     } else {   
   1075         *speed= 10;
   1076     }    
   1077     
   1078     return (SOC_E_NONE);
   1079 }
   1080 
   1081 STATIC int
   1082 _force_asym_speedmod_set(int unit, soc_port_t port, int is_speed_2500)
   1083 {
   1084     int asymmetric_speed_mode ;
   1085     phy_ctrl_t  *pc;
   1086     uint16   temp16;
   1087 
   1088 
   1089     pc = INT_PHY_SW_STATE(unit, port);
   1090     asymmetric_speed_mode = soc_property_port_get(unit, port, spn_SERDES_ASYMMETRIC_SPEED_MODE, 0);
   1091     if(XGXS16G_13G_REV_B0(pc) && asymmetric_speed_mode) {
   1092 
   1093             /*  FORCE ASYMMETRIC SPEED MODES. Refer sect 4.3.2 product brief.
   1094                 Initial setup is done under init()
   1095 
   1096                 (RESET TX and RX lane)
   1097 
   1098                1. Set anaTxAControl1 7th bit
   1099                (Lane0 - 0x8065[6];
   1100                 Lane1 - 0x8075[6];
   1101                 Lane2 - 0x8085[6];
   1102                 Lane3 - 0x8095[6];
   1103                 All lanes - 0x80A5[6];)
   1104                if rates are 1G or less than 1G.
   1105                Keep this bit at the default value 1'b0, if the rate is 2.5G.
   1106 
   1107                2. Set anaRxAControl1 7th bit
   1108                (Lane0 - 0x80BC[6];
   1109                 Lane1 - 0x80CC[6];
   1110                 Lane2 - 0x80DC[6];
   1111                 Lane3 - 0x80EC[6];
   1112                 All lanes - 0x80FC[6];)
   1113                 if rates are 1G or less than 1G.
   1114                 Keep this bit at the default value 1'b0, if the rate is 2.5G.
   1115 
   1116                3. Set laneCtrl1 (0x8016), so that each lane is in OS1 mode.
   1117                   For OS1, set mode value = 2'b11 = 0x3
   1118 
   1119           */
   1120             temp16 = 0x0;
   1121             if(!is_speed_2500) {
   1122                 temp16 = 0x1 << 6;
   1123             }
   1124 
   1125             /* Reset lane - tx & rx */
   1126             SOC_IF_ERROR_RETURN
   1127                 (MODIFY_XGXS16G_XGXSBLK2_LANERESETr(unit, pc,
   1128                                      ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT)
   1129                                    | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT),
   1130                                      ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT)
   1131                                    | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT)));
   1132 
   1133             switch(pc->lane_num) {
   1134                 case 0:
   1135                     SOC_IF_ERROR_RETURN
   1136                         (MODIFY_XGXS16G_TX0_TX_BGVCMr(unit, pc,
   1137                                                  temp16,
   1138                                                  TX0_TX_BGVCM_TICKSEL_MASK));
   1139                     SOC_IF_ERROR_RETURN
   1140                         (MODIFY_XGXS16G_RX0_RX_ANALOGBIAS0r(unit, pc,
   1141                                                  temp16,
   1142                                                  RX0_RX_ANALOGBIAS0_SIG_PWRDN_MASK));
   1143                     SOC_IF_ERROR_RETURN
   1144                         (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc,
   1145                                                 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN0_SHIFT
   1146                                               | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN0_SHIFT,
   1147                                                 XGXSBLK1_LANECTRL1_RX1G_MODE_LN0_MASK
   1148                                               | XGXSBLK1_LANECTRL1_TX1G_MODE_LN0_MASK));
   1149                     break;
   1150                 case 1:
   1151                     SOC_IF_ERROR_RETURN
   1152                         (MODIFY_XGXS16G_TX1_TX_BGVCMr(unit, pc,
   1153                                                  temp16,
   1154                                                  TX1_TX_BGVCM_TICKSEL_MASK));
   1155                     SOC_IF_ERROR_RETURN
   1156                         (MODIFY_XGXS16G_RX1_RX_ANALOGBIAS0r(unit, pc,
   1157                                                  temp16,
   1158                                                  RX1_RX_ANALOGBIAS0_SIG_PWRDN_MASK));
   1159                     SOC_IF_ERROR_RETURN
   1160                         (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc,
   1161                                                 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN1_SHIFT
   1162                                               | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN1_SHIFT,
   1163                                                 XGXSBLK1_LANECTRL1_RX1G_MODE_LN1_MASK
   1164                                               | XGXSBLK1_LANECTRL1_TX1G_MODE_LN1_MASK));
   1165                     break;
   1166                 case 2:
   1167                     SOC_IF_ERROR_RETURN
   1168                         (MODIFY_XGXS16G_TX2_TX_BGVCMr(unit, pc,
   1169                                                  temp16,
   1170                                                  TX2_TX_BGVCM_TICKSEL_MASK));
   1171                     SOC_IF_ERROR_RETURN
   1172                         (MODIFY_XGXS16G_RX2_RX_ANALOGBIAS0r(unit, pc,
   1173                                                  temp16,
   1174                                                  RX2_RX_ANALOGBIAS0_SIG_PWRDN_MASK));
   1175                     SOC_IF_ERROR_RETURN
   1176                         (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc,
   1177                                                 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN2_SHIFT
   1178                                               | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN2_SHIFT,
   1179                                                 XGXSBLK1_LANECTRL1_RX1G_MODE_LN2_MASK
   1180                                               | XGXSBLK1_LANECTRL1_TX1G_MODE_LN2_MASK));
   1181                     break;
   1182                 case 3:
   1183                     SOC_IF_ERROR_RETURN
   1184                         (MODIFY_XGXS16G_TX3_TX_BGVCMr(unit, pc,
   1185                                                  temp16,
   1186                                                  TX3_TX_BGVCM_TICKSEL_MASK));
   1187                     SOC_IF_ERROR_RETURN
   1188                         (MODIFY_XGXS16G_RX3_RX_ANALOGBIAS0r(unit, pc,
   1189                                                  temp16,
   1190                                                  RX3_RX_ANALOGBIAS0_SIG_PWRDN_MASK));
   1191                     SOC_IF_ERROR_RETURN
   1192                         (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc,
   1193                                                 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN3_SHIFT
   1194                                               | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN3_SHIFT,
   1195                                                 XGXSBLK1_LANECTRL1_RX1G_MODE_LN3_MASK
   1196                                               | XGXSBLK1_LANECTRL1_TX1G_MODE_LN3_MASK));
   1197                     break;
   1198                 default:
   1199                    return SOC_E_FAIL;
   1200             }
   1201             /* Release Rx and Tx lane reset  */
   1202             SOC_IF_ERROR_RETURN
   1203                 (MODIFY_XGXS16G_XGXSBLK2_LANERESETr(unit, pc, 0,
   1204                                   ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT)
   1205                                 | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT)));
   1206 
   1207         }
   1208 
   1209     return SOC_E_NONE ;
   1210 
   1211 }
   1212 /*
   1213  * Function:    
   1214  *      phy_xgxs16g1l_an_set
   1215  * Purpose:     
   1216  *      Enable or disabled auto-negotiation on the specified port.
   1217  * Parameters:
   1218  *      unit - StrataSwitch unit #.
   1219  *      port - StrataSwitch port #. 
   1220  *      an   - Boolean, if true, auto-negotiation is enabled 
   1221  *              (and/or restarted). If false, autonegotiation is disabled.
   1222  * Returns:     
   1223  *      SOC_E_XXX
   1224  */
   1225 STATIC int
   1226 phy_xgxs16g1l_an_set(int unit, soc_port_t port, int an)
   1227 {
   1228     phy_ctrl_t  *pc;
   1229     phy_ctrl_t  *local_pc;
   1230     uint16             an_enable;
   1231     uint16             auto_det;
   1232     int blk_num = 0;
   1233     soc_pbmp_t blk_pbmp;
   1234     soc_port_t local_port = 0;
   1235     int speed = 0;
   1236     int is_speed_2500 = 0;
   1237 
   1238     pc = INT_PHY_SW_STATE(unit, port);
   1239                                                                                 
   1240     LOG_INFO(BSL_LS_SOC_PHY,
   1241              (BSL_META_U(unit,
   1242                          "phy_xgxs16g1l_an_set: u=%d p=%d an=%d\n"),
   1243               unit, port, an));
   1244 
   1245     an_enable = 0;
   1246     auto_det  = 0;
   1247 
   1248     if (an) {
   1249         /* disable 100FX and 100FX auto-detect */
   1250         SOC_IF_ERROR_RETURN
   1251             (MODIFY_XGXS16G_FX100_CONTROL1r(unit, pc, 0,
   1252                                             FX100_CONTROL1_AUTODET_EN_MASK |
   1253                                             FX100_CONTROL1_ENABLE_MASK));
   1254 
   1255         an_enable = MII_CTRL_AE | MII_CTRL_RAN;
   1256 
   1257         /*
   1258          * Should read one during init and cache it in Phy flags
   1259          */
   1260         if (soc_property_port_get(unit, port,
   1261                                   spn_SERDES_AUTOMEDIUM,
   1262                                   FALSE)) {
   1263             auto_det = SERDESDIGITAL_CONTROL1000X1_AUTODET_EN_MASK;
   1264         }
   1265 
   1266         /* If auto-neg is enabled, make sure not forcing any speed */
   1267         SOC_IF_ERROR_RETURN
   1268             (MODIFY_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, 0,
   1269                                    SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK));
   1270         /* Enable/Disable auto detect */
   1271         SOC_IF_ERROR_RETURN
   1272              (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, auto_det,
   1273                                  SERDESDIGITAL_CONTROL1000X1_AUTODET_EN_MASK));
   1274                                                                                 
   1275     } else {
   1276         /* Disable auto detect */
   1277         SOC_IF_ERROR_RETURN
   1278              (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, auto_det,
   1279                                  SERDESDIGITAL_CONTROL1000X1_AUTODET_EN_MASK));
   1280                                                                                 
   1281     }
   1282 
   1283     /* restart the autoneg if enabled, or disable the autoneg */
   1284     SOC_IF_ERROR_RETURN
   1285         (MODIFY_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, an_enable,
   1286                                       MII_CTRL_AE | MII_CTRL_RAN));
   1287 
   1288     if (PHY_CLAUSE73_MODE(unit, port)) {
   1289         SOC_IF_ERROR_RETURN
   1290             (MODIFY_XGXS16G_AN_CL73_REG(unit, pc,MII_CTRL_REG,
   1291                                           an_enable,
   1292                                           MII_CTRL_AE | MII_CTRL_RAN));
   1293     }
   1294 
   1295     if(an) {
   1296         is_speed_2500 = 0;
   1297     }else{
   1298         SOC_IF_ERROR_RETURN
   1299             (phy_xgxs16g1l_speed_get(unit, port, &speed));
   1300         if(speed == 2500) {
   1301            is_speed_2500 = 1;
   1302         } else {
   1303             is_speed_2500 = 0;
   1304         }
   1305     }
   1306 
   1307     SOC_IF_ERROR_RETURN
   1308         (_force_asym_speedmod_set(unit,port,is_speed_2500));
   1309 
   1310     pc->fiber.autoneg_enable = an;
   1311 
   1312     if (SOC_IS_KATANA(unit)) {
   1313         blk_num = SOC_PORT_BLOCK(unit, port);
   1314         SOC_PBMP_ASSIGN(blk_pbmp,SOC_BLOCK_BITMAP(unit,blk_num));
   1315         SOC_PBMP_ITER(blk_pbmp,local_port) {
   1316             local_pc = INT_PHY_SW_STATE(unit, local_port);
   1317             if (local_pc == NULL) {
   1318                 continue;
   1319             } 
   1320             if ((local_pc->lane_num == 0) && !SOC_PORT_VALID(unit, local_port)) {
   1321                 SOC_IF_ERROR_RETURN(WRITE_XGXS16G_AERBLK_AERr(unit, pc, 0x1f));
   1322                 break;
   1323             }
   1324         }
   1325     }
   1326 
   1327     return SOC_E_NONE;
   1328 }
   1329 
   1330 
   1331 /*
   1332  * Function:    
   1333  *      phy_xgxs16g1l_an_get
   1334  * Purpose:     
   1335  *      Get the current auto-negotiation status (enabled/busy)
   1336  * Parameters:
   1337  *      unit - StrataSwitch unit #.
   1338  *      port - StrataSwitch port #. 
   1339  *      an   - (OUT) if true, auto-negotiation is enabled.
   1340  *      an_done - (OUT) if true, auto-negotiation is complete. This
   1341  *              value is undefined if an == false.
   1342  * Returns:     
   1343  *      SOC_E_XXX
   1344  */
   1345 
   1346 STATIC int
   1347 phy_xgxs16g1l_an_get(int unit, soc_port_t port, int *an, int *an_done)
   1348 {
   1349     uint16      mii_ctrl;
   1350     uint16      mii_stat;
   1351     phy_ctrl_t *pc;
   1352                                                                                 
   1353     if ((NULL == an) || (NULL == an_done)) {
   1354         return (SOC_E_PARAM);
   1355     }
   1356 
   1357     pc = INT_PHY_SW_STATE(unit, port);
   1358                                                                                 
   1359     SOC_IF_ERROR_RETURN
   1360         (READ_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl));
   1361     SOC_IF_ERROR_RETURN
   1362         (READ_XGXS16G_COMBO_IEEE0_MIISTATr(unit, pc, &mii_stat));
   1363                                                                                 
   1364     *an = (mii_ctrl & MII_CTRL_AE) ? TRUE : FALSE;
   1365     *an_done = (mii_stat & MII_STAT_AN_DONE) ? TRUE : FALSE;
   1366     if (!((*an == TRUE) && (*an_done == TRUE))) {
   1367         if (PHY_CLAUSE73_MODE(unit, port)) {
   1368             /* check clause 73 */
   1369             SOC_IF_ERROR_RETURN
   1370                 (READ_XGXS16G_AN_CL73_REG(unit, pc, MII_CTRL_REG,&mii_ctrl));
   1371             SOC_IF_ERROR_RETURN
   1372                 (READ_XGXS16G_AN_CL73_REG(unit, pc, MII_STAT_REG, &mii_stat));
   1373 
   1374             *an = (mii_ctrl & MII_CTRL_AE) ? TRUE : FALSE;
   1375             *an_done = (mii_stat & MII_STAT_AN_DONE) ? TRUE : FALSE;
   1376         }
   1377     }
   1378 
   1379     return SOC_E_NONE;
   1380 }
   1381 
   1382 STATIC int
   1383 _phy_xgxs16g1l_c73_adv_local_set(int unit, soc_port_t port,
   1384                             soc_port_ability_t *ability)
   1385 {
   1386     uint16            an_adv;
   1387     uint16            pause;
   1388     phy_ctrl_t       *pc;
   1389 
   1390     pc = INT_PHY_SW_STATE(unit, port);
   1391 
   1392     an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ?
   1393                CL73_AN_ADV_TECH_1G_KX : 0;
   1394     an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ?
   1395               CL73_AN_ADV_TECH_10G_KX4 : 0;
   1396 
   1397     SOC_IF_ERROR_RETURN
   1398         (MODIFY_XGXS16G_AN_CL73_REG(unit, pc, CL73_AN_ADVERT1_REG, an_adv,
   1399                                      CL73_AN_ADV_TECH_SPEEDS_MASK));
   1400 
   1401     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   1402     case SOC_PA_PAUSE_TX:
   1403         pause = CL73_AN_ADV_ASYM_PAUSE;
   1404         break;
   1405     case SOC_PA_PAUSE_RX:
   1406         pause = CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE;
   1407         break;
   1408     case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   1409         pause = CL73_AN_ADV_PAUSE;
   1410         break;
   1411     default:
   1412         pause = 0;
   1413         break;
   1414     }
   1415 
   1416     SOC_IF_ERROR_RETURN
   1417         (MODIFY_XGXS16G_AN_CL73_REG(unit, pc, CL73_AN_ADVERT0_REG, pause,
   1418                                      (CL73_AN_ADV_PAUSE |
   1419                                       CL73_AN_ADV_ASYM_PAUSE)));
   1420 
   1421     LOG_INFO(BSL_LS_SOC_PHY,
   1422              (BSL_META_U(unit,
   1423                          "_phy_xgxs16g1l_c73_adv_local_set: u=%d p=%d pause=%08x speeds=%04x,adv=0x%x\n"),
   1424               unit, port, pause, an_adv,ability->speed_full_duplex));
   1425     return SOC_E_NONE;
   1426 }
   1427 
   1428 STATIC int
   1429 _phy_xgxs16g1l_c73_adv_local_get(int unit, soc_port_t port,
   1430                             soc_port_ability_t *ability)
   1431 {
   1432     uint16            an_adv;
   1433     soc_port_mode_t   speeds,pause;
   1434     phy_ctrl_t       *pc;
   1435 
   1436     pc = INT_PHY_SW_STATE(unit, port);
   1437 
   1438     SOC_IF_ERROR_RETURN
   1439         (READ_XGXS16G_AN_CL73_REG(unit, pc, CL73_AN_ADVERT1_REG, &an_adv));
   1440 
   1441     speeds = (an_adv & CL73_AN_ADV_TECH_1G_KX) ? SOC_PA_SPEED_1000MB : 0;
   1442     speeds |= (an_adv & CL73_AN_ADV_TECH_10G_KX4) ? SOC_PA_SPEED_10GB : 0;
   1443     ability->speed_full_duplex |= speeds;
   1444 
   1445     SOC_IF_ERROR_RETURN
   1446         (READ_XGXS16G_AN_CL73_REG(unit, pc, CL73_AN_ADVERT0_REG, &an_adv));
   1447 
   1448     switch (an_adv & (CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE)) {
   1449         case CL73_AN_ADV_PAUSE:
   1450             pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   1451             break;
   1452         case CL73_AN_ADV_ASYM_PAUSE:
   1453             pause = SOC_PA_PAUSE_TX;
   1454             break;
   1455         case CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE:
   1456             pause = SOC_PA_PAUSE_RX;
   1457             break;
   1458         default:
   1459             pause = 0;
   1460             break;
   1461     }
   1462     ability->pause = pause;
   1463 
   1464     LOG_INFO(BSL_LS_SOC_PHY,
   1465              (BSL_META_U(unit,
   1466                          "_phy_xgxs16g1l_c73_adv_local_get: u=%d p=%d pause=%08x speeds=%04x\n"),
   1467               unit, port, pause, speeds));
   1468     return SOC_E_NONE;
   1469 }
   1470 
   1471 STATIC int
   1472 _phy_xgxs16g1l_c73_adv_remote_get(int unit, soc_port_t port,
   1473                              soc_port_ability_t *ability)
   1474 {
   1475     uint16            an_adv;
   1476     soc_port_mode_t   mode;
   1477     phy_ctrl_t       *pc;
   1478      pc = INT_PHY_SW_STATE(unit, port);
   1479      SOC_IF_ERROR_RETURN
   1480         (READ_XGXS16G_AN_CL73_REG(unit, pc,CL73_AN_LP_ABILITY1_REG, &an_adv));
   1481 
   1482     mode = (an_adv & CL73_AN_ADV_TECH_1G_KX) ? SOC_PA_SPEED_1000MB : 0;
   1483     mode |= (an_adv & CL73_AN_ADV_TECH_10G_KX4) ? SOC_PA_SPEED_10GB : 0;
   1484     ability->speed_full_duplex |= mode;
   1485 
   1486     SOC_IF_ERROR_RETURN
   1487         (READ_XGXS16G_AN_CL73_REG(unit, pc, CL73_AN_LP_ABILITY0_REG,&an_adv));
   1488 
   1489     mode = 0;
   1490     switch (an_adv & (CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE)) {
   1491         case CL73_AN_ADV_PAUSE:
   1492             mode = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   1493             break;
   1494         case CL73_AN_ADV_ASYM_PAUSE:
   1495             mode = SOC_PA_PAUSE_TX;
   1496             break;
   1497         case CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE:
   1498             mode = SOC_PA_PAUSE_RX;
   1499             break;
   1500     }
   1501     ability->pause = mode;
   1502 
   1503     return SOC_E_NONE;
   1504 }
   1505 
   1506 /*
   1507  * Function:
   1508  *      phy_xgxs16g1l_ability_advert_set
   1509  * Purpose:
   1510  *      Set the current advertisement for auto-negotiation.
   1511  * Parameters:
   1512  *      unit - StrataSwitch unit #.
   1513  *      port - StrataSwitch port #.
   1514  *      mode - Port mode mask indicating supported options/speeds.
   1515  * Returns:
   1516  *      SOC_E_XXX
   1517  * Notes:
   1518  *      The advertisement is set only for the ACTIVE medium.
   1519  *      No synchronization performed at this level.
   1520  */
   1521 
   1522 STATIC int
   1523 phy_xgxs16g1l_ability_advert_set(int unit, soc_port_t port,
   1524                           soc_port_ability_t *ability)
   1525 {
   1526     uint16           an_adv;
   1527     phy_ctrl_t      *pc;
   1528                                                                                 
   1529     if (NULL == ability) {
   1530         return (SOC_E_PARAM);
   1531     }
   1532                                                                                 
   1533     pc = INT_PHY_SW_STATE(unit, port);
   1534                                                                                 
   1535     /* Set advertised duplex (only FD supported).  */
   1536     an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? 
   1537               MII_ANA_C37_FD : 0;
   1538                                                                                 
   1539     /* Set advertised pause bits in link code word.  */
   1540     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   1541     case SOC_PA_PAUSE_TX:
   1542         an_adv |= MII_ANA_C37_ASYM_PAUSE;
   1543         break;
   1544     case SOC_PA_PAUSE_RX:
   1545         an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE;
   1546         break;
   1547     case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   1548         an_adv |= MII_ANA_C37_PAUSE;
   1549         break;
   1550     }
   1551     /* Update less than 1G capability */
   1552     SOC_IF_ERROR_RETURN
   1553         (WRITE_XGXS16G_COMBO_IEEE0_AUTONEGADVr(unit, pc, an_adv));
   1554 
   1555     if (PHY_CLAUSE73_MODE(unit, port)) {
   1556         SOC_IF_ERROR_RETURN
   1557             (_phy_xgxs16g1l_c73_adv_local_set(unit, port, ability));
   1558     }
   1559                                                                                 
   1560     LOG_INFO(BSL_LS_SOC_PHY,
   1561              (BSL_META_U(unit,
   1562                          "phy_xgxs16g1l_ability_advert_set: u=%d p=%d pause=%08x OVER1G_UP1 %04x\n"),
   1563               unit, port, ability->pause, an_adv));
   1564 
   1565     return (SOC_E_NONE);
   1566 }
   1567 
   1568 /*
   1569  * Function:
   1570  *      phy_xgxs16g1l_ability_advert_get
   1571  * Purpose:
   1572  *      Get the current advertisement for auto-negotiation.
   1573  * Parameters:
   1574  *      unit - StrataSwitch unit #.
   1575  *      port - StrataSwitch port #.
   1576  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1577  * Returns:
   1578  *      SOC_E_XXX
   1579  * Notes:
   1580  *      The advertisement is retrieved for the ACTIVE medium.
   1581  *      No synchronization performed at this level.
   1582  */
   1583 
   1584 STATIC int
   1585 phy_xgxs16g1l_ability_advert_get(int unit, soc_port_t port,
   1586                               soc_port_ability_t *ability)
   1587 {
   1588     phy_ctrl_t      *pc;
   1589     uint16           an_adv;
   1590 
   1591     if (NULL == ability) {
   1592         return (SOC_E_PARAM);
   1593     }
   1594 
   1595     pc = INT_PHY_SW_STATE(unit, port);
   1596 
   1597     sal_memset(ability, 0, sizeof(*ability));
   1598     SOC_IF_ERROR_RETURN
   1599         (READ_XGXS16G_COMBO_IEEE0_AUTONEGADVr(unit, pc, &an_adv));
   1600                                                                                 
   1601     ability->speed_full_duplex = 
   1602                   (an_adv & MII_ANA_C37_FD) ? SOC_PA_SPEED_1000MB : 0;
   1603 
   1604     switch (an_adv & (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE)) {
   1605         case MII_ANA_C37_PAUSE:
   1606             ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   1607             break;
   1608         case MII_ANA_C37_ASYM_PAUSE:
   1609             ability->pause = SOC_PA_PAUSE_TX;
   1610             break;
   1611         case MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE:
   1612             ability->pause = SOC_PA_PAUSE_RX;
   1613             break;
   1614     }
   1615 
   1616     /* check for clause73 */
   1617     if (PHY_CLAUSE73_MODE(unit, port)) {
   1618         SOC_IF_ERROR_RETURN
   1619             (_phy_xgxs16g1l_c73_adv_local_get(unit, port, ability));
   1620     }
   1621                                                                              
   1622     LOG_INFO(BSL_LS_SOC_PHY,
   1623              (BSL_META_U(unit,
   1624                          "phy_xgxs16g1l_ability_advert_get:unit=%d p=%d pause=%08x sp=%08x\n"),
   1625               unit, port, ability->pause, ability->speed_full_duplex));
   1626                                                                                 
   1627     return (SOC_E_NONE);
   1628 }
   1629 
   1630 /*
   1631  * Function:
   1632  *      phy_xgxs16g1l_ability_remote_get
   1633  * Purpose:
   1634  *      Get the current advertisement for auto-negotiation.
   1635  * Parameters:
   1636  *      unit - StrataSwitch unit #.
   1637  *      port - StrataSwitch port #.
   1638  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1639  * Returns:
   1640  *      SOC_E_XXX
   1641  * Notes:
   1642  *      The advertisement is retrieved for the ACTIVE medium.
   1643  *      No synchronization performed at this level.
   1644  */
   1645 
   1646 STATIC int
   1647 phy_xgxs16g1l_ability_remote_get(int unit, soc_port_t port,
   1648                                soc_port_ability_t *ability)
   1649 {
   1650     phy_ctrl_t       *pc;
   1651     uint16            an_adv;
   1652     soc_port_mode_t   mode;
   1653 
   1654     if (NULL == ability) {
   1655         return (SOC_E_PARAM);
   1656     }
   1657 
   1658     pc = INT_PHY_SW_STATE(unit, port);
   1659  
   1660     sal_memset(ability, 0, sizeof(*ability));
   1661 
   1662     SOC_IF_ERROR_RETURN
   1663         (READ_XGXS16G_COMBO_IEEE0_AUTONEGLPABILr(unit, pc, &an_adv));
   1664 
   1665     mode = (an_adv & MII_ANP_C37_FD) ? SOC_PA_SPEED_1000MB : 0;
   1666     ability->speed_full_duplex = mode;
   1667 
   1668     mode = 0;
   1669     switch (an_adv & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) {
   1670         case MII_ANP_C37_PAUSE:
   1671             mode |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   1672             break;
   1673         case MII_ANP_C37_ASYM_PAUSE:
   1674             mode |= SOC_PA_PAUSE_TX;
   1675             break;
   1676         case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE:
   1677             mode |= SOC_PA_PAUSE_RX;
   1678             break;
   1679     }
   1680     ability->pause = mode;
   1681 
   1682     if (PHY_CLAUSE73_MODE(unit, port)) {
   1683         SOC_IF_ERROR_RETURN
   1684             (_phy_xgxs16g1l_c73_adv_remote_get(unit, port, ability));
   1685     }
   1686 
   1687     LOG_INFO(BSL_LS_SOC_PHY,
   1688              (BSL_META_U(unit,
   1689                          "phy_xgxs16g1l_ability_remote_get:unit=%d p=%d pause=%08x sp=%08x\n"),
   1690               unit, port, ability->pause, ability->speed_full_duplex));
   1691 
   1692     return (SOC_E_NONE);
   1693 }
   1694 
   1695 
   1696 /*
   1697  * Function:
   1698  *      phy_xgxs16g1l_lb_set
   1699  * Purpose:
   1700  *      Put XGXS6/FusionCore in PHY loopback
   1701  * Parameters:
   1702  *      unit - StrataSwitch unit #.
   1703  *      port - StrataSwitch port #. 
   1704  *      enable - binary value for on/off (1/0)
   1705  * Returns:     
   1706  *      SOC_E_NONE
   1707  */
   1708 
   1709 STATIC int
   1710 phy_xgxs16g1l_lb_set(int unit, soc_port_t port, int enable)
   1711 {
   1712     uint16      misc_ctrl;
   1713     uint16      lb_bit;
   1714     uint16      lb_mask;
   1715     phy_ctrl_t *pc;
   1716 
   1717     pc = INT_PHY_SW_STATE(unit, port);
   1718     
   1719     /* Configure Loopback in XAUI */
   1720     SOC_IF_ERROR_RETURN
   1721         (READ_XGXS16G_XGXSBLK0_MISCCONTROL1r(unit, pc, &misc_ctrl));
   1722     if (misc_ctrl & XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_MASK) {
   1723           /* PCS */
   1724           lb_bit  = (enable) ? IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK : 0;
   1725           lb_mask = IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK;
   1726     } else if (misc_ctrl & XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_MASK) {
   1727           /* PMA/PMD */
   1728           lb_bit  = (enable) ? 1 : 0;
   1729           lb_mask = 1;
   1730     } else {
   1731           /* PHY XS, DTE XS */
   1732           lb_bit  = (enable) ? IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK : 0;
   1733           lb_mask = IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK;
   1734     }
   1735     SOC_IF_ERROR_RETURN
   1736         (MODIFY_XGXS16G_IEEE0BLK_IEEECONTROL0r(unit, pc, lb_bit, lb_mask));
   1737 
   1738     /* Configure Loopback in SerDes */
   1739     SOC_IF_ERROR_RETURN
   1740         (MODIFY_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, 
   1741                                              (enable) ? MII_CTRL_LE : 0,
   1742                                              MII_CTRL_LE));
   1743 
   1744     return (SOC_E_NONE);
   1745 }
   1746 
   1747 /*
   1748  * Function:
   1749  *      phy_xgxs16g1l_lb_get
   1750  * Purpose:
   1751  *      Get XGXS6/FusionCore PHY loopback state
   1752  * Parameters:
   1753  *      unit - StrataSwitch unit #.
   1754  *      port - StrataSwitch port #. 
   1755  *      enable - address of location to store binary value for on/off (1/0)
   1756  * Returns:     
   1757  *      SOC_E_NONE
   1758  */
   1759 
   1760 STATIC int
   1761 phy_xgxs16g1l_lb_get(int unit, soc_port_t port, int *enable)
   1762 {
   1763     uint16      mii_ctrl;
   1764     phy_ctrl_t *pc;
   1765 
   1766     pc = INT_PHY_SW_STATE(unit, port);
   1767 
   1768     SOC_IF_ERROR_RETURN
   1769         (READ_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl));
   1770     *enable = ((mii_ctrl & MII_CTRL_LE) == MII_CTRL_LE);
   1771 
   1772     return (SOC_E_NONE);
   1773 }
   1774 
   1775 
   1776 STATIC int
   1777 phy_xgxs16g1l_ability_local_get(int unit, soc_port_t port,
   1778                               soc_port_ability_t *ability)
   1779 {
   1780     phy_ctrl_t *pc;
   1781 
   1782     if (NULL == ability) {
   1783         return (SOC_E_PARAM);
   1784     }
   1785 
   1786     pc = INT_PHY_SW_STATE(unit, port);
   1787 
   1788     sal_memset(ability, 0, sizeof(*ability));
   1789 
   1790     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   1791     ability->speed_full_duplex  = SOC_PA_SPEED_1000MB;
   1792     if (PHY_FIBER_MODE(unit, port))   {
   1793         ability->speed_full_duplex  |= SOC_PA_SPEED_2500MB;
   1794         if (FEATURE_SPEED_100FX(pc)) {
   1795             ability->speed_full_duplex  |= SOC_PA_SPEED_100MB;
   1796         }
   1797     } else {
   1798         ability->speed_half_duplex  = SOC_PA_SPEED_10MB |
   1799                                       SOC_PA_SPEED_100MB;
   1800         ability->speed_full_duplex  |= SOC_PA_SPEED_10MB |
   1801                                        SOC_PA_SPEED_100MB;
   1802     }
   1803 
   1804     ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 
   1805     ability->interface = SOC_PA_INTF_GMII | SOC_PA_INTF_SGMII;
   1806     ability->medium    = SOC_PA_MEDIUM_FIBER;
   1807     ability->loopback  = SOC_PA_LB_PHY;
   1808     ability->flags     = SOC_PA_AUTONEG;
   1809 
   1810     return (SOC_E_NONE);
   1811 }
   1812 
   1813 STATIC int
   1814 _phy_xgxs16g1l_control_tx_driver_set(int unit, phy_ctrl_t *pc,
   1815                                 soc_phy_control_t type, uint32 value)
   1816 {
   1817     uint16  data;             /* Temporary holder of reg value to be written */
   1818     uint16  mask;             /* Bit mask of reg value to be updated */
   1819 
   1820     if (value > 15) {
   1821         return SOC_E_PARAM;
   1822     }
   1823 
   1824     data = mask = 0;
   1825     if (XGXS16G_13G_ID(pc) || XGXS16G_2p5G_ID(pc)){
   1826         switch(type) {
   1827         case SOC_PHY_CONTROL_PREEMPHASIS:
   1828              data = value << TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_SHIFT;
   1829              mask = TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_MASK;
   1830              break;
   1831         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   1832              data = value << TX_ALL_040_TX_DRIVER_IDRIVER_SHIFT;
   1833              mask = TX_ALL_040_TX_DRIVER_IDRIVER_MASK;
   1834              break;
   1835         default:
   1836              /* should never get here */
   1837              return SOC_E_PARAM;
   1838         }
   1839         /* Update preemphasis/driver/pre-driver current */
   1840         switch(pc->lane_num){
   1841         case 0:
   1842              SOC_IF_ERROR_RETURN
   1843                  (MODIFY_XGXS13G_040_TX0_ACONTROL1r(unit, pc, data, mask));
   1844              break;
   1845         case 1:
   1846              SOC_IF_ERROR_RETURN
   1847                  (MODIFY_XGXS13G_040_TX1_ACONTROL1r(unit, pc, data, mask));
   1848              break;
   1849         case 2:
   1850              SOC_IF_ERROR_RETURN
   1851                  (MODIFY_XGXS13G_040_TX2_ACONTROL1r(unit, pc, data, mask));
   1852              break;
   1853         case 3:
   1854              SOC_IF_ERROR_RETURN
   1855                  (MODIFY_XGXS13G_040_TX3_ACONTROL1r(unit, pc, data, mask));
   1856              break;
   1857         default:
   1858              SOC_IF_ERROR_RETURN
   1859                  (MODIFY_XGXS13G_040_TX_ALL_ACONTROL1r(unit, pc, data, mask));
   1860              break;
   1861         }
   1862     } else {
   1863         switch(type) {
   1864         case SOC_PHY_CONTROL_PREEMPHASIS:
   1865              data = value << TX_ALL_TX_DRIVER_PREEMPHASIS_SHIFT;
   1866              mask = TX_ALL_TX_DRIVER_PREEMPHASIS_MASK;
   1867              break;
   1868         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   1869              data = value << TX_ALL_TX_DRIVER_IDRIVER_SHIFT;
   1870              mask = TX_ALL_TX_DRIVER_IDRIVER_MASK;
   1871              break;
   1872         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   1873              data = value << TX_ALL_TX_DRIVER_IPREDRIVER_SHIFT;
   1874              mask = TX_ALL_TX_DRIVER_IPREDRIVER_MASK;
   1875              break;
   1876         default:
   1877              /* should never get here */
   1878              return SOC_E_PARAM;
   1879         }
   1880         /* Update preemphasis/driver/pre-driver current */
   1881         switch(pc->lane_num){
   1882         case 0:
   1883              SOC_IF_ERROR_RETURN
   1884                  (MODIFY_XGXS16G_TX0_TX_DRIVERr(unit, pc, data, mask));
   1885              break;
   1886         case 1:
   1887              SOC_IF_ERROR_RETURN
   1888                  (MODIFY_XGXS16G_TX1_TX_DRIVERr(unit, pc, data, mask));
   1889              break;
   1890         case 2:
   1891              SOC_IF_ERROR_RETURN
   1892                  (MODIFY_XGXS16G_TX2_TX_DRIVERr(unit, pc, data, mask));
   1893              break;
   1894         case 3:
   1895              SOC_IF_ERROR_RETURN
   1896                  (MODIFY_XGXS16G_TX3_TX_DRIVERr(unit, pc, data, mask));
   1897              break;
   1898         default:
   1899              SOC_IF_ERROR_RETURN
   1900                  (MODIFY_XGXS16G_TX_ALL_TX_DRIVERr(unit, pc, data, mask));
   1901              break;
   1902         }
   1903 
   1904     }
   1905     return SOC_E_NONE;
   1906 }
   1907 
   1908 STATIC int
   1909 _phy_xgxs16g1l_control_linkdown_transmit_set(int unit, soc_port_t port, 
   1910                                            uint32 value)
   1911 {
   1912     uint16      data;
   1913     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   1914 
   1915     if (value) {
   1916         data = (SERDESDIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_BITS <<
   1917                 SERDESDIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_SHIFT) |
   1918                (SERDESDIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_BITS <<
   1919                 SERDESDIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_SHIFT) |
   1920                (SERDESDIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_BITS <<
   1921                 SERDESDIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_SHIFT);
   1922         SOC_IF_ERROR_RETURN
   1923             (WRITE_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc, data));
   1924     } else {
   1925         data = (SERDESDIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_BITS <<
   1926                 SERDESDIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_SHIFT) |
   1927                (SERDESDIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_BITS <<
   1928                 SERDESDIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_SHIFT) |
   1929                (SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_BITS <<
   1930                 SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_SHIFT);
   1931         SOC_IF_ERROR_RETURN
   1932             (WRITE_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc, data));
   1933     }
   1934     return SOC_E_NONE;
   1935 }
   1936 
   1937 STATIC int
   1938 _phy_xgxs16g1l_control_linkdown_transmit_get(int unit, soc_port_t port, 
   1939                                            uint32 *value)
   1940 {
   1941     uint16      data;
   1942     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   1943 
   1944     SOC_IF_ERROR_RETURN
   1945             (READ_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc, &data));
   1946 
   1947     *value = (data & 
   1948               (SERDESDIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_BITS <<
   1949                SERDESDIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_SHIFT))
   1950              ? 1 : 0;
   1951 
   1952     return SOC_E_NONE;
   1953 }
   1954 
   1955 
   1956 STATIC int
   1957 _phy_xgxs16g1l_control_prbs_polynomial_set(int unit, soc_port_t port, uint32 value)
   1958 {
   1959     uint16      data;
   1960 
   1961     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   1962     uint32      prbs_lane_mask = 0;
   1963 
   1964     value &= 7;
   1965 
   1966     SOC_IF_ERROR_RETURN
   1967         (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   1968 
   1969     prbs_lane_mask = 0x7 << (PHY_XGXS16G_LANEPRBS_LANE_SHIFT * pc->lane_num);
   1970     data &= ~prbs_lane_mask;
   1971     data |= value << (PHY_XGXS16G_LANEPRBS_LANE_SHIFT * pc->lane_num);
   1972 
   1973     
   1974     /* 
   1975      * write back updated configuration 
   1976      */
   1977 
   1978     SOC_IF_ERROR_RETURN
   1979 	(WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, data));
   1980 
   1981     return SOC_E_NONE;
   1982 }
   1983 
   1984 STATIC int
   1985 _phy_xgxs16g1l_control_prbs_polynomial_get(int unit, soc_port_t port, uint32 *value)
   1986 {
   1987     uint16      data;
   1988     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);;
   1989 
   1990     SOC_IF_ERROR_RETURN
   1991         (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   1992 
   1993     /* Extract prbs polynomial setting from register */
   1994     data = ((data >> (XGXSBLK1_LANEPRBS_PRBS_ORDER1_SHIFT * pc->lane_num)) &
   1995             XGXSBLK1_LANEPRBS_PRBS_ORDER0_MASK);
   1996     *value = (uint32) data;
   1997 
   1998     return SOC_E_NONE;
   1999 }
   2000 
   2001 
   2002 STATIC int
   2003 _phy_xgxs16g1l_control_prbs_tx_invert_data_set(int unit, soc_port_t port, uint32 value)
   2004 {
   2005     uint16      data = 0;
   2006     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);		
   2007     uint32      lane_mask = 1 << (PHY_XGXS16G_LANEPRBS_LANE_SHIFT * pc->lane_num);
   2008 
   2009 
   2010     SOC_IF_ERROR_RETURN
   2011         (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   2012     
   2013     /* prbs_inv is bit 2 per lane */
   2014     if (value) {
   2015         data |= lane_mask << XGXSBLK1_LANEPRBS_PRBS_INV0_SHIFT;
   2016     } else {
   2017         data &= ~(lane_mask << XGXSBLK1_LANEPRBS_PRBS_INV0_SHIFT);
   2018     }
   2019 
   2020     /* write back updated configuration */
   2021     if (value > 0x8000) {
   2022         SOC_IF_ERROR_RETURN
   2023 	    (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, value));
   2024     } else {
   2025         SOC_IF_ERROR_RETURN
   2026 	    (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, data));
   2027     } 
   2028 
   2029     return SOC_E_NONE;
   2030 
   2031 }
   2032 
   2033 STATIC int
   2034 _phy_xgxs16g1l_control_prbs_tx_invert_data_get(int unit, soc_port_t port, uint32 *value)
   2035 {
   2036     uint16      data;
   2037     uint16       inv_shifter = 0;
   2038     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   2039     
   2040     SOC_IF_ERROR_RETURN
   2041         (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   2042 
   2043     inv_shifter = (XGXSBLK1_LANEPRBS_PRBS_ORDER1_SHIFT * pc->lane_num) +
   2044                  XGXSBLK1_LANEPRBS_PRBS_INV0_SHIFT;
   2045    
   2046     data &= (1 << inv_shifter);
   2047     
   2048     *value = (data) ?  1 : 0;
   2049     
   2050     return SOC_E_NONE;
   2051 }
   2052 
   2053 
   2054 STATIC int
   2055 _phy_xgxs16g1l_control_xgxs_prbs_tx_enable_set(int unit, soc_port_t port, 
   2056                                           uint32 value)
   2057 {
   2058     uint16      data = 0;
   2059     uint16      pll_mode = 0;
   2060     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   2061 
   2062     if (value) {
   2063 
   2064         /* Set double wide div/1: 0x8016=0xffff */
   2065         SOC_IF_ERROR_RETURN
   2066             (WRITE_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc, 0xffff));
   2067         
   2068         /* clear multiPRT mode: 0x800d=0x0003 */
   2069         /*SOC_IF_ERROR_RETURN
   2070             (WRITE_XGXS16G_XGXSBLK0_MMDSELECTr(unit, pc, 0x4003));
   2071 	*/
   2072 
   2073         /* Set in individual lane mode, Disable PLL Sequencer: 0x8000=0x063f */
   2074         SOC_IF_ERROR_RETURN
   2075             (WRITE_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, 0x063f));
   2076         
   2077         /* Force VCO based on current operating frequency */
   2078         SOC_IF_ERROR_RETURN 
   2079             (READ_XGXS16G_PLL_PLLSTATUSr(unit, pc, &pll_mode)); 
   2080         pll_mode &= 
   2081             (PLL_PLLSTATUS_PLL_MODE_AFE_MASK | PLL_PLLSTATUS_RESERVED0_MASK); 
   2082         SOC_IF_ERROR_RETURN 
   2083             (READ_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, &data)); 
   2084         data &= ~SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_MASK; 
   2085         data |= SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_SEL_MASK | 
   2086             (pll_mode << SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_SHIFT); 
   2087         SOC_IF_ERROR_RETURN 
   2088             (WRITE_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, data)); 
   2089 
   2090 	/* Disable asymmetric mode for 40nm UC_B0 */
   2091 	if(XGXS16G_13G_REV_B0(pc)){
   2092 	       SOC_IF_ERROR_RETURN
   2093                 (MODIFY_XGXS16G_XGXSBLK8_TXLNSWAP1r(unit, pc, 0,
   2094                         XGXSBLK8_TXLNSWAP1_ASYMM_EN_MASK)); 
   2095 	}
   2096 
   2097         /* Turn AN off: 0x0=0x0 */
   2098         SOC_IF_ERROR_RETURN
   2099             (READ_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, &data));
   2100         data &= ~IEEE0BLK_IEEECONTROL0_AUTONEG_ENABLE_MASK;
   2101         SOC_IF_ERROR_RETURN
   2102             (WRITE_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, 0));
   2103 	
   2104         /* Turn CL36 PCS off: 0x8015=0x0 */
   2105         SOC_IF_ERROR_RETURN
   2106             (WRITE_XGXS16G_XGXSBLK1_LANECTRL0r(unit, pc, 0));
   2107         
   2108         /* Put port in loopback if requested */
   2109         data = ((value & 0x8000) == 0x8000) ? 
   2110                XGXSBLK1_LANECTRL2_GLOOP1G_MASK : 0;
   2111         /* CDED & EDEN off: 0x8017 */
   2112         SOC_IF_ERROR_RETURN
   2113             (WRITE_XGXS16G_XGXSBLK1_LANECTRL2r(unit, pc, data));
   2114 
   2115         /* PRBS Polynomial for all lanes: 0x8019=0x8888 */
   2116         SOC_IF_ERROR_RETURN
   2117             (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   2118         data |= 0x8888;
   2119         SOC_IF_ERROR_RETURN
   2120             (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, data));
   2121  
   2122         /* Enable PRBS read: 0x80f1=0x1c47 */ 
   2123         SOC_IF_ERROR_RETURN
   2124             (WRITE_XGXS16G_RX_ALL_RX_CONTROLr(unit, pc, 0x1c47));
   2125         
   2126         /* Enable PLL Sequencer: 0x8000=0x263f */
   2127         SOC_IF_ERROR_RETURN
   2128             (WRITE_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, 0x263f));
   2129         
   2130         /* Delay a while */
   2131         sal_usleep(250000);
   2132     } else {
   2133         /* Restore port */
   2134         return phy_xgxs16g1l_init(unit, port);
   2135     }
   2136     return SOC_E_NONE;
   2137 }
   2138 
   2139 STATIC int
   2140 _phy_xgxs16g1l_control_prbs_tx_enable_set(int unit, soc_port_t port, uint32 value)
   2141 {
   2142     SOC_IF_ERROR_RETURN(
   2143 			_phy_xgxs16g1l_control_xgxs_prbs_tx_enable_set(unit, port, value));
   2144     return SOC_E_NONE;
   2145 }
   2146 
   2147 
   2148 STATIC int
   2149 _phy_xgxs16g1l_control_prbs_tx_rx_enable_get(int unit, soc_port_t port, 
   2150                                         uint32 *value)
   2151 {
   2152     uint16      data;
   2153     uint16       inv_shifter = 0;
   2154     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   2155     /*
   2156      * Hypercore PRBS - note that in the Hypercore there is only 1 enable 
   2157      * for both TX/RX 
   2158      */
   2159     SOC_IF_ERROR_RETURN
   2160         (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   2161     inv_shifter = (XGXSBLK1_LANEPRBS_PRBS_ORDER1_SHIFT * pc->lane_num) +
   2162                 XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT;
   2163     data &= (1 << inv_shifter);
   2164     *value = (data) ?  1 : 0;
   2165   
   2166     return SOC_E_NONE;
   2167 }
   2168 
   2169 STATIC int
   2170 _phy_xgxs16g1l_control_prbs_tx_enable_get(int unit, soc_port_t port, uint32 *value)
   2171 {
   2172     return _phy_xgxs16g1l_control_prbs_tx_rx_enable_get(unit, port, value);
   2173 }
   2174 
   2175 STATIC int
   2176 _phy_xgxs16g1l_control_prbs_rx_enable_set(int unit, soc_port_t port, uint32 value)
   2177 {
   2178     uint16      data;
   2179     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   2180     uint32      lane_mask = 1 << (PHY_XGXS16G_LANEPRBS_LANE_SHIFT * pc->lane_num);
   2181 
   2182     SOC_IF_ERROR_RETURN
   2183         (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   2184 
   2185     if (value) {
   2186         data |= lane_mask <<  XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT;
   2187     }  else {
   2188         data &= ~(lane_mask << XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT);
   2189     }
   2190     
   2191     /* write back updated configuration */
   2192     SOC_IF_ERROR_RETURN
   2193         (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, data));
   2194     
   2195     /* Set up status collection */
   2196     /* uPrbsRxControlReg = 0x80b1;
   2197      * uPrbsRxControlReg += uLaneAddr * 0x10;
   2198      */
   2199     SOC_IF_ERROR_RETURN
   2200         (XGXS16G_REG_READ(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), &data));
   2201     
   2202     data &= ~RX0_RX_CONTROL_STATUS_SEL_MASK;
   2203     if (value) {
   2204         data |= RX0_RX_CONTROL_STATUS_SEL_prbsStatus;
   2205     } else {
   2206         data &= ~RX0_RX_CONTROL_STATUS_SEL_prbsStatus;
   2207     }
   2208     
   2209     SOC_IF_ERROR_RETURN
   2210         (XGXS16G_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), data));
   2211 
   2212     return SOC_E_NONE;
   2213 }
   2214 
   2215 STATIC int
   2216 _phy_xgxs16g1l_control_prbs_rx_enable_get(int unit, soc_port_t port, uint32 *value)
   2217 {
   2218     return _phy_xgxs16g1l_control_prbs_tx_rx_enable_get(unit, port, value);
   2219 }
   2220 
   2221 /*
   2222  * Returns value 
   2223  *      ==  0: PRBS receive is in sync
   2224  *      == -1: PRBS receive never got into sync
   2225  *      ==  n: number of errors
   2226  */
   2227 STATIC int
   2228 _phy_xgxs16g1l_control_xgxs_prbs_rx_status_get(int unit, soc_port_t port, 
   2229                                           uint32 *value)
   2230 {
   2231   /*int         lane;*/
   2232     uint16      data;
   2233     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);;
   2234 
   2235     
   2236     /* Get status for one of the 4 lanes and check for sync
   2237      * 0x80b0, 0x80c0, 0x80d0, 0x80e0 
   2238      */
   2239     *value = 0;
   2240 
   2241     SOC_IF_ERROR_RETURN
   2242         (XGXS16G_REG_READ(unit, pc, 0x0, 0x80b0 + (0x10 * pc->lane_num), &data));
   2243     if (data == (RX0_RX_STATUS_PRBS_STATUS_PRBS_LOCK_BITS  <<
   2244 		 RX0_RX_STATUS_PRBS_STATUS_PRBS_LOCK_SHIFT)) {
   2245         /* PRBS is in sync */
   2246     } else if (data == 0) {
   2247         /* PRBS not in sync */
   2248         *value = -1;            
   2249     } else {
   2250         /* Get errors */
   2251         *value += data & RX0_RX_STATUS_PRBS_STATUS_PTBS_ERRORS_MASK;
   2252     }
   2253     return SOC_E_NONE;
   2254 }
   2255 
   2256 
   2257 STATIC int
   2258 _phy_xgxs16g1l_control_prbs_rx_status_get(int unit, soc_port_t port, uint32 *value)
   2259 {
   2260     int         rv;
   2261     uint16      rx_sts, saved_rx_sts;
   2262     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   2263 
   2264     /* Set up prbs rx status collection */
   2265     SOC_IF_ERROR_RETURN
   2266         (XGXS16G_REG_READ(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), &rx_sts));
   2267     saved_rx_sts = rx_sts;
   2268     rx_sts = (rx_sts & ~RX0_RX_CONTROL_STATUS_SEL_MASK) |
   2269              RX0_RX_CONTROL_STATUS_SEL_prbsStatus;
   2270     SOC_IF_ERROR_RETURN
   2271         (XGXS16G_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), rx_sts));
   2272 
   2273     rv = _phy_xgxs16g1l_control_xgxs_prbs_rx_status_get(unit, port, value);
   2274 
   2275 
   2276     /* Restore rx status */
   2277     SOC_IF_ERROR_RETURN
   2278         (XGXS16G_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), saved_rx_sts));
   2279 
   2280     return rv;
   2281 }
   2282 
   2283 STATIC int
   2284 _phy_xgxs16g1l_control_vco_disturbed_get(int unit, soc_port_t port, uint32 *value)
   2285 {
   2286     uint16 data;
   2287     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   2288     if(!pc) {
   2289         return SOC_E_NONE;
   2290     }
   2291     SOC_IF_ERROR_RETURN(READ_XGXS16G_SERDESDIGITAL_PATGENCTRLr(unit, pc, &data));
   2292     SOC_IF_ERROR_RETURN(MODIFY_XGXS16G_SERDESDIGITAL_PATGENCTRLr(unit, pc, 0,  SERDESDIGITAL_PATGENCTRL_PKT_SIZE_MASK));
   2293 
   2294     *value = (data & SERDESDIGITAL_PATGENCTRL_PKT_SIZE_MASK) ? 1 : 0;
   2295 
   2296     return SOC_E_NONE;
   2297 }
   2298 
   2299 STATIC int
   2300 _phy_xgxs16g1l_control_vco_disturbed_set(int unit, soc_port_t port)
   2301 {
   2302     uint16 data, mask;
   2303     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   2304     if(!pc) {
   2305         return SOC_E_NONE;
   2306     }
   2307     data = 1 << SERDESDIGITAL_PATGENCTRL_PKT_SIZE_SHIFT;
   2308     mask = SERDESDIGITAL_PATGENCTRL_PKT_SIZE_MASK;
   2309 
   2310     SOC_IF_ERROR_RETURN(MODIFY_XGXS16G_SERDESDIGITAL_PATGENCTRLr(unit, pc, data, mask));
   2311 
   2312     return SOC_E_NONE;
   2313 }
   2314 
   2315 
   2316 /*
   2317  * Function:
   2318  *      phy_xgxs16g1l_control_set
   2319  * Purpose:
   2320  *      Configure PHY device specific control fucntion. 
   2321  * Parameters:
   2322  *      unit  - StrataSwitch unit #.
   2323  *      port  - StrataSwitch port #. 
   2324  *      type  - Control to update 
   2325  *      value - New setting for the control 
   2326  * Returns:     
   2327  *      SOC_E_NONE
   2328  */
   2329 STATIC int
   2330 phy_xgxs16g1l_control_set(int unit, soc_port_t port,
   2331                      soc_phy_control_t type, uint32 value)
   2332 {
   2333     int rv;
   2334     phy_ctrl_t *pc;
   2335     /* coverity[mixed_enums] */
   2336     if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) {
   2337         return SOC_E_PARAM;
   2338     }
   2339 
   2340     pc = INT_PHY_SW_STATE(unit, port);
   2341     rv = SOC_E_UNAVAIL;
   2342     switch(type) {
   2343     case SOC_PHY_CONTROL_PREEMPHASIS:
   2344         /* fall through */
   2345     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   2346         /* fall through */
   2347     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   2348         rv = _phy_xgxs16g1l_control_tx_driver_set(unit, pc, type, value);
   2349         break;
   2350     case SOC_PHY_CONTROL_EQUALIZER_BOOST:
   2351         rv = MODIFY_XGXS16G_RX0_RX_ANALOGBIAS0r(unit, pc, value,
   2352                                   RX_ALL_RX_EQ_BOOST_EQUALIZER_CONTROL_MASK);
   2353         break;
   2354     case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT:
   2355         rv = _phy_xgxs16g1l_control_linkdown_transmit_set(unit, port, value);
   2356         break;
   2357 
   2358     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   2359         rv = _phy_xgxs16g1l_control_prbs_polynomial_set(unit, port, value);
   2360         break;
   2361     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   2362         rv = _phy_xgxs16g1l_control_prbs_tx_invert_data_set(unit, port, value);
   2363         break;
   2364     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   2365         rv = _phy_xgxs16g1l_control_prbs_tx_enable_set(unit, port, value);
   2366         break;
   2367     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   2368         rv = _phy_xgxs16g1l_control_prbs_rx_enable_set(unit, port, value);
   2369         break;
   2370     case SOC_PHY_CONTROL_PARALLEL_DETECTION:
   2371         /* enable 1000X parallel detect */
   2372         SOC_IF_ERROR_RETURN
   2373             (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc,
   2374             value? SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK:0,              SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK));
   2375         rv = SOC_E_NONE;
   2376         break;
   2377     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   2378         SOC_IF_ERROR_RETURN(
   2379                 MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc,
   2380                 value ? SERDESDIGITAL_CONTROL1000X1_REMOTE_LOOPBACK_MASK : 0,
   2381                 SERDESDIGITAL_CONTROL1000X1_REMOTE_LOOPBACK_MASK));
   2382         rv = SOC_E_NONE;
   2383         break; 
   2384     default:
   2385         rv = (SOC_E_UNAVAIL);
   2386         break;
   2387     }
   2388     return rv;
   2389 }
   2390 
   2391 STATIC int
   2392 _phy_xgxs16g1l_control_tx_driver_get(int unit, phy_ctrl_t *pc,
   2393                                 soc_phy_control_t type, uint32 *value)
   2394 {
   2395     uint16  data16;           /* Temporary holder of 16 bit reg value */
   2396 
   2397     /* Read preemphasis/driver/pre-driver current */
   2398     if (XGXS16G_13G_ID(pc) || XGXS16G_2p5G_ID(pc)){
   2399         switch(pc->lane_num){
   2400         case 0:
   2401              SOC_IF_ERROR_RETURN
   2402                  (READ_XGXS13G_040_TX0_ACONTROL1r(unit, pc, &data16));
   2403              break;
   2404         case 1:
   2405              SOC_IF_ERROR_RETURN
   2406                  (READ_XGXS13G_040_TX1_ACONTROL1r(unit, pc, &data16));
   2407              break;
   2408         case 2:
   2409              SOC_IF_ERROR_RETURN
   2410                  (READ_XGXS13G_040_TX2_ACONTROL1r(unit, pc, &data16));
   2411              break;
   2412         case 3:
   2413              SOC_IF_ERROR_RETURN
   2414                  (READ_XGXS13G_040_TX3_ACONTROL1r(unit, pc, &data16));
   2415              break;
   2416         default:
   2417              SOC_IF_ERROR_RETURN
   2418                  (READ_XGXS13G_040_TX_ALL_ACONTROL1r(unit, pc, &data16));
   2419              break;
   2420         }
   2421         switch(type) {
   2422         case SOC_PHY_CONTROL_PREEMPHASIS:
   2423              *value = (data16 & TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_MASK) >>
   2424                       TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_SHIFT;
   2425              break;
   2426         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   2427              *value = (data16 & TX_ALL_040_TX_DRIVER_IDRIVER_MASK) >>
   2428                       TX_ALL_040_TX_DRIVER_IDRIVER_SHIFT;
   2429              break;
   2430         default:
   2431              /* should never get here */
   2432              return (SOC_E_PARAM);
   2433         }
   2434     } else {
   2435         switch(pc->lane_num){
   2436         case 0:
   2437              SOC_IF_ERROR_RETURN
   2438                  (READ_XGXS16G_TX0_TX_DRIVERr(unit, pc, &data16));
   2439              break;
   2440         case 1:
   2441              SOC_IF_ERROR_RETURN
   2442                  (READ_XGXS16G_TX1_TX_DRIVERr(unit, pc, &data16));
   2443              break;
   2444         case 2:
   2445              SOC_IF_ERROR_RETURN
   2446                  (READ_XGXS16G_TX2_TX_DRIVERr(unit, pc, &data16));
   2447              break;
   2448         case 3:
   2449              SOC_IF_ERROR_RETURN
   2450                  (READ_XGXS16G_TX3_TX_DRIVERr(unit, pc, &data16));
   2451              break;
   2452         default:
   2453              SOC_IF_ERROR_RETURN
   2454                  (READ_XGXS16G_TX_ALL_TX_DRIVERr(unit, pc, &data16));
   2455              break;
   2456         }
   2457         switch(type) {
   2458         case SOC_PHY_CONTROL_PREEMPHASIS:
   2459              *value = (data16 & TX_ALL_TX_DRIVER_PREEMPHASIS_MASK) >>
   2460                       TX_ALL_TX_DRIVER_PREEMPHASIS_SHIFT;
   2461              break;
   2462         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   2463               *value = (data16 & TX_ALL_TX_DRIVER_IDRIVER_MASK) >>
   2464                        TX_ALL_TX_DRIVER_IDRIVER_SHIFT;
   2465               break;
   2466         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   2467               *value = (data16 & TX_ALL_TX_DRIVER_IPREDRIVER_MASK) >>
   2468                        TX_ALL_TX_DRIVER_IPREDRIVER_SHIFT;
   2469               break;
   2470         default:
   2471               /* should never get here */
   2472               return (SOC_E_PARAM);
   2473         }
   2474     }
   2475     return (SOC_E_NONE);
   2476 }
   2477 
   2478 /*
   2479  * Function:
   2480  *      phy_xgxs16g1l_control_get
   2481  * Purpose:
   2482  *      Get current control settign of the PHY. 
   2483  * Parameters:
   2484  *      unit  - StrataSwitch unit #.
   2485  *      port  - StrataSwitch port #. 
   2486  *      type  - Control to update 
   2487  *      value - (OUT)Current setting for the control 
   2488  * Returns:     
   2489  *      SOC_E_NONE
   2490  */
   2491 STATIC int
   2492 phy_xgxs16g1l_control_get(int unit, soc_port_t port,
   2493                      soc_phy_control_t type, uint32 *value)
   2494 {
   2495     int rv;
   2496     phy_ctrl_t *pc;
   2497     uint16 data16;
   2498     /* coverity[mixed_enums] */
   2499     if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) {
   2500         return (SOC_E_PARAM);
   2501     }
   2502 
   2503     pc = INT_PHY_SW_STATE(unit, port);
   2504     rv = SOC_E_UNAVAIL;
   2505     switch(type) {
   2506     case SOC_PHY_CONTROL_PREEMPHASIS:
   2507         /* fall through */
   2508     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   2509         /* fall through */
   2510     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   2511         rv = _phy_xgxs16g1l_control_tx_driver_get(unit, pc, type, value);
   2512         break;
   2513     case SOC_PHY_CONTROL_EQUALIZER_BOOST:
   2514         SOC_IF_ERROR_RETURN
   2515             (READ_XGXS16G_RX0_RX_ANALOGBIAS0r(unit, pc, &data16));
   2516         *value = data16 & RX_ALL_RX_EQ_BOOST_EQUALIZER_CONTROL_MASK;
   2517         rv = SOC_E_NONE;
   2518         break;
   2519     case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT:
   2520         rv = _phy_xgxs16g1l_control_linkdown_transmit_get(unit, port, value);
   2521         break;
   2522     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   2523         rv = _phy_xgxs16g1l_control_prbs_polynomial_get(unit, port, value);
   2524         break;
   2525     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   2526         rv = _phy_xgxs16g1l_control_prbs_tx_invert_data_get(unit, port, value);
   2527         break;
   2528     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   2529         rv = _phy_xgxs16g1l_control_prbs_tx_enable_get(unit, port, value);
   2530         break;
   2531     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   2532         rv = _phy_xgxs16g1l_control_prbs_rx_enable_get(unit, port, value);
   2533         break;
   2534     case SOC_PHY_CONTROL_PRBS_RX_STATUS:
   2535         rv = _phy_xgxs16g1l_control_prbs_rx_status_get(unit, port, value);
   2536         break;
   2537     case SOC_PHY_CONTROL_PARALLEL_DETECTION:
   2538         SOC_IF_ERROR_RETURN
   2539             (READ_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc,&data16));
   2540         *value =
   2541            data16 & SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK?
   2542              TRUE: FALSE;
   2543         rv = SOC_E_NONE;
   2544         break;
   2545     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   2546         SOC_IF_ERROR_RETURN
   2547             (READ_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, &data16));
   2548         * value =
   2549             data16 & SERDESDIGITAL_CONTROL1000X1_REMOTE_LOOPBACK_MASK?
   2550             TRUE : FALSE;
   2551         rv = SOC_E_NONE;
   2552         break; 
   2553     case SOC_PHY_CONTROL_VCO_DISTURBED:
   2554          rv = _phy_xgxs16g1l_control_vco_disturbed_get(unit, port, value);
   2555          break;
   2556     default:
   2557         rv = (SOC_E_UNAVAIL);
   2558         break;
   2559     }
   2560     return rv;
   2561 }
   2562 
   2563 /*
   2564  * Function:
   2565  *      phy_xgxs16g1l_reg_read
   2566  * Purpose:
   2567  *      Routine to read PHY register
   2568  * Parameters:
   2569  *      uint         - BCM unit number
   2570  *      pc           - PHY state
   2571  *      flags        - Flags which specify the register type
   2572  *      phy_reg_addr - Encoded register address
   2573  *      phy_data     - (OUT) Value read from PHY register
   2574  * Note:
   2575  *      This register read function is not thread safe. Higher level
   2576  * function that calls this function must obtain a per port lock
   2577  * to avoid overriding register page mapping between threads.
   2578  */
   2579 STATIC int
   2580 phy_xgxs16g1l_reg_read(int unit, soc_port_t port, uint32 flags,
   2581                   uint32 phy_reg_addr, uint32 *phy_data)
   2582 {
   2583     uint16               data;     /* Temporary holder for phy_data */
   2584     phy_ctrl_t          *pc;      /* PHY software state */
   2585 
   2586     pc = INT_PHY_SW_STATE(unit, port);
   2587 
   2588     SOC_IF_ERROR_RETURN
   2589         (phy_reg_aer_read(unit, pc, phy_reg_addr, &data));
   2590 
   2591    *phy_data = data;
   2592 
   2593     return (SOC_E_NONE);
   2594 }
   2595 
   2596 /*
   2597  * Function:
   2598  *      phy_xgxs16g1l_reg_write
   2599  * Purpose:
   2600  *      Routine to write PHY register
   2601  * Parameters:
   2602  *      uint         - BCM unit number
   2603  *      pc           - PHY state
   2604  *      flags        - Flags which specify the register type
   2605  *      phy_reg_addr - Encoded register address
   2606  *      phy_data     - Value write to PHY register
   2607  * Note:
   2608  *      This register read function is not thread safe. Higher level
   2609  * function that calls this function must obtain a per port lock
   2610  * to avoid overriding register page mapping between threads.
   2611  */
   2612 STATIC int
   2613 phy_xgxs16g1l_reg_write(int unit, soc_port_t port, uint32 flags,
   2614                    uint32 phy_reg_addr, uint32 phy_data)
   2615 {
   2616     uint16               data;     /* Temporary holder for phy_data */
   2617     phy_ctrl_t          *pc;      /* PHY software state */
   2618 
   2619     pc = INT_PHY_SW_STATE(unit, port);
   2620 
   2621     data      = (uint16) (phy_data & 0x0000FFFF);
   2622 
   2623     SOC_IF_ERROR_RETURN
   2624         (phy_reg_aer_write(unit, pc, phy_reg_addr, data));
   2625 
   2626     return (SOC_E_NONE);
   2627 }  
   2628 
   2629 /*
   2630  * Function:
   2631  *      phy_xgxs16g1l_reg_modify
   2632  * Purpose:
   2633  *      Routine to write PHY register
   2634  * Parameters:
   2635  *      uint         - BCM unit number
   2636  *      pc           - PHY state
   2637  *      flags        - Flags which specify the register type
   2638  *      phy_reg_addr - Encoded register address
   2639  *      phy_mo_data  - New value for the bits specified in phy_mo_mask
   2640  *      phy_mo_mask  - Bit mask to modify
   2641  * Note:
   2642  *      This register read function is not thread safe. Higher level
   2643  * function that calls this function must obtain a per port lock
   2644  * to avoid overriding register page mapping between threads.
   2645  */
   2646 STATIC int
   2647 phy_xgxs16g1l_reg_modify(int unit, soc_port_t port, uint32 flags,
   2648                     uint32 phy_reg_addr, uint32 phy_data,
   2649                     uint32 phy_data_mask)
   2650 {
   2651     uint16               data;     /* Temporary holder for phy_data */
   2652     uint16               mask;
   2653     phy_ctrl_t    *pc;      /* PHY software state */
   2654 
   2655     pc = INT_PHY_SW_STATE(unit, port);
   2656 
   2657     data      = (uint16) (phy_data & 0x0000FFFF);
   2658     mask      = (uint16) (phy_data_mask & 0x0000FFFF);
   2659 
   2660     SOC_IF_ERROR_RETURN
   2661         (phy_reg_aer_modify(unit, pc, phy_reg_addr, data, mask));
   2662 
   2663     return (SOC_E_NONE);
   2664 }
   2665 
   2666 STATIC int
   2667 phy_xgxs16g1l_probe(int unit, phy_ctrl_t *pc)
   2668 {
   2669     uint16      serdes_id0;
   2670     uint16      serdes_id2;
   2671     soc_info_t *si;
   2672     int phy_port;  /* physical port number */
   2673 
   2674     si = &SOC_INFO(unit);
   2675     if (soc_feature(unit, soc_feature_logical_port_num)) {
   2676         phy_port = si->port_l2p_mapping[pc->port];
   2677     } else {
   2678         phy_port = pc->port;
   2679     }
   2680 
   2681     SOC_IF_ERROR_RETURN
   2682         (READ_XGXS16G_SERDESID_SERDESID0r(unit, pc, &serdes_id0));
   2683     SOC_IF_ERROR_RETURN
   2684         (READ_XGXS16G_SERDESID_SERDESID2r(unit, pc, &serdes_id2));
   2685 
   2686     LOG_INFO(BSL_LS_SOC_PHY,
   2687              (BSL_META_U(unit,
   2688                          "_phy_xgxs16g_probe u=%d p=%d: id0 = 0x%x, id1 = 0x%x\n"),
   2689               unit, pc->port, serdes_id0,serdes_id2));
   2690 
   2691     if (((serdes_id0 & SERDESID_SERDESID0_MODEL_NUMBER_MASK) ==
   2692         SERDES_ID0_MODEL_NUMBER_XGXS_16G) && 
   2693            (serdes_id2 & SERDESID_SERDESID2_DR_16G_4L_MASK)) {
   2694         LOG_INFO(BSL_LS_SOC_PHY,
   2695                  (BSL_META_U(unit,
   2696                              "_phy_xgxs16g_probe u=%d p=%d: xgxs16g\n"),
   2697                   unit, pc->port));
   2698         /* XGXS16G */
   2699         pc->size = sizeof(XGXS16G_DEV_DESC);
   2700         return SOC_E_NONE;
   2701     }
   2702 
   2703     if (((serdes_id0 & SERDESID_SERDESID0_MODEL_NUMBER_MASK) == 
   2704         SERDES_ID0_MODEL_NUMBER_XGXS_16G) && 
   2705         (serdes_id2 & SERDESID_SERDESID2_DR_13G_4L_MASK)) {
   2706         LOG_INFO(BSL_LS_SOC_PHY,
   2707                  (BSL_META_U(unit,
   2708                              "_phy_xgxs16g_probe u=%d p=%d: xgxs13g\n"),
   2709                   unit, pc->port));
   2710         /* XGXS13G new 40nm serdes */
   2711         pc->lane_num = SOC_PORT_BINDEX(unit, phy_port);
   2712         pc->chip_num = SOC_BLOCK_NUMBER(unit, SOC_PORT_BLOCK(unit, phy_port));
   2713         if (SOC_IS_TRIUMPH3(unit)) {
   2714             pc->lane_num = pc->lane_num % 4;
   2715         } else if (pc->lane_num >= 4) {
   2716             LOG_WARN(BSL_LS_SOC_PHY,
   2717                      (BSL_META_U(unit,
   2718                                  "_phy_xgxs16g_probe u=%d p=%d: wrong lane# 0x%x, set to 0\n"),
   2719                       unit, pc->port, pc->lane_num));
   2720             pc->lane_num = 0;
   2721         }
   2722 
   2723         pc->dev_name = "XGXS13G1l";
   2724 
   2725         pc->size = sizeof(XGXS16G_DEV_DESC);
   2726         return SOC_E_NONE;
   2727     }
   2728 
   2729     if (((serdes_id0 & SERDESID_SERDESID0_MODEL_NUMBER_MASK) == 0xf) && 
   2730         (serdes_id2 & SERDESID_SERDESID2_DR_2P5G_SL_MASK)) {
   2731         LOG_INFO(BSL_LS_SOC_PHY,
   2732                  (BSL_META_U(unit,
   2733                              "_phy_xgxs16g_probe u=%d p=%d: qs40\n"),
   2734                   unit, pc->port));
   2735         /* quad SGMII new 40nm serdes */
   2736         pc->lane_num = SOC_PORT_BINDEX(unit, phy_port);
   2737         pc->chip_num = SOC_BLOCK_NUMBER(unit, SOC_PORT_BLOCK(unit, phy_port));
   2738         pc->chip_num *= 2;
   2739         pc->chip_num += pc->lane_num/4;
   2740         pc->lane_num %= 4;
   2741 
   2742         if (SOC_IS_TRIUMPH3(unit)) {
   2743             pc->lane_num = pc->lane_num % 4;
   2744         } else if (pc->lane_num >= 4) {
   2745             LOG_WARN(BSL_LS_SOC_PHY,
   2746                      (BSL_META_U(unit,
   2747                                  "_phy_xgxs16g_probe u=%d p=%d: wrong lane# 0x%x, set to 0\n"),
   2748                       unit, pc->port, pc->lane_num));
   2749             pc->lane_num = 0;
   2750         }
   2751         pc->dev_name = "QS40";
   2752 
   2753         pc->size = sizeof(XGXS16G_DEV_DESC);
   2754         return SOC_E_NONE;
   2755     }
   2756 
   2757     return SOC_E_NOT_FOUND;
   2758 }
   2759 
   2760 STATIC int
   2761 phy_xgxs16g1l_notify(int unit, soc_port_t port,
   2762                  soc_phy_event_t event, uint32 value)
   2763 {
   2764     int             rv;
   2765 
   2766     if (event >= phyEventCount) {
   2767         return SOC_E_PARAM;
   2768     }
   2769 
   2770     rv = SOC_E_NONE;
   2771     switch(event) {
   2772     case phyEventInterface:
   2773         rv = (_phy_xgxs16g1l_notify_interface(unit, port, value));
   2774         break;
   2775     case phyEventDuplex:
   2776         rv = (_phy_xgxs16g1l_notify_duplex(unit, port, value));
   2777         break;
   2778     case phyEventSpeed:
   2779         rv = (_phy_xgxs16g1l_notify_speed(unit, port, value));
   2780         break;
   2781     case phyEventStop:
   2782         rv = (_phy_xgxs16g1l_notify_stop(unit, port, value));
   2783         break;
   2784     case phyEventResume:
   2785         rv = (_phy_xgxs16g1l_notify_resume(unit, port, value));
   2786         break;
   2787     default:
   2788         rv = SOC_E_PARAM;
   2789         break;
   2790     }
   2791 
   2792     return rv;
   2793 }
   2794 
   2795 /*
   2796  * Function:
   2797  *      phy_xgxs16g1l_duplex_set
   2798  * Purpose:
   2799  *      Set the current duplex mode (forced).
   2800  * Parameters:
   2801  *      unit - StrataSwitch unit #.
   2802  *      port - StrataSwitch port #.
   2803  *      duplex - Boolean, true indicates full duplex, false indicates half.
   2804  * Returns:
   2805  *      SOC_E_XXX
   2806  */
   2807 
   2808 STATIC int
   2809 phy_xgxs16g1l_duplex_set(int unit, soc_port_t port, int duplex)
   2810 {
   2811     uint16       data16;
   2812     phy_ctrl_t  *pc;
   2813                                                                                 
   2814     pc = INT_PHY_SW_STATE(unit, port);
   2815                                                                                 
   2816     SOC_IF_ERROR_RETURN
   2817         (READ_XGXS16G_GP_STATUS_STATUS1000X1r(unit, pc, &data16));
   2818 
   2819     if (!(data16 & GP_STATUS_STATUS1000X1_SGMII_MODE_MASK)) {
   2820         /* 1000X fiber mode, always full duplex */
   2821         duplex = TRUE;
   2822     }
   2823 
   2824     data16 = duplex? MII_CTRL_FD: 0;
   2825  
   2826     /* program the duplex setting */
   2827     SOC_IF_ERROR_RETURN
   2828         (MODIFY_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, data16,MII_CTRL_FD));
   2829                                                                                 
   2830     return SOC_E_NONE;
   2831 }
   2832 
   2833 STATIC int
   2834 phy_xgxs16g1l_duplex_get(int unit, soc_port_t port, int *duplex)
   2835 {
   2836     uint16       reg0_16;
   2837     uint16       mii_ctrl;
   2838     phy_ctrl_t  *pc;
   2839                                                                                
   2840     pc = INT_PHY_SW_STATE(unit, port);
   2841                                                                                
   2842     *duplex = TRUE;
   2843                                                                                
   2844     SOC_IF_ERROR_RETURN
   2845         (READ_XGXS16G_GP_STATUS_STATUS1000X1r(unit, pc, &reg0_16));
   2846                                                                                
   2847     if (reg0_16 & GP_STATUS_STATUS1000X1_SGMII_MODE_MASK) {
   2848                                                                                
   2849     /* retrieve the duplex setting in SGMII mode */
   2850         SOC_IF_ERROR_RETURN
   2851             (READ_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl));
   2852                                                                                
   2853         if (mii_ctrl & MII_CTRL_AE) {
   2854             SOC_IF_ERROR_RETURN
   2855                 (READ_XGXS16G_COMBO_IEEE0_AUTONEGLPABILr(unit,pc,&reg0_16));
   2856                                                                                
   2857             /* make sure link partner is also in SGMII mode
   2858              * otherwise fall through to use the FD bit in MII_CTRL reg
   2859              */
   2860             if (reg0_16 & MII_ANP_SGMII_MODE) {
   2861                 if (reg0_16 & MII_ANP_SGMII_FD) {
   2862                     *duplex = TRUE;
   2863                 } else {
   2864                     *duplex = FALSE;
   2865                 }
   2866                 return SOC_E_NONE;
   2867             }
   2868         }
   2869         *duplex = (mii_ctrl & MII_CTRL_FD) ? TRUE : FALSE;
   2870     }
   2871                                                                                
   2872     return SOC_E_NONE;
   2873 }
   2874 
   2875 /*
   2876  * Variable:
   2877  *      phy_xgxs16g1l_drv
   2878  * Purpose:
   2879  *      Phy Driver for 10G (XAUI x 4) Serdes PHY. 
   2880  */
   2881 
   2882 phy_driver_t phy_xgxs16g1l_ge = {
   2883     /* .drv_name                      = */ "XGXS16G/1 Unicore PHY Driver",
   2884     /* .pd_init                       = */ phy_xgxs16g1l_init,
   2885     /* .pd_reset                      = */ phy_null_reset,
   2886     /* .pd_link_get                   = */ phy_xgxs16g1l_link_get,
   2887     /* .pd_enable_set                 = */ phy_xgxs16g1l_enable_set,
   2888     /* .pd_enable_get                 = */ phy_null_enable_get,
   2889     /* .pd_duplex_set                 = */ phy_xgxs16g1l_duplex_set,
   2890     /* .pd_duplex_get                 = */ phy_xgxs16g1l_duplex_get,
   2891     /* .pd_speed_set                  = */ phy_xgxs16g1l_speed_set,
   2892     /* .pd_speed_get                  = */ phy_xgxs16g1l_speed_get,
   2893     /* .pd_master_set                 = */ phy_null_set,
   2894     /* .pd_master_get                 = */ phy_xgxs16g1l_master_get,
   2895     /* .pd_an_set                     = */ phy_xgxs16g1l_an_set,
   2896     /* .pd_an_get                     = */ phy_xgxs16g1l_an_get,
   2897     /* .pd_adv_local_set              = */ NULL, /* Deprecated */
   2898     /* .pd_adv_local_get              = */ NULL, /* Deprecated */
   2899     /* .pd_adv_remote_get             = */ NULL, /* Deprecated */ 
   2900     /* .pd_lb_set                     = */ phy_xgxs16g1l_lb_set,
   2901     /* .pd_lb_get                     = */ phy_xgxs16g1l_lb_get,
   2902     /* .pd_interface_set              = */ phy_null_interface_set,
   2903     /* .pd_interface_get              = */ phy_xgxs16g1l_interface_get,
   2904     /* .pd_ability                    = */ NULL, /* Deprecated */ 
   2905     /* .pd_linkup_evt                 = */ NULL,
   2906     /* .pd_linkdn_evt                 = */ NULL,
   2907     /* .pd_mdix_set                   = */ phy_null_mdix_set,
   2908     /* .pd_mdix_get                   = */ phy_null_mdix_get,
   2909     /* .pd_mdix_status_get            = */ phy_null_mdix_status_get,
   2910     /* .pd_medium_config_set          = */ phy_xgxs16g1l_medium_config_set,
   2911     /* .pd_medium_config_get          = */ NULL,
   2912     /* .pd_medium_get                 = */ phy_xgxs16g1l_medium_get,
   2913     /* .pd_cable_diag                 = */ NULL,
   2914     /* .pd_link_change                = */ NULL,
   2915     /* .pd_control_set                = */ phy_xgxs16g1l_control_set,
   2916     /* .pd_control_get                = */ phy_xgxs16g1l_control_get,
   2917     /* .pd_reg_read                   = */ phy_xgxs16g1l_reg_read,
   2918     /* .pd_reg_write                  = */ phy_xgxs16g1l_reg_write,
   2919     /* .pd_reg_modify                 = */ phy_xgxs16g1l_reg_modify,
   2920     /* .pd_notify                     = */ phy_xgxs16g1l_notify,
   2921     /* .pd_probe                      = */ phy_xgxs16g1l_probe,
   2922     /* .pd_ability_advert_set         = */ phy_xgxs16g1l_ability_advert_set, 
   2923     /* .pd_ability_advert_get         = */ phy_xgxs16g1l_ability_advert_get,
   2924     /* .pd_ability_remote_get         = */ phy_xgxs16g1l_ability_remote_get,
   2925     /* .pd_ability_local_get          = */ phy_xgxs16g1l_ability_local_get
   2926 };
   2927 
   2928 /***********************************************************************
   2929  *
   2930  * PASS-THROUGH NOTIFY ROUTINES
   2931  */
   2932 
   2933 /*
   2934  * Function:
   2935  *      phy_xgxs16g1l_notify_duplex
   2936  * Purpose:
   2937  *      Program duplex if (and only if) 56xxx is an intermediate PHY.
   2938  * Parameters:
   2939  *      unit - StrataSwitch unit #.
   2940  *      port - StrataSwitch port #.
   2941  *      duplex - Boolean, TRUE indicates full duplex, FALSE
   2942  *              indicates half.
   2943  * Returns:
   2944  *      SOC_E_XXX
   2945  * Notes:
   2946  *      If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to
   2947  *      talk directly to an external fiber module.
   2948  *
   2949  *      If PHY_FLAGS_FIBER is clear, the PHY is being used in
   2950  *      pass-through mode to talk to an external SGMII PHY.
   2951  *
   2952  *      When used in SGMII mode, autoneg must be turned off and
   2953  *      the speed/duplex forced to match that of the external PHY.
   2954  */
   2955 STATIC int
   2956 _phy_xgxs16g1l_notify_duplex(int unit, soc_port_t port, uint32 duplex)
   2957 {
   2958     int                 fiber;
   2959                                                                                
   2960     fiber = PHY_FIBER_MODE(unit, port);
   2961     LOG_INFO(BSL_LS_SOC_PHY,
   2962              (BSL_META_U(unit,
   2963                          "_phy_xgxs16g1l_notify_duplex: "
   2964                          "u=%d p=%d duplex=%d fiber=%d\n"),
   2965               unit, port, duplex, fiber));
   2966                                                                                
   2967     if (SAL_BOOT_SIMULATION) {
   2968         return SOC_E_NONE;
   2969     }
   2970                                                                                
   2971     /* Put SERDES PHY in reset */
   2972                                                                                
   2973     SOC_IF_ERROR_RETURN
   2974         (_phy_xgxs16g1l_notify_stop(unit, port, PHY_STOP_DUPLEX_CHG));
   2975 
   2976     SOC_IF_ERROR_RETURN
   2977         (phy_xgxs16g1l_duplex_set(unit,port,duplex));
   2978 
   2979     /* Take SERDES PHY out of reset */
   2980     SOC_IF_ERROR_RETURN
   2981         (_phy_xgxs16g1l_notify_resume(unit, port, PHY_STOP_DUPLEX_CHG));
   2982                                                                                
   2983     /* Autonegotiation must be turned off to talk to external PHY if
   2984      * SGMII autoneg is not enabled.
   2985      */
   2986     if (!PHY_SGMII_AUTONEG_MODE(unit, port)) {
   2987         SOC_IF_ERROR_RETURN
   2988             (phy_xgxs16g1l_an_set(unit, port, FALSE));
   2989     }
   2990     return SOC_E_NONE;
   2991 }
   2992 
   2993 /*
   2994  * Function:
   2995  *      phy_xgxs16g1l_notify_speed
   2996  * Purpose:
   2997  *      Program duplex if (and only if) 56xxx is an intermediate PHY.
   2998  * Parameters:
   2999  *      unit - StrataSwitch unit #.
   3000  *      port - StrataSwitch port #.
   3001  *      speed - Speed to program.
   3002  * Returns:
   3003  *      SOC_E_XXX
   3004  * Notes:
   3005  *      If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to
   3006  *      talk directly to an external fiber module.
   3007  *
   3008  *      If PHY_FLAGS_FIBER is clear, the PHY is being used in
   3009  *      pass-through mode to talk to an external SGMII PHY.
   3010  *
   3011  *      When used in pass-through mode, autoneg must be turned off and
   3012  *      the speed/duplex forced to match that of the external PHY.
   3013  */
   3014 
   3015 STATIC int
   3016 _phy_xgxs16g1l_notify_speed(int unit, soc_port_t port, uint32 speed)
   3017 {
   3018     /* Put SERDES PHY in reset */
   3019     SOC_IF_ERROR_RETURN
   3020         (_phy_xgxs16g1l_notify_stop(unit, port, PHY_STOP_SPEED_CHG));
   3021 
   3022     /* Update speed */
   3023     SOC_IF_ERROR_RETURN
   3024         (phy_xgxs16g1l_speed_set(unit, port, speed));
   3025 
   3026     /* Take SERDES PHY out of reset */
   3027     SOC_IF_ERROR_RETURN
   3028         (_phy_xgxs16g1l_notify_resume(unit, port, PHY_STOP_SPEED_CHG));
   3029 
   3030     /* Autonegotiation must be turned off to talk to external PHY */
   3031     if (!PHY_SGMII_AUTONEG_MODE(unit, port) && PHY_EXTERNAL_MODE(unit, port)) {        SOC_IF_ERROR_RETURN
   3032             (phy_xgxs16g1l_an_set(unit, port, FALSE));
   3033     }
   3034 
   3035     return (SOC_E_NONE);
   3036 }
   3037 
   3038 /*
   3039  * Function:
   3040  *      _phy_xgxs16g1l_stop
   3041  * Purpose:
   3042  *      Put 56xxx SERDES in or out of reset depending on conditions
   3043  */
   3044 
   3045 STATIC int
   3046 _phy_xgxs16g1l_stop(int unit, soc_port_t port)
   3047 {
   3048     uint16 mask16,data16;
   3049     int          stop, copper;
   3050     phy_ctrl_t  *pc;
   3051 
   3052     pc = INT_PHY_SW_STATE(unit, port);
   3053 
   3054     copper = (pc->stop &
   3055               PHY_STOP_COPPER) != 0;
   3056     stop = ((pc->stop &
   3057              (PHY_STOP_PHY_DIS |
   3058               PHY_STOP_DRAIN)) != 0 ||
   3059             (copper &&
   3060              (pc->stop &
   3061               (PHY_STOP_MAC_DIS |
   3062                PHY_STOP_DUPLEX_CHG |
   3063                PHY_STOP_SPEED_CHG)) != 0));
   3064 
   3065     LOG_INFO(BSL_LS_SOC_PHY,
   3066              (BSL_META_U(unit,
   3067                          "phy_xgxs16g1l_stop: u=%d p=%d copper=%d stop=%d flg=0x%x\n"),
   3068               unit, port, copper, stop,
   3069               pc->stop));
   3070 
   3071     mask16 = (1 << pc->lane_num);    /* rx lane */
   3072     mask16 |= (mask16 << 4); /* add tx lane */
   3073                                                                                
   3074     if (stop) {
   3075         mask16 |= 0x800;
   3076         data16 = mask16;
   3077     } else {
   3078         data16 = 0;
   3079     }
   3080                                                                                
   3081     SOC_IF_ERROR_RETURN
   3082         (MODIFY_XGXS16G_XGXSBLK1_LANECTRL3r(unit,pc,data16,mask16));
   3083                                                                                
   3084     return SOC_E_NONE;
   3085 }
   3086 
   3087 /*
   3088  * Function:
   3089  *      phy_xgxs16g1l_notify_stop
   3090  * Purpose:
   3091  *      Add a reason to put 56xxx PHY in reset.
   3092  * Parameters:
   3093  *      unit - StrataSwitch unit #.
   3094  *      port - StrataSwitch port #.
   3095  *      flags - Reason to stop
   3096  * Returns:
   3097  *      SOC_E_XXX
   3098  */
   3099 STATIC int
   3100 _phy_xgxs16g1l_notify_stop(int unit, soc_port_t port, uint32 flags)
   3101 {
   3102     phy_ctrl_t  *pc;
   3103 
   3104     pc = INT_PHY_SW_STATE(unit, port);
   3105 
   3106     pc->stop |= flags;
   3107 
   3108     return _phy_xgxs16g1l_stop(unit, port);
   3109 }
   3110 
   3111 /*
   3112  * Function:
   3113  *      phy_xgxs16g1l_notify_resume
   3114  * Purpose:
   3115  *      Remove a reason to put 56xxx PHY in reset.
   3116  * Parameters:
   3117  *      unit - StrataSwitch unit #.
   3118  *      port - StrataSwitch port #.
   3119  *      flags - Reason to stop
   3120  * Returns:
   3121  *      SOC_E_XXX
   3122  */
   3123 STATIC int
   3124 _phy_xgxs16g1l_notify_resume(int unit, soc_port_t port, uint32 flags)
   3125 {
   3126     phy_ctrl_t  *pc;
   3127 
   3128     pc = INT_PHY_SW_STATE(unit, port);
   3129 
   3130     pc->stop &= ~flags;
   3131 
   3132     return _phy_xgxs16g1l_stop(unit, port);
   3133 }
   3134 
   3135 
   3136 STATIC int
   3137 _phy_xgxs16g1l_notify_interface(int unit, soc_port_t port, uint32 intf)
   3138 {
   3139     phy_ctrl_t  *pc;
   3140     uint16       data16;
   3141 
   3142     pc = INT_PHY_SW_STATE(unit, port);
   3143 
   3144     data16 = (intf == SOC_PORT_IF_SGMII) ? 
   3145                  0 : SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
   3146 
   3147     /* Disable 1000X/SGMII auto detect and force to 1000X.
   3148      * 1000X mode is not supported in this driver.
   3149      */
   3150     SOC_IF_ERROR_RETURN
   3151         (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, data16,
   3152                       SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK));
   3153 
   3154     return SOC_E_NONE;
   3155 }
   3156 
   3157 /*
   3158  * Function:
   3159  *      phy_xgxs16g1l_master_get
   3160  * Purpose:
   3161  *      this function is meant for 1000Base-T PHY. Added here to support
   3162  *      internal PHY regression test
   3163  * Parameters:
   3164  *      unit - StrataSwitch unit #.
   3165  *      port - StrataSwitch port #.
   3166  *      master - (OUT) SOC_PORT_MS_*
   3167  * Returns:
   3168  *      SOC_E_NONE
   3169  * Notes:
   3170  *      The master mode is retrieved for the ACTIVE medium.
   3171  */
   3172 
   3173 STATIC int
   3174 phy_xgxs16g1l_master_get(int unit, soc_port_t port, int *master)
   3175 {
   3176     *master = SOC_PORT_MS_NONE;
   3177     return SOC_E_NONE;
   3178 }
   3179 /*
   3180  * Function:
   3181  *      phy_xgxs16g1l_interface_get
   3182  * Purpose:
   3183  *      this function is meant for 1000Base-T PHY. Added here to support
   3184  *      internal PHY regression test
   3185  * Parameters:
   3186  *      unit - StrataSwitch unit #.
   3187  *      port - StrataSwitch port #.
   3188  *      master - (OUT) SOC_PORT_IF_*
   3189  * Returns:
   3190  *      SOC_E_NONE
   3191  * Notes:
   3192  *      Interface mode is retrieved for the ACTIVE medium.
   3193  */
   3194 
   3195 STATIC int
   3196 phy_xgxs16g1l_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   3197 {
   3198    int speed;
   3199    SOC_IF_ERROR_RETURN(phy_xgxs16g1l_speed_get(unit, port, &speed));
   3200    switch(speed)
   3201    {
   3202    case 10:
   3203    case 100:
   3204         *pif = SOC_PORT_IF_MII;
   3205         break;
   3206    case 1000:
   3207    case 2500:
   3208    default:
   3209         *pif = SOC_PORT_IF_GMII;
   3210         break;
   3211    }
   3212    return SOC_E_NONE;
   3213 }
   3214 
   3215 /*
   3216  * Function:
   3217  * phy_xgxs16g1l_medium_config_set
   3218  * Purpose:
   3219  * set the configured medium the device is operating on.
   3220  * Parameters:
   3221  * unit - StrataSwitch unit #
   3222  * port - Port number
   3223  * medium - SOC_PORT_MEDIUM_COPPER/FIBER
   3224  * cfg - not used
   3225  * Returns:
   3226  * SOC_E_XXX
   3227  */
   3228 STATIC int
   3229 phy_xgxs16g1l_medium_config_set(int unit, soc_port_t port, soc_port_medium_t medium,  soc_phy_config_t *cfg)
   3230 {
   3231     phy_ctrl_t *pc;
   3232     uint16 fiber_mode = 0;
   3233 
   3234     pc = INT_PHY_SW_STATE(unit, port);
   3235 
   3236     switch (medium) {
   3237     case SOC_PORT_MEDIUM_COPPER:
   3238         fiber_mode = 0;
   3239         break;
   3240     case SOC_PORT_MEDIUM_FIBER:
   3241         fiber_mode = SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
   3242         break;
   3243     default:
   3244         return SOC_E_PARAM;
   3245     }
   3246 
   3247     SOC_IF_ERROR_RETURN(MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, fiber_mode,
   3248                             SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK));
   3249 
   3250     return SOC_E_NONE;
   3251 }
   3252 
   3253 /*
   3254  * Function:
   3255  * phy_xgxs16g1l_medium_get
   3256  * Purpose:
   3257  * get the configured medium the device is operating on.
   3258  * Parameters:
   3259  * unit - StrataSwitch unit #
   3260  * port - Port number
   3261  * medium - SOC_PORT_MEDIUM_COPPER/FIBER
   3262  * cfg - not used
   3263  * Returns:
   3264  * SOC_E_XXX
   3265  */
   3266 STATIC int
   3267 phy_xgxs16g1l_medium_get(int unit, soc_port_t port, soc_port_medium_t *medium)
   3268 {
   3269     phy_ctrl_t *pc;
   3270     uint16 data16 = 0;
   3271 
   3272     if (NULL == medium) {
   3273         return (SOC_E_PARAM);
   3274     }
   3275 
   3276     pc = INT_PHY_SW_STATE(unit, port);
   3277 
   3278     SOC_IF_ERROR_RETURN(READ_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, &data16));
   3279 
   3280     *medium = data16 & SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK ? SOC_PORT_MEDIUM_FIBER : SOC_PORT_MEDIUM_COPPER;
   3281 
   3282     return SOC_E_NONE;
   3283 }
   3284 
   3285 #ifdef BROADCOM_DEBUG
   3286 int _phy_xgxs16g1l_cfg_dump(int unit, soc_port_t port)
   3287 {
   3288     phy_ctrl_t  *pc;
   3289     soc_phy_info_t *pi;
   3290     XGXS16G_DEV_DESC *pCfg;
   3291 
   3292     pc = INT_PHY_SW_STATE(unit, port);
   3293     pCfg = (XGXS16G_DEV_DESC *)(pc + 1);
   3294     pi = &SOC_PHY_INFO(unit, port);
   3295 
   3296     LOG_CLI((BSL_META_U(unit,
   3297                         "serdesid0    0x%04x\n"), pCfg->serdes_id0));
   3298     LOG_CLI((BSL_META_U(unit,
   3299                         "serdesid2      0x%04x\n"),
   3300              pCfg->serdes_id2));
   3301     LOG_CLI((BSL_META_U(unit,
   3302                         "chip_num     0x%04x\n"), pc->chip_num));
   3303     LOG_CLI((BSL_META_U(unit,
   3304                         "lane_num     0x%04x\n"), pc->lane_num));
   3305     LOG_CLI((BSL_META_U(unit,
   3306                         "speedMax     0x%04x\n"), pc->speed_max));
   3307     LOG_CLI((BSL_META_U(unit,
   3308                         "pc->flags    0x%04x\n"), pc->flags));
   3309     LOG_CLI((BSL_META_U(unit,
   3310                         "pc->stop     0x%04x\n"), pc->stop));
   3311     LOG_CLI((BSL_META_U(unit,
   3312                         "pi->phy_flags   0x%04x\n"), pi->phy_flags));
   3313     return 0;
   3314 }
   3315 #endif
   3316 
   3317 #else
   3318 int _phy_xgxs16g1l_not_empty;
   3319 #endif /*  INCLUDE_XGXS_16G */
   3320