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

hl65.c (239226B)


      1 /*
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * File:        hl65.c
      9  * Purpose:     Broadcom 10/100/1000/2500/10000/12000/13000/16000/20000 SerDes 
     10  *              (HyperLite 65nm with x1 and x4 lane support)
     11  */
     12 
     13 #include <shared/bsl.h>
     14 
     15 #include <sal/types.h>
     16 #include <sal/core/spl.h>
     17 #include <soc/drv.h>
     18 #include <soc/error.h>
     19 #include <soc/phyreg.h>
     20 #include <soc/port_ability.h>
     21 #include <soc/phyctrl.h>
     22 
     23 #include <soc/phy.h>
     24 #include <soc/phy/phyctrl.h>
     25 #include <soc/phy/drv.h>
     26 
     27 #include "phydefs.h"      /* Must include before other phy related includes */
     28 
     29 #if defined(INCLUDE_XGXS_HL65)
     30 #include "phyconfig.h"     /* Must include before other phy related includes */
     31 #include "phyreg.h"
     32 #include "phyfege.h"
     33 #include "phynull.h"
     34 #include "serdesid.h"
     35 #include "hl65.h"
     36 
     37 /* 
     38  * HL/HC defines not contained in hl65.h which is generated from RDB files 
     39  */
     40 
     41 #define HL65_PLL_WAIT  250000
     42 #define HL65_AN_WAIT   400000   /* 400ms */
     43 #define HL65_NUM_LANES 4
     44 #define TX_DRIVER_DFT_LN_CTRL  0x4
     45 
     46 #define HL_SERDES_ID0_REVID_A0    0x0000
     47 #define HL_SERDES_ID0_REVID_A1    0x0800
     48 #define HL_SERDES_ID0_REVID_B0    0x4000
     49 #define HL_SERDES_ID0_REVID_C0    0x8000
     50 #define HL_SERDES_ID0_REVID_D0    0xc000
     51 
     52 #define HL_ALL_LANES  0xf
     53 #define HL_AER_BCST_OFS_STRAP   0x3ff
     54 
     55 #define HL65_A0A1_DSC_DFE_BRCDR 0x2180
     56 #define HL65_B0C0_DSC_DFE_BRCDR 0x2300
     57 #define OVER1G_UP3_20GPLUS_MASK (DIGITAL3_UP3_DATARATE_25P45GX4_MASK | \
     58 				 DIGITAL3_UP3_DATARATE_21GX4_MASK)
     59 #define PLL_PLLACONTROL4_BIT12_MASK         0x1000
     60 
     61 /* Broadcast to all lanes with AER::MMD_PORT set to aer_bcst_ofs_strap */
     62 #define HL65_BROADCAST_WRITE(_unit, _pc, _bcst_strap, _reg_addr, _data) \
     63         HL65_REG_WRITE((_unit), (_pc), 0x00, \
     64                        ((_bcst_strap) << 16) | (_reg_addr), (_data))
     65 
     66 typedef enum {
     67     PHY_HL65_DSC_CFG_1X_OSR,
     68     PHY_HL65_DSC_CFG_2X_OSR,
     69     PHY_HL65_DSC_CFG_4X_OSR,
     70     PHY_HL65_DSC_CFG_5X_OSR,
     71     PHY_HL65_DSC_CFG_BR_CDR,
     72     PHY_HL65_DSC_CFG_UNKNOWN
     73 } phy_hl65_dsc_cfg_t;
     74 
     75 /* function forward declaration */
     76 STATIC int _phy_hl65_notify_duplex(int unit, soc_port_t port, uint32 duplex);
     77 STATIC int _phy_hl65_notify_speed(int unit, soc_port_t port, uint32 speed);
     78 STATIC int _phy_hl65_notify_stop(int unit, soc_port_t port, uint32 flags);
     79 STATIC int _phy_hl65_notify_resume(int unit, soc_port_t port, uint32 flags);
     80 STATIC int _phy_hl65_notify_interface(int unit, soc_port_t port, uint32 intf);
     81 STATIC int phy_hl65_an_set(int unit, soc_port_t port, int an);
     82 STATIC int phy_hl65_lb_set(int unit, soc_port_t port, int enable);
     83 STATIC int phy_hl65_ability_advert_set(int unit, soc_port_t port,
     84                                       soc_port_ability_t *ability);
     85 STATIC int phy_hl65_ability_local_get(int unit, soc_port_t port,
     86                                 soc_port_ability_t *ability);
     87 STATIC int phy_hl65_diag_ctrl(int, soc_port_t, uint32, int, int, void *); 
     88 STATIC int phy_hl65_speed_set(int unit, soc_port_t port, int speed);
     89 STATIC int phy_hl65_speed_get(int unit, soc_port_t port, int *speed);
     90 STATIC int phy_hl65_an_get(int unit, soc_port_t port, int *an, int *an_done); 
     91 STATIC int _phy_hl65_analog_dsc_init (int unit,int port,int lane);
     92 STATIC int _hl65_xgmii_scw_config (int unit, phy_ctrl_t *pc);
     93 STATIC int _hl65_rxaui_config(int unit, phy_ctrl_t  *pc,int rxaui);
     94 STATIC int _hl65_soft_reset(int unit, phy_ctrl_t  *pc);
     95 STATIC int _hl65_lane_reg_init(int unit, phy_ctrl_t  *pc);
     96 STATIC int phy_hl65_uc_status_dump(int unit, soc_port_t port);
     97 
     98 
     99 
    100 STATIC int
    101 _phy_hl65_pll_lock_wait(int unit, soc_port_t port)
    102 {
    103     uint16           data16;
    104     phy_ctrl_t      *pc;
    105     soc_timeout_t    to;
    106     int              rv;
    107 
    108     pc = INT_PHY_SW_STATE(unit, port);
    109     soc_timeout_init(&to, HL65_PLL_WAIT, 0);
    110     do {
    111         rv = READ_HL65_XGXSBLK0_XGXSSTATUSr(unit, pc, &data16);
    112         if ((data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK) ||
    113             SOC_FAILURE(rv)) {
    114             break;
    115         }
    116     } while (!soc_timeout_check(&to));
    117     if ((data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK) == 0) {
    118         LOG_WARN(BSL_LS_SOC_PHY,
    119                  (BSL_META_U(unit,
    120                              "HL65 : TXPLL did not lock: u=%d p=%d\n"),
    121                   unit, port));
    122         return (SOC_E_TIMEOUT);
    123     }
    124     return (SOC_E_NONE);
    125 }
    126 
    127 STATIC int
    128 _phy_hl65_half_rate_set(int unit, soc_port_t port,int speed)
    129 {
    130     phy_ctrl_t     *pc;
    131     int tx_halfrate_bit;
    132     uint16 serdes_id0;
    133 
    134     pc = INT_PHY_SW_STATE(unit, port);
    135 
    136     SOC_IF_ERROR_RETURN
    137         (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
    138 
    139     serdes_id0 = serdes_id0 & (TEST_SERDESID0_REV_NUMBER_MASK |
    140                             TEST_SERDESID0_REV_LETTER_MASK);
    141 
    142     /* only apply to these revisions */
    143 
    144     if ((serdes_id0 == HL_SERDES_ID0_REVID_A0) ||
    145         (serdes_id0 == HL_SERDES_ID0_REVID_A1) ||
    146         (serdes_id0 == HL_SERDES_ID0_REVID_B0)) {
    147         
    148         if (speed == 2500 || speed == 10000) {
    149             tx_halfrate_bit = TX0_ANATXACONTROL1_TX_SEL_HALFRATE_MASK;
    150         } else {
    151             tx_halfrate_bit = 0;
    152         }
    153                                                                                
    154         /* set tx half rate bits after the link is established at 2.5G or 10G
    155          * in both force mode or autoneg mode.
    156          */
    157         SOC_IF_ERROR_RETURN
    158             (MODIFY_HL65_TX0_ANATXACONTROL1r(unit, pc,
    159                        tx_halfrate_bit,
    160                        TX0_ANATXACONTROL1_TX_SEL_HALFRATE_MASK));
    161         if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
    162             SOC_IF_ERROR_RETURN
    163                 (MODIFY_HL65_TX1_ANATXACONTROL1r(unit, pc,
    164                        tx_halfrate_bit,
    165                        TX0_ANATXACONTROL1_TX_SEL_HALFRATE_MASK));
    166             SOC_IF_ERROR_RETURN
    167                 (MODIFY_HL65_TX2_ANATXACONTROL1r(unit, pc,
    168                        tx_halfrate_bit,
    169                        TX0_ANATXACONTROL1_TX_SEL_HALFRATE_MASK));
    170             SOC_IF_ERROR_RETURN
    171                 (MODIFY_HL65_TX3_ANATXACONTROL1r(unit, pc,
    172                        tx_halfrate_bit,
    173                        TX0_ANATXACONTROL1_TX_SEL_HALFRATE_MASK));
    174         }
    175     }
    176     return (SOC_E_NONE);
    177 }
    178 
    179 STATIC int
    180 _phy_hl65_tx_control_set(int unit, soc_port_t port)
    181 {
    182     phy_ctrl_t     *pc;
    183     uint32          preemph;
    184     uint32          idriver;
    185     uint32          pdriver;
    186     uint16          data16;
    187  
    188     pc = INT_PHY_SW_STATE(unit, port);
    189 
    190     
    191     if (PHY_EXTERNAL_MODE(unit, port)) {
    192         /* HL65 connected to external PHY */
    193         if (IS_HG_PORT(unit, port)) {
    194             preemph = 0x0;
    195             idriver = 0x9;
    196             pdriver = 0x9;
    197         } else if (IS_XE_PORT(unit, port)) {
    198             preemph = 0x0;
    199             idriver = 0x9;
    200             pdriver = 0x9;
    201         } else {
    202             preemph = 0x0;
    203             idriver = 0x9;
    204             pdriver = 0x9;
    205         }
    206     } else {
    207         /* No external PHY */
    208         if (IS_HG_PORT(unit, port)) {
    209             preemph = 0x0;
    210             idriver = 0x9;
    211             pdriver = 0x9;
    212         } else if (IS_XE_PORT(unit, port)) {
    213             preemph = 0x0;
    214             idriver = 0x9;
    215             pdriver = 0x9;
    216         } else {
    217             preemph = 0x0;
    218             idriver = 0x9;
    219             pdriver = 0x9;
    220         }
    221     }
    222 
    223     /* Read config override */
    224     preemph = soc_property_port_get(unit, port,
    225                                     spn_SERDES_PREEMPHASIS, preemph);
    226     idriver = soc_property_port_get(unit, port,
    227                                     spn_SERDES_DRIVER_CURRENT, idriver);
    228     pdriver = soc_property_port_get(unit, port,
    229                                     spn_SERDES_PRE_DRIVER_CURRENT, pdriver);
    230 
    231     
    232     preemph = (preemph << TXB_TX_OS_DRIVER_PREEMPHASIS_POST_SHIFT) &
    233               TXB_TX_OS_DRIVER_PREEMPHASIS_POST_MASK;
    234     idriver = (idriver << TXB_TX_OS_DRIVER_IDRIVER_SHIFT) & 
    235               TXB_TX_OS_DRIVER_IDRIVER_MASK;
    236     pdriver = (pdriver << TXB_TX_OS_DRIVER_IPREDRIVER_SHIFT) &
    237               TXB_TX_OS_DRIVER_IPREDRIVER_MASK;
    238     data16  = (uint16)(preemph | idriver | pdriver);
    239 
    240     SOC_IF_ERROR_RETURN
    241         (MODIFY_HL65_TXB_TX_OS_DRIVERr(unit, pc, data16,
    242                               TXB_TX_OS_DRIVER_PREEMPHASIS_POST_MASK |
    243                               TXB_TX_OS_DRIVER_IDRIVER_MASK |
    244                               TXB_TX_OS_DRIVER_IPREDRIVER_MASK));
    245 
    246     /* set for BR-CDR mode as well */
    247     SOC_IF_ERROR_RETURN
    248         (MODIFY_HL65_TXB_TX_BR_DRIVERr(unit, pc, data16,
    249                               TXB_TX_OS_DRIVER_PREEMPHASIS_POST_MASK |
    250                               TXB_TX_OS_DRIVER_IDRIVER_MASK |
    251                               TXB_TX_OS_DRIVER_IPREDRIVER_MASK));
    252     return SOC_E_NONE;
    253 }
    254 
    255 STATIC int
    256 _hl65_ind_lane_polarity_set (int unit, soc_port_t port)
    257 {
    258     int rxpol;
    259     int txpol;
    260     uint16 data16;
    261     uint16 mask16;
    262     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
    263 
    264     txpol = soc_property_port_get(unit, port,
    265                             spn_PHY_XAUI_TX_POLARITY_FLIP, 0);
    266     rxpol = soc_property_port_get(unit, port,
    267                             spn_PHY_XAUI_RX_POLARITY_FLIP, 0);
    268     if (rxpol) {
    269         /* Flip Rx polarity */
    270         mask16 = RX0_ANARXCONTROLPCI_RX_POLARITY_FORCE_SM_MASK |
    271                  RX0_ANARXCONTROLPCI_RX_POLARITY_R_MASK;
    272         data16 = mask16;
    273         if (pc->lane_num == 0) {
    274             SOC_IF_ERROR_RETURN
    275                 (MODIFY_HL65_RX0_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    276         } else if (pc->lane_num == 1) {
    277             SOC_IF_ERROR_RETURN
    278                 (MODIFY_HL65_RX1_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    279         } else if (pc->lane_num == 2) {
    280             SOC_IF_ERROR_RETURN
    281                 (MODIFY_HL65_RX2_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    282         } else if (pc->lane_num == 3) {
    283             SOC_IF_ERROR_RETURN
    284                 (MODIFY_HL65_RX3_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    285         }
    286         if (pc->phy_mode == PHYCTRL_DUAL_LANE_PORT) {
    287             /* Also flip for the next lane */
    288             if (pc->lane_num == 0) {
    289                 SOC_IF_ERROR_RETURN
    290                     (MODIFY_HL65_RX1_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    291             } else if (pc->lane_num == 2) {
    292                 SOC_IF_ERROR_RETURN
    293                     (MODIFY_HL65_RX3_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    294             }
    295         }
    296     }
    297     if (txpol) {
    298         /* Flip TX polarity */
    299         data16 = TX0_ANATXACONTROL0_TXPOL_FLIP_MASK;
    300         mask16 = TX0_ANATXACONTROL0_TXPOL_FLIP_MASK;
    301         if (pc->lane_num == 0) {
    302             SOC_IF_ERROR_RETURN
    303                 (MODIFY_HL65_TX0_ANATXACONTROL0r(unit, pc, data16, mask16));
    304         } else if (pc->lane_num == 1) {
    305             SOC_IF_ERROR_RETURN
    306                 (MODIFY_HL65_TX1_ANATXACONTROL0r(unit, pc, data16, mask16));
    307         } else if (pc->lane_num == 2) {
    308             SOC_IF_ERROR_RETURN
    309                 (MODIFY_HL65_TX2_ANATXACONTROL0r(unit, pc, data16, mask16));
    310         } else if (pc->lane_num == 3) {
    311             SOC_IF_ERROR_RETURN
    312                 (MODIFY_HL65_TX3_ANATXACONTROL0r(unit, pc, data16, mask16));
    313         }
    314         if (pc->phy_mode == PHYCTRL_DUAL_LANE_PORT) {
    315             /* Also flip for the next lane */
    316             if (pc->lane_num == 0) {
    317                 SOC_IF_ERROR_RETURN
    318                     (MODIFY_HL65_TX1_ANATXACONTROL0r(unit, pc, data16, mask16));
    319             } else if (pc->lane_num == 2) {
    320                 SOC_IF_ERROR_RETURN
    321                     (MODIFY_HL65_TX3_ANATXACONTROL0r(unit, pc, data16, mask16));
    322             }
    323         }
    324     }
    325     return SOC_E_NONE;
    326 }
    327 
    328 STATIC int
    329 _hl65_combo_lane_polarity_set (int unit, soc_port_t port)
    330 {
    331     int rxpol;
    332     int txpol;
    333     uint16 data16;
    334     uint16 mask16;
    335     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
    336 
    337     txpol = soc_property_port_get(unit, port,
    338                             spn_PHY_XAUI_TX_POLARITY_FLIP, 0);
    339     rxpol = soc_property_port_get(unit, port,
    340                             spn_PHY_XAUI_RX_POLARITY_FLIP, 0);
    341 
    342     if (txpol) {             /* Flip TX polarity */
    343         data16 = TX0_ANATXACONTROL0_TXPOL_FLIP_MASK;
    344         mask16 = TX0_ANATXACONTROL0_TXPOL_FLIP_MASK;
    345         if (txpol == 1) {
    346             SOC_IF_ERROR_RETURN
    347                 (MODIFY_HL65_TXB_ANATXACONTROL0r(unit, pc, data16, mask16));
    348         }
    349         if ((txpol & 0x000F) == 0x000F) {
    350             SOC_IF_ERROR_RETURN
    351               (MODIFY_HL65_TX0_ANATXACONTROL0r(unit, pc, data16, mask16));
    352         }
    353         if ((txpol & 0x00F0) == 0x00F0) {
    354             SOC_IF_ERROR_RETURN
    355               (MODIFY_HL65_TX1_ANATXACONTROL0r(unit, pc, data16, mask16));
    356         }
    357         if ((txpol & 0x0F00) == 0x0F00) {
    358             SOC_IF_ERROR_RETURN
    359               (MODIFY_HL65_TX2_ANATXACONTROL0r(unit, pc, data16, mask16));
    360         }
    361         if ((txpol & 0xF000) == 0xF000) {
    362             SOC_IF_ERROR_RETURN
    363               (MODIFY_HL65_TX3_ANATXACONTROL0r(unit, pc, data16, mask16));
    364         }
    365     }
    366     if (rxpol) {
    367         /* Flip Rx polarity */
    368         mask16 = RX0_ANARXCONTROLPCI_RX_POLARITY_FORCE_SM_MASK |
    369              RX0_ANARXCONTROLPCI_RX_POLARITY_R_MASK;
    370         data16 = mask16;
    371         if (rxpol == 1) {
    372             SOC_IF_ERROR_RETURN
    373                 (MODIFY_HL65_RXB_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    374         }
    375         if ((rxpol & 0x000F) == 0x000F) {
    376             SOC_IF_ERROR_RETURN
    377                 (MODIFY_HL65_RX0_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    378         }
    379         if ((rxpol & 0x00F0) == 0x00F0) {
    380             SOC_IF_ERROR_RETURN
    381                 (MODIFY_HL65_RX1_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    382         }
    383         if ((rxpol & 0x0F00) == 0x0F00) {
    384             SOC_IF_ERROR_RETURN
    385                 (MODIFY_HL65_RX2_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    386         }
    387         if ((rxpol & 0xF000) == 0xF000) {
    388             SOC_IF_ERROR_RETURN
    389                 (MODIFY_HL65_RX3_ANARXCONTROLPCIr(unit,pc,data16,mask16));
    390         }
    391     }
    392     return SOC_E_NONE;
    393 }
    394 
    395 STATIC int
    396 _phy_hl65_independent_lane_init(int unit, soc_port_t port)
    397 {
    398     int                 fiber;
    399     uint16              data16, mask16;
    400     uint16              mode_1000x;
    401     int                 rv;
    402     soc_timeout_t       to;
    403     phy_ctrl_t         *pc;
    404     soc_port_ability_t  ability;
    405 
    406     if (SOC_IS_RELOADING(unit)) {
    407         return SOC_E_NONE;
    408     }
    409 
    410     /* Only need to track fiber mode state.
    411      * Copper mode state is tracked by external PHY.
    412      */
    413     pc                       = INT_PHY_SW_STATE(unit, port);
    414     fiber                    = PHY_FIBER_MODE(unit, port);
    415     pc->fiber.enable         = fiber;
    416     pc->fiber.preferred      = fiber;
    417     pc->fiber.autoneg_enable = 1;
    418     pc->fiber.force_speed    = 1000;
    419     pc->fiber.force_duplex   = TRUE;
    420     pc->fiber.master         = SOC_PORT_MS_NONE;
    421     pc->fiber.mdix           = SOC_PORT_MDIX_NORMAL;
    422 
    423     /* if the port is using two lanes and not using as dxgxs mode,
    424      * then disable the second lane
    425      */
    426     if ((pc->phy_mode == PHYCTRL_DUAL_LANE_PORT) && IS_GE_PORT(unit,port)) {
    427         int mdio_addr_share = FALSE;
    428 
    429         /* clear next lane default dxgxs configuration */
    430         if (!(pc->flags & PHYCTRL_MDIO_ADDR_SHARE)) {
    431             pc->phy_id++;
    432         } else {
    433             pc->lane_num++;
    434         }
    435         SOC_IF_ERROR_RETURN
    436              (MODIFY_HL65_DIGITAL_MISC1r(unit, pc, 0, 0x1f));
    437 
    438         SOC_IF_ERROR_RETURN
    439              (MODIFY_HL65_DIGITAL4_MISC3r(unit, pc, 0,
    440                      DIGITAL4_MISC3_FORCE_SPEED_B5_MASK));
    441         if (!(pc->flags & PHYCTRL_MDIO_ADDR_SHARE)) {
    442             pc->phy_id--;
    443         } else {
    444             pc->lane_num--;
    445         }
    446 
    447         /* disable the next lane
    448          * the lane disable register can only be accessed from lane 0
    449          */
    450         if (pc->flags & PHYCTRL_MDIO_ADDR_SHARE) {
    451             mdio_addr_share = TRUE;
    452             pc->flags &= ~PHYCTRL_MDIO_ADDR_SHARE;
    453         } else {
    454             pc->phy_id -= pc->lane_num;
    455         }
    456 
    457         mask16 = (1 << (pc->lane_num + 1));    /* rx lane */
    458         mask16 |= (mask16 << 4); /* add tx lane */
    459         mask16 |= 0x800;         /* add force bit */
    460         data16 = mask16;
    461 
    462         SOC_IF_ERROR_RETURN
    463             (MODIFY_HL65_XGXSBLK1_LANECTRL3r(unit,pc,data16,mask16));
    464         
    465         /* restore the previous MDIO address mode */
    466         if (mdio_addr_share == TRUE) {
    467             pc->flags |= PHYCTRL_MDIO_ADDR_SHARE;
    468         } else {
    469             pc->phy_id += pc->lane_num;
    470         }
    471     }
    472 
    473     /* Since driver reset function vector does not reset
    474      * the SerDes, reset the SerDes in initialization first.
    475      * The internal SERDES PHY's reset bit is self-clearing.
    476      */
    477     SOC_IF_ERROR_RETURN
    478         (WRITE_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, MII_CTRL_RESET));
    479 
    480     soc_timeout_init(&to, 10000, 0);
    481     while (!soc_timeout_check(&to)) {
    482         rv = READ_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, &data16);
    483         if (((data16 & MII_CTRL_RESET) == 0) ||
    484             SOC_FAILURE(rv)) {
    485             break;
    486         }
    487     }
    488     if ((data16 & MII_CTRL_RESET) != 0) {
    489         LOG_WARN(BSL_LS_SOC_PHY,
    490                  (BSL_META_U(unit,
    491                              "Combo SerDes reset failed: u=%d p=%d\n"),
    492                   unit, port));
    493     }
    494 
    495     /* disable in-band MDIO. PHY-443 */
    496     SOC_IF_ERROR_RETURN
    497         (MODIFY_HL65_XGXSBLK3_LOCALCONTROL0r(unit,pc,
    498                 XGXSBLK3_LOCALCONTROL0_RX_INBANDMDIO_RST_MASK,
    499                 XGXSBLK3_LOCALCONTROL0_RX_INBANDMDIO_RST_MASK));
    500 
    501     /* check if need to flip any polarity for the lane */
    502     SOC_IF_ERROR_RETURN
    503         (_hl65_ind_lane_polarity_set (unit, port));
    504 
    505     /* Select recovered clock from MII fifo read */
    506     if (IS_GE_PORT(unit, port) && (fiber == 0)) {
    507         mask16 = DIGITAL4_MISC3_RXCK_MII_OVERRIDE_VAL_MASK |
    508                  DIGITAL4_MISC3_RXCK_MII_OVERRIDE_MASK;
    509         data16 = mask16;
    510         SOC_IF_ERROR_RETURN
    511             (MODIFY_HL65_DIGITAL4_MISC3r(unit, pc, data16, mask16));
    512     }
    513 
    514     /* Enable output clock to be present when the core is commanded into
    515      * power down state.
    516      */
    517     data16 = XGXSBLK1_LANETEST_PWRDWN_CLKS_EN_MASK;
    518     SOC_IF_ERROR_RETURN
    519         (WRITE_HL65_XGXSBLK1_LANETESTr(unit, pc, data16)); 
    520 
    521     /* Set Local Advertising Configuration */
    522     SOC_IF_ERROR_RETURN
    523         (phy_hl65_ability_local_get(unit, port, &ability)); 
    524     /* Do not advertise 2.5G. 2.5 Gbps AN is not supported */
    525     ability.speed_full_duplex &= ~SOC_PA_SPEED_2500MB;
    526 
    527     pc->fiber.advert_ability = ability;
    528     SOC_IF_ERROR_RETURN
    529         (phy_hl65_ability_advert_set(unit, port, &ability));
    530 
    531     /* Disable BAM in Independent Lance mode. Over1G AN not supported  */
    532     SOC_IF_ERROR_RETURN
    533         (WRITE_HL65_DIGITAL6_MP5_NEXTPAGECTRLr(unit, pc, 0));
    534     SOC_IF_ERROR_RETURN
    535         (WRITE_HL65_DIGITAL6_UD_FIELDr(unit, pc, 0));
    536 
    537     data16 = DIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_MASK |
    538              DIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_MASK;
    539     mask16 = data16 | DIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK;
    540 
    541     if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) ||
    542         PHY_PASSTHRU_MODE(unit, port) ||
    543         PHY_SGMII_AUTONEG_MODE(unit, port)) {
    544         /* Enable 1000X parallel detect */
    545         data16 |= DIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK;
    546     }
    547     
    548     SOC_IF_ERROR_RETURN
    549         (MODIFY_HL65_DIGITAL_CONTROL1000X2r(unit, pc, data16, mask16));
    550 
    551     /* Initialialize autoneg and fullduplex */
    552     data16 = MII_CTRL_FD | MII_CTRL_SS_1000;
    553     if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) ||
    554         PHY_PASSTHRU_MODE(unit, port) ||
    555         PHY_SGMII_AUTONEG_MODE(unit, port)) {
    556         data16 |= MII_CTRL_AE | MII_CTRL_RAN;
    557     }
    558     SOC_IF_ERROR_RETURN
    559         (WRITE_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, data16));
    560 
    561     /* Configure default preemphasis, predriver, idriver values */
    562     SOC_IF_ERROR_RETURN
    563         (_phy_hl65_tx_control_set(unit, port));
    564 
    565     /* Configuring operating mode */
    566     data16 = DIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK;
    567     mask16 = DIGITAL_CONTROL1000X1_AUTODET_EN_MASK |
    568              DIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK |
    569              DIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK;
    570     /*
    571      * Configure signal auto-detection between SGMII and fiber.
    572      * This detection only works if auto-negotiation is enabled.
    573      */
    574     if (soc_property_port_get(unit, port,
    575                               spn_SERDES_AUTOMEDIUM, FALSE)) {
    576         data16 |= DIGITAL_CONTROL1000X1_AUTODET_EN_MASK;
    577     }
    578 
    579     /*
    580      * Put the Serdes in Fiber or SGMII mode
    581      */
    582     mode_1000x = 0;
    583     if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) ||
    584         PHY_PASSTHRU_MODE(unit, port)) {
    585         mode_1000x = DIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
    586     }
    587     /* Allow property to override */
    588     if (soc_property_port_get(unit, port,
    589                               spn_SERDES_FIBER_PREF, mode_1000x)) {
    590         data16 |= DIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
    591     } else {
    592         data16 &= ~DIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
    593     }
    594     if (soc_property_port_get(unit, port, 
    595                               spn_SERDES_SGMII_MASTER, FALSE)) {
    596         data16 |= DIGITAL_CONTROL1000X1_SGMII_MASTER_MODE_MASK;
    597         mask16 |= DIGITAL_CONTROL1000X1_SGMII_MASTER_MODE_MASK;
    598     }
    599 
    600     SOC_IF_ERROR_RETURN
    601         (MODIFY_HL65_DIGITAL_CONTROL1000X1r(unit, pc, data16, mask16));
    602 
    603     SOC_IF_ERROR_RETURN
    604         (_hl65_lane_reg_init(unit,pc));
    605 
    606     SOC_IF_ERROR_RETURN
    607         (_phy_hl65_analog_dsc_init(unit,port,pc->lane_num));
    608 
    609     /* config the 64B/66B for dxgxs mode */
    610     SOC_IF_ERROR_RETURN
    611         (_hl65_xgmii_scw_config (unit,pc));
    612 
    613     /* autoneg is not supported in dxgxs mode */
    614     if ((pc->phy_mode == PHYCTRL_DUAL_LANE_PORT) && 
    615         (IS_HG_PORT(unit,port) || IS_XE_PORT(unit,port))) {
    616         SOC_IF_ERROR_RETURN
    617             (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, 0, MII_CTRL_AE));
    618         SOC_IF_ERROR_RETURN
    619              (MODIFY_HL65_DIGITAL_MISC1r(unit, pc, 0x1, 0x1f));
    620 
    621          SOC_IF_ERROR_RETURN
    622              (MODIFY_HL65_DIGITAL4_MISC3r(unit, pc, DIGITAL4_MISC3_FORCE_SPEED_B5_MASK,
    623                      DIGITAL4_MISC3_FORCE_SPEED_B5_MASK));
    624     } else { /* all other modes, enable autoneg by default */
    625         /* clear forced speed control. Some two-lane ports are strapped
    626          * in forced dxgxs speed.
    627          */ 
    628         SOC_IF_ERROR_RETURN
    629             (MODIFY_HL65_DIGITAL_MISC1r(unit, pc, 0, 
    630                                DIGITAL_MISC1_FORCE_SPEED_MASK));
    631         SOC_IF_ERROR_RETURN
    632             (MODIFY_HL65_DIGITAL4_MISC3r(unit, pc, 0,
    633                     DIGITAL4_MISC3_FORCE_SPEED_B5_MASK));
    634 
    635         /* enable autoneg */
    636         SOC_IF_ERROR_RETURN
    637             (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, MII_CTRL_AE, 
    638                           MII_CTRL_AE));
    639     }
    640     /* PRBS Polynomial for all lanes: 0x8019=0x0000 */
    641 	
    642     SOC_IF_ERROR_RETURN
    643         (WRITE_HL65_XGXSBLK1_LANEPRBSr(unit, pc, 0)); 
    644 
    645      LOG_INFO(BSL_LS_SOC_PHY,
    646               (BSL_META_U(unit,
    647                           "phy_hl65_init: u=%d p=%d %s\n"),
    648                unit, port, (fiber) ? "Fiber" : "Copper"));
    649     return SOC_E_NONE;
    650 }
    651 
    652 STATIC int
    653 _phy_hl65_combo_core_init(int unit, soc_port_t port)
    654 {
    655     phy_ctrl_t        *pc;
    656     soc_port_ability_t ability;
    657     uint16             data16, mask16;
    658 
    659     pc = INT_PHY_SW_STATE(unit, port);
    660 
    661     /* must be done after reset, otherwise will be cleared  */
    662     data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_ComboCoreMode <<
    663                         XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT);
    664     SOC_IF_ERROR_RETURN
    665             (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc,data16,
    666                                        (XGXSBLK0_XGXSCONTROL_MODE_10G_MASK)));
    667 
    668     /* disable in-band MDIO. PHY-443 */
    669     SOC_IF_ERROR_RETURN
    670         (MODIFY_HL65_XGXSBLK3_LOCALCONTROL0r(unit,pc,
    671                 XGXSBLK3_LOCALCONTROL0_RX_INBANDMDIO_RST_MASK,
    672                 XGXSBLK3_LOCALCONTROL0_RX_INBANDMDIO_RST_MASK));
    673 
    674     /* check if need to flip any polarity for the lanes */
    675     SOC_IF_ERROR_RETURN
    676         (_hl65_combo_lane_polarity_set (unit, port));
    677 
    678     /* disable CL73 BAM */
    679     SOC_IF_ERROR_RETURN
    680         (HL65_REG_MODIFY(unit,pc,0,0x38008372,
    681                0,
    682                CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK));
    683                                                                                 
    684     if (!PHY_CLAUSE73_MODE(unit, port)) {
    685         /* disable CL73 AN device*/
    686         SOC_IF_ERROR_RETURN
    687             (WRITE_HL65_AN_IEEE0BLK_AN_IEEECONTROL1r(unit,pc,0));
    688     }
    689 
    690     /* PLL VCO step time */
    691     SOC_IF_ERROR_RETURN
    692         (WRITE_HL65_TXPLL_ANAPLLTIMER1r(unit, pc, 0x04ff));
    693 
    694     /* Disable IEEE block select auto-detect. 
    695      * The driver will select desired block as necessary.
    696      * By default, the driver keeps the mapping for XAUI block in
    697      * IEEE address space.
    698      */
    699     SOC_IF_ERROR_RETURN
    700         (MODIFY_HL65_XGXSBLK0_MISCCONTROL1r(unit, pc, 
    701                            XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK,
    702                            XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK |
    703                            XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK));
    704 
    705     SOC_IF_ERROR_RETURN
    706         (phy_hl65_ability_local_get(unit, port, &ability));
    707     if (PHY_EXTERNAL_MODE(unit, port)) {
    708             ability.speed_full_duplex = SOC_PA_SPEED_10GB;
    709     }
    710     SOC_IF_ERROR_RETURN
    711         (phy_hl65_ability_advert_set(unit, port, &ability));
    712 
    713     /* Configure 10G parallel detect */
    714     SOC_IF_ERROR_RETURN    /* Adjust parallel detect link timer to 60ms */
    715         (WRITE_HL65_AN73_PDET_PARDET10GLINKr(unit, pc, 0x16E2));
    716 
    717     data16 = 0;
    718     mask16 = AN73_PDET_PARDET10GCONTROL_PD_12G_TXDON_DISABLE_MASK |
    719              AN73_PDET_PARDET10GCONTROL_PD_12G_DISABLE_MASK |
    720              AN73_PDET_PARDET10GCONTROL_PARDET10G_EN_MASK;
    721     if (soc_property_port_get(unit, port, spn_XGXS_PDETECT_10G, 1)) {
    722         data16 |= AN73_PDET_PARDET10GCONTROL_PARDET10G_EN_MASK;
    723         if (pc->speed_max <= 10000) {
    724             /* Disable parallel detect for 12Gbps. */
    725             data16 |= AN73_PDET_PARDET10GCONTROL_PD_12G_TXDON_DISABLE_MASK |
    726                       AN73_PDET_PARDET10GCONTROL_PD_12G_DISABLE_MASK;
    727         }
    728     }
    729     SOC_IF_ERROR_RETURN
    730         (MODIFY_HL65_AN73_PDET_PARDET10GCONTROLr(unit, pc, data16, mask16));
    731 
    732     /* Configure default preemphasis, predriver, idriver values */
    733     SOC_IF_ERROR_RETURN
    734         (_phy_hl65_tx_control_set(unit, port));
    735 
    736     /* Enable output clock to be present when the core is commanded into
    737      * power down state. 
    738      */
    739     data16 = XGXSBLK1_LANETEST_PWRDWN_CLKS_EN_MASK |
    740              XGXSBLK1_LANETEST_PWRDN_SAFE_DIS_MASK;
    741     SOC_IF_ERROR_RETURN
    742         (WRITE_HL65_XGXSBLK1_LANETESTr(unit, pc, data16)); 
    743 
    744     /*
    745      * Transform CX4 pin out on the board to HG pinout
    746      */
    747     if (soc_property_port_get(unit, port, spn_CX4_TO_HIGIG, FALSE)) {
    748         SOC_IF_ERROR_RETURN     /* Enable TX Lane swap */
    749             (WRITE_HL65_XGXSBLK2_TXLNSWAPr(unit, pc, 0x80e4));
    750 
    751         SOC_IF_ERROR_RETURN     /* Flip TX Lane polarity */
    752             (WRITE_HL65_TXB_ANATXACONTROL0r(unit, pc, 0x1020));
    753     } else {
    754         /* If CX4 to HG conversion is enabled, do not allow individual lane
    755          * swapping.
    756          */
    757         uint16 lane_map, i;
    758         uint16 lane, hw_map, chk_map;
    759 
    760         /* Update RX lane map */
    761         lane_map = soc_property_port_get(unit, port,
    762                                         spn_XGXS_RX_LANE_MAP, 0x0123) & 0xffff;
    763         if (lane_map != 0x0123) {
    764             hw_map  = 0;
    765             chk_map = 0;
    766             for (i = 0; i < 4; i++) {
    767                 lane     = (lane_map >> (i * 4)) & 0xf;
    768                 hw_map  |= lane << (i * 2);
    769                 chk_map |= 1 << lane;
    770             }
    771             if (chk_map == 0xf) {
    772                 SOC_IF_ERROR_RETURN     /* Enable RX Lane swap */
    773                    (MODIFY_HL65_XGXSBLK2_RXLNSWAPr(unit, pc,
    774                        XGXSBLK2_RXLNSWAP_RX_LNSWAP_EN_MASK |
    775                        XGXSBLK2_RXLNSWAP_RX_LNSWAP_FORCE_EN_MASK | hw_map,
    776                        XGXSBLK2_RXLNSWAP_RX_LNSWAP_FORCE_EN_MASK |
    777                        XGXSBLK2_RXLNSWAP_RX_LNSWAP_EN_MASK |
    778                        XGXSBLK2_RXLNSWAP_RX_LNSWAP_FORCE0_MASK |
    779                        XGXSBLK2_RXLNSWAP_RX_LNSWAP_FORCE1_MASK |
    780                        XGXSBLK2_RXLNSWAP_RX_LNSWAP_FORCE2_MASK |
    781                        XGXSBLK2_RXLNSWAP_RX_LNSWAP_FORCE3_MASK));
    782             } else {
    783                 LOG_ERROR(BSL_LS_SOC_PHY,
    784                           (BSL_META_U(unit,
    785                                       "unit %d port %s: Invalid RX lane map 0x%04x.\n"),
    786                            unit, SOC_PORT_NAME(unit, port), lane_map));
    787             }
    788         }
    789 
    790         /* Update TX lane map */
    791         lane_map = soc_property_port_get(unit, port,
    792                                         spn_XGXS_TX_LANE_MAP, 0x0123) & 0xffff;
    793         if (lane_map != 0x0123) {
    794             hw_map  = 0;
    795             chk_map = 0;
    796             for (i = 0; i < 4; i++) {
    797                 lane     = (lane_map >> (i * 4)) & 0xf;
    798                 hw_map  |= lane << (i * 2);
    799                 chk_map |= 1 << lane;
    800             }
    801             if (chk_map == 0xf) {
    802                 SOC_IF_ERROR_RETURN     /* Enable TX Lane swap */
    803                    (MODIFY_HL65_XGXSBLK2_TXLNSWAPr(unit, pc, 0x8000 | hw_map,
    804                                                    0x80ff));
    805             } else {
    806                 LOG_ERROR(BSL_LS_SOC_PHY,
    807                           (BSL_META_U(unit,
    808                                       "unit %d port %s: Invalid TX lane map 0x%04x.\n"),
    809                            unit, SOC_PORT_NAME(unit, port), lane_map));
    810             }
    811         }
    812     }
    813 
    814     SOC_IF_ERROR_RETURN
    815          (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, 0,
    816                               XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK));
    817 
    818     SOC_IF_ERROR_RETURN
    819         (_phy_hl65_analog_dsc_init(unit,port,HL_ALL_LANES));
    820 
    821     /* config the 64B/66B for 25G, won't affect other speeds and AN  */
    822     SOC_IF_ERROR_RETURN
    823         (_hl65_xgmii_scw_config (unit,pc));
    824 
    825     /* broadcast to all lanes */
    826     SOC_IF_ERROR_RETURN
    827         (WRITE_HL65_AERBLK_AERr(unit,pc, HL_AER_BCST_OFS_STRAP));
    828 
    829     SOC_IF_ERROR_RETURN
    830         (_hl65_lane_reg_init(unit,pc));
    831 
    832     /* reset AER */
    833     SOC_IF_ERROR_RETURN
    834         (WRITE_HL65_AERBLK_AERr(unit,pc, 0));
    835     
    836     /* enable autoneg or force a speed depending on the port type */
    837     
    838     if (PHY_EXTERNAL_MODE(unit, port) &&
    839         (IS_XE_PORT(unit, port) || IS_HG_PORT(unit, port))) {
    840         int force_speed;
    841 
    842         if (soc_property_port_get(unit, port, spn_10G_IS_CX4, TRUE)) {
    843             force_speed= DIGITAL_MISC1_FORCE_SPEED_dr_10GBASE_CX4; /* 10G CX4 */
    844         } else {
    845             force_speed= DIGITAL_MISC1_FORCE_SPEED_dr_10GHiGig_X4; /* 10G HiG */
    846         }
    847 
    848         /* disable autoneg */
    849         SOC_IF_ERROR_RETURN
    850             (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc,
    851                                              0,
    852                                              MII_CTRL_AE));
    853         if (PHY_CLAUSE73_MODE(unit, port)) {
    854             SOC_IF_ERROR_RETURN
    855                 (MODIFY_HL65_AN_IEEE0BLK_AN_IEEECONTROL1r(unit, pc,
    856                                               0,
    857                                               MII_CTRL_AE));
    858         }
    859 
    860         /* force speed  to 10G */
    861         SOC_IF_ERROR_RETURN
    862             (MODIFY_HL65_DIGITAL_MISC1r(unit, pc, force_speed,
    863                                 DIGITAL_MISC1_FORCE_SPEED_MASK));
    864     } else { /* autoneg */
    865         /* clear forced bit */
    866         SOC_IF_ERROR_RETURN
    867             (MODIFY_HL65_DIGITAL_MISC1r(unit, pc, 0, 0x10));
    868 
    869         SOC_IF_ERROR_RETURN
    870             (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc,
    871                                              MII_CTRL_AE | MII_CTRL_RAN,
    872                                              MII_CTRL_AE | MII_CTRL_RAN));
    873         if (PHY_CLAUSE73_MODE(unit, port)) {
    874             SOC_IF_ERROR_RETURN
    875                 (MODIFY_HL65_AN_IEEE0BLK_AN_IEEECONTROL1r(unit, pc,
    876                                               MII_CTRL_AE | MII_CTRL_RAN,
    877                                               MII_CTRL_AE | MII_CTRL_RAN));
    878         }
    879     }
    880 
    881     SOC_IF_ERROR_RETURN
    882          (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc,
    883                              XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK,
    884                              XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK));
    885 
    886     /*
    887      * Configure signal auto-detection between SGMII and fiber.
    888      */
    889     data16 = DIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK;
    890     mask16 = DIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK |
    891              DIGITAL_CONTROL1000X1_AUTODET_EN_MASK |
    892              DIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
    893     if (soc_property_port_get(unit, port, spn_SERDES_AUTOMEDIUM, TRUE)) {
    894         data16 |= DIGITAL_CONTROL1000X1_AUTODET_EN_MASK;
    895     }
    896     if (soc_property_port_get(unit, port, spn_SERDES_FIBER_PREF, TRUE)) {
    897         data16 |= DIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
    898     }
    899     SOC_IF_ERROR_RETURN
    900         (MODIFY_HL65_DIGITAL_CONTROL1000X1r(unit, pc, data16, mask16));
    901 
    902     /* set filter_force_link and disable_false_link */
    903 
    904     mask16 = DIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_MASK |
    905              DIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_MASK;
    906     data16 = mask16;
    907     SOC_IF_ERROR_RETURN
    908         (MODIFY_HL65_DIGITAL_CONTROL1000X2r(unit, pc, data16, mask16));
    909 
    910     (void) _phy_hl65_pll_lock_wait(unit, port);
    911 
    912     /* select recovery clock from lane0 for rxck0_10g */
    913     SOC_IF_ERROR_RETURN
    914          (MODIFY_HL65_XGXSBLK1_TESTTXr(unit,pc,
    915                  0,
    916                  XGXSBLK1_TESTTX_RX_CK4X1MUXSEL_MASK));
    917     return SOC_E_NONE;
    918 }
    919 
    920 
    921 STATIC int
    922 _phy_hl65_fabric_init(int unit, soc_port_t port)
    923 {
    924     uint16      data;
    925     uint16      serdes_id0;
    926     uint16      aer_bcst_ofs_strap;
    927     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
    928 
    929     LOG_INFO(BSL_LS_SOC_PHY,
    930              (BSL_META_U(unit,
    931                          "phy_hl65_fabric_init: u=%d p=%d\n"), unit, port));
    932     SOC_IF_ERROR_RETURN
    933         (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
    934 
    935     serdes_id0 = serdes_id0 & (TEST_SERDESID0_REV_NUMBER_MASK |
    936                             TEST_SERDESID0_REV_LETTER_MASK);
    937 
    938     if (serdes_id0 == HL_SERDES_ID0_REVID_C0) {
    939         aer_bcst_ofs_strap = 0x1ff;
    940     } else {
    941         aer_bcst_ofs_strap = 0x3ff;
    942     }
    943         
    944     PHY_FLAGS_SET(unit, port, PHY_FLAGS_INDEPENDENT_LANE);
    945 
    946     /* Broadcast all lanes only when initializing the first lane */
    947     if (pc->lane_num == 0) {
    948         /* 
    949          * Force the sync character to the lower byte of the parallel 
    950          * interface 
    951          */
    952         /* hwBm9600HcBroadcastWrite(pInitParams, HC_ffde_ADDR, 0x03ff) */
    953         /* hwBm9600HcRead(pInitParams, HC_PORT_ZERO, HC_80b9_ADDR, &uReadData)*/
    954         SOC_IF_ERROR_RETURN
    955             (HL65_REG_READ(unit, pc, 0x00, 0x80b9, &data));
    956         
    957         /* data = data | 0x0020;*/
    958         data = data | (RX0_ANARXCONTROL1G_COMMA_LOW_BYTE_SM_BITS <<
    959                        RX0_ANARXCONTROL1G_COMMA_LOW_BYTE_SM_SHIFT);
    960 
    961 	/* Enable the comma byte adjust on the opposite byte */
    962         data = data | (RX0_ANARXCONTROL1G_COMMA_BYTE_ADJ_EN_SM_BITS <<
    963                        RX0_ANARXCONTROL1G_COMMA_BYTE_ADJ_EN_SM_SHIFT);
    964 
    965 
    966         /* hwBm9600HcBroadcastWrite(pInitParams, HC_80b9_ADDR, uReadData) */
    967         SOC_IF_ERROR_RETURN
    968             (HL65_BROADCAST_WRITE(unit, pc, aer_bcst_ofs_strap,  0x80b9, data));
    969     }
    970 
    971     /* PLL Sequencer disable */
    972     /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, 
    973      *  0x8000, 0x062f)
    974      *  >> Clear START_SEQUENCER_BITS 13
    975      */
    976     SOC_IF_ERROR_RETURN
    977         (WRITE_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, 0x062f));
    978 
    979     /* Set force_lane_mode so that lane rates can be configured independently */
    980     /* soc_bm9600_mdio_hc_read(pInitParams->m_nBaseAddr, uPhyAddr, uLane, 
    981      *  0x8308, &uData)
    982      */
    983     SOC_IF_ERROR_RETURN
    984         (READ_HL65_DIGITAL_MISC1r(unit, pc, &data));
    985 
    986     /* uData |= 0x0020 */ 
    987     data |=  (DIGITAL_MISC1_FORCE_LN_MODE_BITS <<  DIGITAL_MISC1_FORCE_LN_MODE_SHIFT);
    988 	
    989     /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, uLane, 0x8308, uData) */
    990     SOC_IF_ERROR_RETURN
    991         (WRITE_HL65_DIGITAL_MISC1r(unit, pc, data));
    992 
    993     if (serdes_id0 == HL_SERDES_ID0_REVID_C0) {
    994       
    995 	SOC_IF_ERROR_RETURN
    996 	    (READ_HL65_XGXSBLK1_LANECTRL0r(unit, pc, &data));
    997 
    998         /* XgxsBlk1 Lanectrl0 (8015) :: Clear CL36- keep already set up 64/66 settings  */
    999         data &= 0xff00;
   1000 
   1001         SOC_IF_ERROR_RETURN
   1002             (WRITE_HL65_XGXSBLK1_LANECTRL0r(unit, pc, data));
   1003 
   1004         /*
   1005          *  XgxsBlk1 Shared (0x800d) ::
   1006          *    Clear SELECT_DEVPMD_EN_BITS | MMDSELECT_DEVAN_EN_BITS
   1007          *  This setup matches other SBX fabric (88130)
   1008          */
   1009         data = (XGXSBLK0_MMDSELECT_DEVDEVAD_EN_BITS <<  
   1010                 XGXSBLK0_MMDSELECT_DEVDEVAD_EN_SHIFT) |
   1011                (XGXSBLK0_MMDSELECT_DEVCL22_EN_BITS <<
   1012                 XGXSBLK0_MMDSELECT_DEVCL22_EN_SHIFT);
   1013         SOC_IF_ERROR_RETURN
   1014             (WRITE_HL65_XGXSBLK0_MMDSELECTr(unit, pc, data));
   1015  
   1016         /* SerdesDigital_Control1000X3 (0x8302) */
   1017         SOC_IF_ERROR_RETURN
   1018             (WRITE_HL65_DIGITAL_CONTROL1000X3r(unit, pc, 0));
   1019 
   1020         /* Set pf_br_init to 4 for C0 */
   1021         /* DSC2B0_SM_CTRL7    uRegAddr = 0x8267 + (uLane*0x10) */
   1022         SOC_IF_ERROR_RETURN
   1023             (HL65_REG_WRITE(unit, pc, 0x0, 0x8267 + (0x10 * pc->lane_num), 0x14A5));
   1024 
   1025 
   1026         /* Enable hysteresis, enable tuning state machine set postc_metric_ctrl to 1 */
   1027         /* DSC2B0_SM_CTRL0     uRegAddr = 0x8260 + (uLane*0x10) */
   1028         /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, uRegAddr, 0x0021) */
   1029         SOC_IF_ERROR_RETURN
   1030             (HL65_REG_WRITE(unit, pc, 0x0, 0x8260 + (0x10 * pc->lane_num), 0x1821));
   1031 
   1032     } else {
   1033 
   1034         /* Perform suggested writes during init */
   1035         /* Set DSC2B0_SM_CTRL11[14:10] msr_br_vga_timeout = 0 */
   1036         /* uRegAddr = 0x826b + (uLane*0x10) */
   1037         /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, uRegAddr, 0x0312) */
   1038         SOC_IF_ERROR_RETURN
   1039             (HL65_REG_WRITE(unit, pc, 0x0, 0x826b + (0x10 * pc->lane_num), 0x0312));
   1040         
   1041         /* Set DSC2B0_SM_CTRL12[13:12] br_vga_lms_gain= 0 */
   1042         /* uRegAddr = 0x826c + (uLane*0x10); */
   1043         /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, uRegAddr, 0x046a) */
   1044         SOC_IF_ERROR_RETURN
   1045             (HL65_REG_WRITE(unit, pc, 0x0, 0x826c + (0x10 * pc->lane_num), 0x046a));
   1046 	
   1047         /* Disable hysteresis, enable tuning state machine  */
   1048         /* DSC2B0_SM_CTRL0     uRegAddr = 0x8260 + (uLane*0x10) */
   1049         /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, uRegAddr, 0x0021) */
   1050         SOC_IF_ERROR_RETURN
   1051             (HL65_REG_WRITE(unit, pc, 0x0, 0x8260 + (0x10 * pc->lane_num), 0x0021));
   1052     	
   1053         /* Increase ACQVGA timeout to 580K bits */
   1054         /* DSC2B0_SM_CTRL2    uRegAddr = 0x8262 + (uLane*0x10) */
   1055         /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, uRegAddr, 0x3800)*/
   1056         SOC_IF_ERROR_RETURN
   1057             (HL65_REG_WRITE(unit, pc, 0x0, 0x8262 + (0x10 * pc->lane_num), 0x3800));
   1058     	
   1059         /* Set pf_br_init to 2 */
   1060         /* DSC2B0_SM_CTRL7    uRegAddr = 0x8267 + (uLane*0x10) */
   1061         /*  rv = soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, uRegAddr, 0x1495) */
   1062         SOC_IF_ERROR_RETURN
   1063             (HL65_REG_WRITE(unit, pc, 0x0, 0x8267 + (0x10 * pc->lane_num), 0x1495));
   1064 	
   1065         
   1066         /* Set vga_min=0, vga_max=31 */
   1067         /* DSC2B0_SM_CTRL8    uRegAddr = 0x8268 + (uLane*0x10) */
   1068         /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, uRegAddr, 0x03e0) */
   1069         SOC_IF_ERROR_RETURN
   1070             (HL65_REG_WRITE(unit, pc, 0x0, 0x8268 + (0x10 * pc->lane_num), 0x03e0));
   1071         
   1072         /* Set dfe_min=0, dfe_max=63 */
   1073         /* DSC2B0_SM_CTRL9    uRegAddr = 0x8269 + (uLane*0x10) */
   1074         /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, uRegAddr, 0x0fc0) */
   1075         SOC_IF_ERROR_RETURN
   1076             (HL65_REG_WRITE(unit, pc, 0x0, 0x8269 + (0x10 * pc->lane_num), 0x0fc0));
   1077         
   1078         /* Set BR ACQCDR kp=4 */
   1079         /* DSC2B0_SM_CTRL3     uRegAddr = 0x8263 + (uLane*0x10) */
   1080         /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, uRegAddr, 0x421b) */
   1081         SOC_IF_ERROR_RETURN
   1082             (HL65_REG_WRITE(unit, pc, 0x0, 0x8263 + (0x10 * pc->lane_num), 0x421b));
   1083         
   1084         /* Set BR ACQ1, ACQ2 kp=4 */
   1085         /* DSC2B0_SM_CTRL4     uRegAddr = 0x8264 + (uLane*0x10) */
   1086         /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, uRegAddr, 0x53e4) */
   1087         SOC_IF_ERROR_RETURN
   1088             (HL65_REG_WRITE(unit, pc, 0x0, 0x8264 + (0x10 * pc->lane_num), 0x53e4));
   1089         
   1090         /* Jitter performance improvement over PVT (process voltage temperature) */
   1091         /* soc_bm9600_mdio_hc_read(pInitParams->m_nBaseAddr, uPhyAddr, 0, 0x805e, &uData) */
   1092         SOC_IF_ERROR_RETURN
   1093             (READ_HL65_TXPLL_ANAPLLACONTROL4r(unit, pc, &data));
   1094         
   1095         /* uData |= 0x1000 */
   1096         data |= 0x1000;
   1097         
   1098         /*soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, 0x805e, uData) */
   1099         SOC_IF_ERROR_RETURN
   1100             (WRITE_HL65_TXPLL_ANAPLLACONTROL4r(unit, pc, data));
   1101     }
   1102 
   1103         
   1104     /* Set IQP to 200 uA  0x805c */
   1105     SOC_IF_ERROR_RETURN
   1106       (READ_HL65_TXPLL_ANAPLLACONTROL2r(unit, pc, &data));
   1107     
   1108     /* uData |= 0x0004 */
   1109     data |= 0x0004;
   1110     
   1111     /*soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, 0x805c, uData) */
   1112     SOC_IF_ERROR_RETURN
   1113       (WRITE_HL65_TXPLL_ANAPLLACONTROL2r(unit, pc, data));
   1114 
   1115 
   1116     
   1117     /* PLL Sequencer enable */
   1118     /* soc_bm9600_mdio_hc_write(pInitParams->m_nBaseAddr, uPhyAddr, 0, 0x8000, 0x262f) */
   1119     SOC_IF_ERROR_RETURN
   1120         (WRITE_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, 0x262f));
   1121     
   1122     return SOC_E_NONE;
   1123 }
   1124 
   1125 /*
   1126  * Function:
   1127  *      phy_hl65_init
   1128  * Purpose:     
   1129  *      Initialize hc phys
   1130  * Parameters:
   1131  *      unit - StrataSwitch unit #.
   1132  *      port - StrataSwitch port #. 
   1133  * Returns:     
   1134  *      SOC_E_NONE
   1135  */
   1136 
   1137 STATIC int
   1138 phy_hl65_init(int unit, soc_port_t port)
   1139 {
   1140     phy_ctrl_t         *pc;               
   1141     uint16             xgxs_ctrl;
   1142     uint16             vco_freq;
   1143     int mode_1000x;
   1144     uint16 id_rev;
   1145 
   1146     if (PHY_HC65_FABRIC_MODE(unit, port)) {
   1147         return _phy_hl65_fabric_init(unit, port);
   1148     }
   1149 
   1150     pc = INT_PHY_SW_STATE(unit, port);
   1151 
   1152     if (!PHY_EXTERNAL_MODE(unit, port)) {
   1153          /* PHY reset callbacks */
   1154         SOC_IF_ERROR_RETURN(soc_phy_reset(unit, port));
   1155 
   1156         if (soc_property_port_get(unit, port,
   1157                                   spn_SERDES_FIBER_PREF, 1)) {
   1158             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   1159         } else {
   1160             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
   1161         }
   1162 
   1163 
   1164         if (soc_property_port_get(unit, port,
   1165                               spn_PHY_AN_C73, FALSE)) {
   1166             PHY_FLAGS_SET(unit, port, PHY_FLAGS_C73);
   1167         }
   1168     }
   1169 
   1170     if (PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   1171         /* In this mode, the device's 4 lanes connect to 4 different ports.
   1172          * It is necessary to configure and initialize the shared resource
   1173          * once before going to each lane. It is assumed the port connecting
   1174          * to lane 0 must be initialized first. 
   1175          */
   1176 
   1177         if ((!PHY_FLAGS_TST(unit, port, PHY_FLAGS_INIT_DONE)) && 
   1178             (pc->lane_num == 0)) {
   1179             /* configure and initialize the resource shared by all 4 lanes*/
   1180 
   1181             SOC_IF_ERROR_RETURN(_hl65_soft_reset(unit,pc)); /* reset once */
   1182                   
   1183             /* Force to asymetric 1G/2.5G independent lane mode.
   1184              * Support SGMII 10/100/100Mbps, 1000X, and 2500X speeds.
   1185              */
   1186             /* workaround for a Rx problem running at 10M bps(PR20236).
   1187              * Use mode 6 for speed at 10/100/1000M bps, SGMII interface
   1188              * Use mode 5 for speed at 1000/2500 bps, optical device.
   1189              *
   1190              * Rev B and up has fixed the problem. No need to switch mode
   1191              * between fiber and SGMII.
   1192              */
   1193 
   1194             SOC_IF_ERROR_RETURN
   1195                 (READ_HL65_TEST_SERDESID0r(unit,pc,&id_rev));
   1196             if (!(id_rev & TEST_SERDESID0_REV_LETTER_MASK)) {
   1197 
   1198                 mode_1000x = FALSE;
   1199                 if (PHY_FIBER_MODE(unit, port) && 
   1200                               (!PHY_EXTERNAL_MODE(unit, port))) {
   1201                     mode_1000x = TRUE;
   1202                 }
   1203 
   1204                 /* Allow property to override */
   1205                 mode_1000x = soc_property_port_get(unit, port,
   1206                                spn_SERDES_FIBER_PREF, mode_1000x);
   1207      
   1208                 if (mode_1000x) {
   1209                     xgxs_ctrl = 5;
   1210                 } else {       
   1211                     xgxs_ctrl = 6;
   1212                 }
   1213             } else {
   1214                 /* REV B and above, use mode 6 if speed =<1000 */
   1215                 if (pc->speed_max > 1000) {
   1216                     xgxs_ctrl = 5;
   1217                 } else {
   1218                     xgxs_ctrl = 6;
   1219                 }                   
   1220             }
   1221  
   1222             /* allow mode override by configuration */
   1223 
   1224             xgxs_ctrl = soc_property_port_get(unit, port, 
   1225                           spn_PHY_HL65_1LANE_MODE, xgxs_ctrl);
   1226             if (IS_HG_PORT(unit, port)) {
   1227                 vco_freq = 0x7800;
   1228             } else {
   1229                 vco_freq = xgxs_ctrl == 5? 0x7700:0x7500;
   1230             }
   1231             xgxs_ctrl <<= XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT;
   1232 
   1233             /* set device's mode and disable PLL sequencer */
   1234             SOC_IF_ERROR_RETURN
   1235                 (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, 
   1236                            xgxs_ctrl,
   1237                            XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK |
   1238                            XGXSBLK0_XGXSCONTROL_MODE_10G_MASK));
   1239 
   1240             /* broadcast to all lanes */ 
   1241             SOC_IF_ERROR_RETURN
   1242                 (WRITE_HL65_AERBLK_AERr(unit,pc, HL_AER_BCST_OFS_STRAP));
   1243 
   1244             /* configure VCO frequency */
   1245             SOC_IF_ERROR_RETURN
   1246                 (WRITE_HL65_DIGITAL_MISC1r(unit,pc,vco_freq));
   1247 
   1248             /* disable 10G parallel detect */
   1249             SOC_IF_ERROR_RETURN
   1250                 (MODIFY_HL65_AN73_PDET_PARDET10GCONTROLr(unit, pc,
   1251                       0,
   1252                       AN73_PDET_PARDET10GCONTROL_PARDET10G_EN_MASK));
   1253 
   1254             /* reset AER */
   1255             SOC_IF_ERROR_RETURN
   1256                 (WRITE_HL65_AERBLK_AERr(unit,pc, 0));
   1257 
   1258             /* enable PLL sequencer */
   1259             SOC_IF_ERROR_RETURN
   1260                 (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc,
   1261                              XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK,
   1262                              XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK));
   1263 
   1264             /* select recovery clock from lane0 for rxck0_10g */
   1265             SOC_IF_ERROR_RETURN
   1266                 (MODIFY_HL65_XGXSBLK1_TESTTXr(unit,pc,
   1267                        0,
   1268                        XGXSBLK1_TESTTX_RX_CK4X1MUXSEL_MASK));
   1269         }
   1270 
   1271         SOC_IF_ERROR_RETURN
   1272             (_phy_hl65_independent_lane_init(unit, port));
   1273     } else {
   1274         SOC_IF_ERROR_RETURN(_hl65_soft_reset(unit,pc)); /* soft reset */
   1275 
   1276         /* Force to comboCore mode.
   1277          * Support SGMII 10/100/1000Mbps, 1000X, 2500X, 10G, and 12G.
   1278          */
   1279         SOC_IF_ERROR_RETURN
   1280             (_phy_hl65_combo_core_init(unit, port));
   1281     }  
   1282 
   1283     LOG_INFO(BSL_LS_SOC_PHY,
   1284              (BSL_META_U(unit,
   1285                          "phy_hl65_init: u=%d p=%d\n"), unit, port));
   1286     return SOC_E_NONE;
   1287 }
   1288 
   1289 /*
   1290  *      phy_hl65_link_get
   1291  * Purpose:
   1292  *      Get layer2 connection status.
   1293  * Parameters:
   1294  *      unit - StrataSwitch unit #.
   1295  *      port - StrataSwitch port #. 
   1296  *      link - address of memory to store link up/down state.
   1297  * Returns:     
   1298  *      SOC_E_NONE
   1299  */
   1300 
   1301 STATIC int
   1302 phy_hl65_link_get(int unit, soc_port_t port, int *link)
   1303 {
   1304     uint16      mii_stat;
   1305     phy_ctrl_t *pc;
   1306  
   1307     if (PHY_DISABLED_MODE(unit, port)) {
   1308         *link = FALSE;
   1309         return SOC_E_NONE;
   1310     }
   1311 
   1312     pc = INT_PHY_SW_STATE(unit, port);
   1313 
   1314     *link = FALSE;
   1315     /* Check XAUI link first if XAUI mode */
   1316     if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   1317         SOC_IF_ERROR_RETURN
   1318             (READ_HL65_DTE_IEEE0BLK_DTE_IEEESTATUS1r(unit, pc, &mii_stat));
   1319         if (mii_stat & MII_STAT_LA) {
   1320             *link = TRUE;
   1321         }
   1322     }
   1323 
   1324     /* Check combo link only if no XAUI link */
   1325     if (*link == FALSE) {
   1326         SOC_IF_ERROR_RETURN
   1327             (READ_HL65_COMBO_IEEE0_MIISTATr(unit, pc, &mii_stat));
   1328         if (mii_stat & MII_STAT_LA) {
   1329             *link = TRUE;
   1330         } else if (PHY_INDEPENDENT_LANE_MODE(unit,port)) {
   1331             /* Check dxgxs link */
   1332             if ((pc->phy_mode == PHYCTRL_DUAL_LANE_PORT) && 
   1333                     (IS_HG_PORT(unit,port) || IS_XE_PORT(unit,port))) {
   1334                 SOC_IF_ERROR_RETURN
   1335                     (READ_HL65_DTE_IEEE0BLK_DTE_IEEESTATUS1r(unit, pc,
   1336                                                            &mii_stat));
   1337                 if (mii_stat & MII_STAT_LA) {
   1338                     *link = TRUE;
   1339                 }
   1340             }
   1341         }
   1342     }
   1343 
   1344     return (SOC_E_NONE);
   1345 }
   1346 
   1347 
   1348 /*
   1349  * Function:
   1350  *      phy_hl65_enable_set
   1351  * Purpose:
   1352  *      Enable/Disable phy 
   1353  * Parameters:
   1354  *      unit - StrataSwitch unit #.
   1355  *      port - StrataSwitch port #. 
   1356  *      enable - on/off state to set
   1357  * Returns:     
   1358  *      SOC_E_NONE
   1359  */
   1360 
   1361 STATIC int
   1362 phy_hl65_enable_set(int unit, soc_port_t port, int enable)
   1363 {
   1364     int         rv;
   1365     phy_ctrl_t *pc;
   1366 
   1367     pc = INT_PHY_SW_STATE(unit, port);
   1368 
   1369     rv = SOC_E_NONE;
   1370     if (PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   1371         if (enable) {
   1372             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
   1373             rv = _phy_hl65_notify_resume(unit, port, PHY_STOP_PHY_DIS);
   1374         } else {
   1375             PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
   1376             rv = _phy_hl65_notify_stop(unit, port, PHY_STOP_PHY_DIS);
   1377         }
   1378     } else {
   1379         if (enable) {
   1380             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
   1381             rv = MODIFY_HL65_XGXSBLK0_MISCCONTROL1r(unit, pc, 0,
   1382                              XGXSBLK0_MISCCONTROL1_GLOBAL_PMD_TX_DISABLE_MASK);
   1383           
   1384             /* enable Rx */
   1385             rv = MODIFY_HL65_DSC2BB_DSC_MISC_CTRL0r(unit, pc, 0,
   1386                              DSC2BB_DSC_MISC_CTRL0_RXSEQSTART_MASK);
   1387 
   1388         } else {
   1389             PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
   1390             rv = MODIFY_HL65_XGXSBLK0_MISCCONTROL1r(unit, pc,
   1391                              XGXSBLK0_MISCCONTROL1_GLOBAL_PMD_TX_DISABLE_MASK,
   1392                              XGXSBLK0_MISCCONTROL1_GLOBAL_PMD_TX_DISABLE_MASK);
   1393 
   1394             /* disable Rx */
   1395             rv = MODIFY_HL65_DSC2BB_DSC_MISC_CTRL0r(unit, pc, 
   1396                              DSC2BB_DSC_MISC_CTRL0_RXSEQSTART_MASK,
   1397                              DSC2BB_DSC_MISC_CTRL0_RXSEQSTART_MASK);
   1398         }
   1399     }
   1400     return rv;
   1401 }
   1402 
   1403 /*
   1404  * Function:
   1405  *      phy_hl65_enable_get
   1406  * Purpose:
   1407  *      Get Enable/Disable status
   1408  * Parameters:
   1409  *      unit - StrataSwitch unit #.
   1410  *      port - StrataSwitch port #. 
   1411  *      enable - address of where to store on/off state
   1412  * Returns:     
   1413  *      SOC_E_NONE
   1414  */
   1415 
   1416 STATIC int
   1417 phy_hl65_enable_get(int unit, soc_port_t port, int *enable)
   1418 {
   1419     *enable = !PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE);
   1420 
   1421     return SOC_E_NONE;
   1422 }
   1423 
   1424 STATIC int
   1425 _phy_hl65_dsp_cfg (int unit, phy_ctrl_t *pc, int speed)
   1426 {
   1427     uint16      serdes_id0;
   1428     uint16      brcdr;
   1429 
   1430     /* For speed at 20G, configure the device for BR CDR.  */
   1431     if (speed == 20000) {
   1432         SOC_IF_ERROR_RETURN
   1433             (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
   1434 
   1435         serdes_id0 = serdes_id0 & (TEST_SERDESID0_REV_NUMBER_MASK |
   1436                      TEST_SERDESID0_REV_LETTER_MASK);
   1437 
   1438         if ((serdes_id0 == HL_SERDES_ID0_REVID_A0) ||
   1439             (serdes_id0 == HL_SERDES_ID0_REVID_A1) ) {
   1440             brcdr = HL65_A0A1_DSC_DFE_BRCDR;
   1441         } else if ((serdes_id0 == HL_SERDES_ID0_REVID_B0) ||
   1442                    (serdes_id0 == HL_SERDES_ID0_REVID_C0) ) {
   1443             brcdr = HL65_B0C0_DSC_DFE_BRCDR;
   1444         } else {
   1445             LOG_WARN(BSL_LS_SOC_PHY,
   1446                      (BSL_META_U(unit,
   1447                                  "HL65 : BR-CDR setting may not be correct: u=%d p=%d\n"),                        unit, pc->port));
   1448             brcdr = HL65_B0C0_DSC_DFE_BRCDR;  /* assumed for future versions */
   1449         }
   1450 
   1451         /* enable DFE/BR CDR */
   1452 
   1453         SOC_IF_ERROR_RETURN
   1454             (WRITE_HL65_DSC2BB_DSC_MISC_CTRL0r(unit, pc, brcdr));
   1455     } else {
   1456         /* default value for CDR */
   1457         SOC_IF_ERROR_RETURN
   1458             (WRITE_HL65_DSC2BB_DSC_MISC_CTRL0r(unit, pc, 0x2000));
   1459     }
   1460     return SOC_E_NONE;
   1461 }
   1462 
   1463 /*
   1464  * Function:
   1465  *      phy_hl65_fabric_mode_speed_set
   1466  * Purpose:
   1467  *      Set PHY speed
   1468  * Parameters:
   1469  *      unit - SBX device unit #.
   1470  *      port - SBX device port #. 
   1471  *      speed - link speed in Mbps
   1472  * Returns:     
   1473  *      SOC_E_NONE
   1474  */
   1475 
   1476 STATIC int
   1477 phy_hl65_fabric_mode_speed_set(int unit, soc_port_t port, int speed)
   1478 {
   1479     phy_ctrl_t  *pc;
   1480     uint16 data;
   1481     int rv = SOC_E_NONE;
   1482     uint16 serdes_id0;
   1483 
   1484     if (SOC_IS_RELOADING(unit)) {
   1485         return SOC_E_NONE;
   1486     }
   1487 
   1488     pc = INT_PHY_SW_STATE(unit, port);
   1489 
   1490     SOC_IF_ERROR_RETURN
   1491         (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
   1492 
   1493     serdes_id0 = serdes_id0 & (TEST_SERDESID0_REV_NUMBER_MASK |
   1494                             TEST_SERDESID0_REV_LETTER_MASK);
   1495 
   1496     switch (speed) {
   1497 
   1498     case 3125:
   1499         /* Disable baud rate CDR  */
   1500         /* uRegAddr = 0x826e + (uLaneAddr*0x10)*/
   1501         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, uRegAddr, 0x2000) */
   1502         SOC_IF_ERROR_RETURN
   1503             (HL65_REG_WRITE(unit, pc, 0x0, 0x826E + (0x10 * pc->lane_num),
   1504                             DSC2B0_DSC_MISC_CTRL0_ENABLE_ACOR_PICW_BITS <<
   1505                             DSC2B0_DSC_MISC_CTRL0_ENABLE_ACOR_PICW_SHIFT));
   1506 
   1507 
   1508 
   1509         /* 6.25G rate half speed 0x603a */
   1510         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, 0x8308, 0x603A)*/
   1511         SOC_IF_ERROR_RETURN
   1512             (WRITE_HL65_DIGITAL_MISC1r(unit, pc, 0x603a));
   1513 
   1514         /* Set 6.25G speed through the backdoor method clock divisor is in shared lane register  */
   1515         /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, 0x8016, &uData) */
   1516         SOC_IF_ERROR_RETURN
   1517             (READ_HL65_XGXSBLK1_LANECTRL1r(unit, pc, &data));
   1518         
   1519         /* clear bits */
   1520         data &= ~(0x0303 << (pc->lane_num * 2));
   1521 	data |= (0x0202 << (pc->lane_num * 2));
   1522         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8016, uData) */
   1523         SOC_IF_ERROR_RETURN
   1524             (WRITE_HL65_XGXSBLK1_LANECTRL1r(unit, pc, data));
   1525 
   1526         /* Set half-rate indicator for equalization algorithm to work */
   1527         /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, 0x8065, &uData) */
   1528         SOC_IF_ERROR_RETURN
   1529             (READ_HL65_TX0_ANATXACONTROL1r(unit, pc, &data));
   1530 
   1531         /*  uData &= ~(BM9600_HYPERCORE_8065_TX_SEL_HALF_RATE_MASK << BM9600_HYPERCORE_8065_TX_SEL_HALF_RATE_SHIFT) */
   1532         /* uData |= (1 << BM9600_HYPERCORE_8065_TX_SEL_HALF_RATE_SHIFT) */
   1533         data &= ~(TX0_ANATXACONTROL1_TX_SEL_HALFRATE_BITS <<  
   1534                   TX0_ANATXACONTROL1_TX_SEL_HALFRATE_SHIFT);
   1535         data |= (TX0_ANATXACONTROL1_TX_SEL_HALFRATE_BITS <<  
   1536                  TX0_ANATXACONTROL1_TX_SEL_HALFRATE_SHIFT);
   1537 
   1538         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, 0x8065, uData) */
   1539         SOC_IF_ERROR_RETURN
   1540             (WRITE_HL65_TX0_ANATXACONTROL1r(unit, pc, data));
   1541    
   1542         break;
   1543     
   1544     case 6250:
   1545 
   1546         /* Force baud rate CDR */
   1547         /* uRegAddr = 0x826e + (uLaneAddr*0x10) */
   1548         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, uRegAddr, 0x2180) */
   1549         if ((serdes_id0 == HL_SERDES_ID0_REVID_A0) ||
   1550 	    (serdes_id0 == HL_SERDES_ID0_REVID_A1)) {
   1551 	    SOC_IF_ERROR_RETURN
   1552 	        (HL65_REG_WRITE(unit, pc, 0x0, 0x826E + (0x10 * pc->lane_num),
   1553 				0x2180));
   1554 	} else {
   1555 	    SOC_IF_ERROR_RETURN
   1556 	        (HL65_REG_WRITE(unit, pc, 0x0, 0x826E + (0x10 * pc->lane_num),
   1557 				0x2300));
   1558 	}
   1559   
   1560         /* 6.25G rate 156.25MHz then mult by 40 + independent lane mode setting */
   1561         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, 0x8308, 0x7720) */
   1562         SOC_IF_ERROR_RETURN
   1563             (WRITE_HL65_DIGITAL_MISC1r(unit, pc, 0x7720));
   1564 
   1565         /* Set 6.25G speed through the backdoor method clock divisor is in shared lane register  */
   1566         /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, 0x8016, &uData) */
   1567         SOC_IF_ERROR_RETURN
   1568             (READ_HL65_XGXSBLK1_LANECTRL1r(unit, pc, &data));
   1569         
   1570         /* DWSDR_div1 = 0x3 for receive and transmit */
   1571         /*  uData |= 0x0303 << (uLaneAddr * 2) */
   1572         data |= 0x0303 << (pc->lane_num * 2);	    
   1573 
   1574         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8016, uData) */
   1575         SOC_IF_ERROR_RETURN
   1576             (WRITE_HL65_XGXSBLK1_LANECTRL1r(unit, pc, data));
   1577 
   1578 
   1579         /* Clear half-rate indicator for equalization algorithm to work */
   1580         /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, 0x8065, &uData) */
   1581         SOC_IF_ERROR_RETURN
   1582             (READ_HL65_TX0_ANATXACONTROL1r(unit, pc, &data));
   1583 
   1584         /* uData &= ~(BM9600_HYPERCORE_8065_TX_SEL_HALF_RATE_MASK << BM9600_HYPERCORE_8065_TX_SEL_HALF_RATE_SHIFT) */
   1585         /* uData |= (0 << BM9600_HYPERCORE_8065_TX_SEL_HALF_RATE_SHIFT) */
   1586         data &= ~(TX0_ANATXACONTROL1_TX_SEL_HALFRATE_BITS <<  
   1587                   TX0_ANATXACONTROL1_TX_SEL_HALFRATE_SHIFT);
   1588 
   1589         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, 0x8065, uData) */	
   1590         SOC_IF_ERROR_RETURN
   1591             (WRITE_HL65_TX0_ANATXACONTROL1r(unit, pc, data));
   1592 
   1593         break;
   1594 
   1595 
   1596     case 6500:
   1597         /* Jitter performance improvement over PVT - kvh_force=1 */
   1598 
   1599         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x805e, 0x1877) */
   1600         SOC_IF_ERROR_RETURN
   1601             (WRITE_HL65_TXPLL_ANAPLLACONTROL4r(unit, pc, 0x1877));
   1602 
   1603     
   1604         /* Force baud rate CDR */
   1605         /* uRegAddr = 0x826e + (uLaneAddr*0x10) */
   1606         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, uRegAddr, 0x2180) */
   1607         if ((serdes_id0 == HL_SERDES_ID0_REVID_A0) ||
   1608 	    (serdes_id0 == HL_SERDES_ID0_REVID_A1)) {
   1609 	    SOC_IF_ERROR_RETURN
   1610 	        (HL65_REG_WRITE(unit, pc, 0x0, 0x826E + (0x10 * pc->lane_num),
   1611 				0x2180));
   1612 	} else {
   1613 	    SOC_IF_ERROR_RETURN
   1614 	        (HL65_REG_WRITE(unit, pc, 0x0, 0x826E + (0x10 * pc->lane_num),
   1615 				0x2300));
   1616 	}
   1617 
   1618         /* 6.5G independent lane mode setting */
   1619         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, 0x8308, 0x7820) */
   1620         SOC_IF_ERROR_RETURN
   1621             (WRITE_HL65_DIGITAL_MISC1r(unit, pc, 0x7820));
   1622 
   1623 
   1624         /* Set 6.5G speed through the backdoor method clock divisor is in shared lane register  */
   1625         /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, 0x8016, &uData) */
   1626         SOC_IF_ERROR_RETURN
   1627             (READ_HL65_XGXSBLK1_LANECTRL1r(unit, pc, &data));
   1628 
   1629         /* DWSDR_div1 = 0x3 for receive and transmit */
   1630         /* uData |= 0x0303 << (uLaneAddr * 2) */
   1631         data  |= 0x0303 << (pc->lane_num * 2);	    
   1632 
   1633         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8016, uData) */
   1634         SOC_IF_ERROR_RETURN
   1635             (WRITE_HL65_XGXSBLK1_LANECTRL1r(unit, pc, data));
   1636 
   1637 
   1638         /* Clear half-rate indicator for equalization algorithm to work */
   1639         /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, 0x8065, &uData) */
   1640         SOC_IF_ERROR_RETURN
   1641             (READ_HL65_TX0_ANATXACONTROL1r(unit, pc, &data));
   1642 
   1643         /* uData &= ~(BM9600_HYPERCORE_8065_TX_SEL_HALF_RATE_MASK << BM9600_HYPERCORE_8065_TX_SEL_HALF_RATE_SHIFT) */
   1644         /* uData |= (0 << BM9600_HYPERCORE_8065_TX_SEL_HALF_RATE_SHIFT) */
   1645         data &= ~(TX0_ANATXACONTROL1_TX_SEL_HALFRATE_BITS <<  
   1646                   TX0_ANATXACONTROL1_TX_SEL_HALFRATE_SHIFT);
   1647     
   1648         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, 0x8065, uData) */
   1649         SOC_IF_ERROR_RETURN
   1650             (WRITE_HL65_TX0_ANATXACONTROL1r(unit, pc, data));
   1651 
   1652         break;
   1653 
   1654     default:
   1655         rv = SOC_E_PARAM;
   1656     }
   1657 
   1658     return rv;
   1659 }
   1660 
   1661 
   1662 /*
   1663  * Function:
   1664  *      phy_hl65_speed_set
   1665  * Purpose:
   1666  *      Set PHY speed
   1667  * Parameters:
   1668  *      unit - StrataSwitch unit #.
   1669  *      port - StrataSwitch port #. 
   1670  *      speed - link speed in Mbps
   1671  * Returns:     
   1672  *      SOC_E_NONE
   1673  */
   1674 
   1675 STATIC int
   1676 phy_hl65_speed_set(int unit, soc_port_t port, int speed)
   1677 {
   1678     phy_ctrl_t  *pc;
   1679     uint16       speed_val, mask;
   1680     uint16       speed_mii;
   1681     uint16       sgmii_status = 0;
   1682     int          hg10g_port = FALSE;
   1683     int          rxaui;
   1684 
   1685     if (PHY_HC65_FABRIC_MODE(unit, port)) {
   1686         return phy_hl65_fabric_mode_speed_set(unit, port, speed);
   1687     }
   1688 
   1689     pc = INT_PHY_SW_STATE(unit, port);
   1690 
   1691     if (PHY_INDEPENDENT_LANE_MODE(unit, port) && (speed > 12000)) {
   1692         return SOC_E_PARAM;
   1693     } 
   1694 
   1695     /* check if RXAUI is set in combo mode */
   1696     rxaui = soc_property_port_get(unit, port,
   1697                                     spn_SERDES_2WIRE_XAUI, FALSE);
   1698 
   1699     /* HC rev D0 supports 10G and 12G speeds in dxgxs mode in ind. lane mode */
   1700     if (pc->phy_mode == PHYCTRL_DUAL_LANE_PORT) {
   1701         rxaui = TRUE;
   1702     }
   1703 
   1704     if (IS_HG_PORT(unit, port) &&
   1705         soc_property_port_get(unit, port, spn_10G_IS_CX4, TRUE) == FALSE) {
   1706         hg10g_port = TRUE; 
   1707     }
   1708 
   1709     speed_val = 0;
   1710     speed_mii = 0;
   1711     mask      =  DIGITAL_MISC1_FORCE_SPEED_MASK;
   1712     switch (speed) {
   1713     case 0:
   1714         /* Do not change speed */
   1715         return SOC_E_NONE;
   1716     case 10:
   1717         speed_mii = MII_CTRL_SS_10;
   1718         break;
   1719     case 100:
   1720         speed_mii = MII_CTRL_SS_100;
   1721         break;
   1722     case 1000:
   1723         speed_mii = MII_CTRL_SS_1000;
   1724         break;
   1725     case 2500:
   1726         speed_val = DIGITAL_MISC1_FORCE_SPEED_dr_2500BRCM_X1; 
   1727         break;
   1728     case 10000:
   1729         speed_val = DIGITAL_MISC1_FORCE_SPEED_dr_10GBASE_CX4; /* 10G CX4 */
   1730         if ((hg10g_port == TRUE) && rxaui) {
   1731             speed_val = 0x21;  /* 10.5HiG dual-XGXS */
   1732         } else if (rxaui) {
   1733             speed_val = 0x20; /* 10G ethernet dual-XGXS */
   1734         } else if (hg10g_port == TRUE) {
   1735             speed_val = DIGITAL_MISC1_FORCE_SPEED_dr_10GHiGig_X4; /* 10G HiG */
   1736         }
   1737         break;
   1738     case 12000:
   1739         speed_val = rxaui? 0x23: /* 12.7HiG dual-XGXS*/
   1740                      DIGITAL_MISC1_FORCE_SPEED_dr_12GHiGig_X4;   /* 12 HiG */
   1741         break;
   1742     case 13000:
   1743         speed_val = DIGITAL_MISC1_FORCE_SPEED_dr_13GHiGig_X4;
   1744         break;
   1745     case 16000:
   1746         speed_val = DIGITAL_MISC1_FORCE_SPEED_dr_16GHiGig_X4;
   1747         break;
   1748     case 20000:
   1749         speed_val = DIGITAL_MISC1_FORCE_SPEED_dr_20GHiGig_X4;
   1750         break;
   1751     case 21000:
   1752         speed_val = DIGITAL_MISC1_FORCE_SPEED_dr_21GHiGig_X4;
   1753         break;
   1754     case 25000:
   1755         speed_val = DIGITAL_MISC1_FORCE_SPEED_dr_25p45GHiGig_X4;
   1756         break;
   1757     default:
   1758         return SOC_E_PARAM;
   1759     }
   1760 
   1761     if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   1762         /* set scrambler controls */
   1763         if (speed == 20000) {
   1764             SOC_IF_ERROR_RETURN
   1765                  (MODIFY_HL65_XGXSBLK0_XGMIIRCONTROLr(unit,pc,
   1766                        XGXSBLK0_XGMIIRCONTROL_SCR_EN_4LANE_MASK,
   1767                        XGXSBLK0_XGMIIRCONTROL_SCR_EN_4LANE_MASK));
   1768         } else {
   1769             SOC_IF_ERROR_RETURN
   1770                  (MODIFY_HL65_XGXSBLK0_XGMIIRCONTROLr(unit,pc,
   1771                        0,
   1772                        XGXSBLK0_XGMIIRCONTROL_SCR_EN_4LANE_MASK));
   1773         }
   1774         _phy_hl65_dsp_cfg(unit,pc,speed); 
   1775 
   1776         /* Puts PLL in reset state and forces all datapath into reset state */
   1777         SOC_IF_ERROR_RETURN
   1778             (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, 0,
   1779                                   XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK));
   1780 
   1781         /* 2wire XAUI configuration */
   1782         SOC_IF_ERROR_RETURN
   1783             (_hl65_rxaui_config(unit,pc,rxaui));
   1784 
   1785     } else {
   1786         /* Hold rxSeqStart */
   1787         SOC_IF_ERROR_RETURN
   1788             (HL65_REG_MODIFY(unit,pc,0x0,0x826E + (0x10 * pc->lane_num),
   1789                               DSC2B0_DSC_MISC_CTRL0_RXSEQSTART_MASK,
   1790                               DSC2B0_DSC_MISC_CTRL0_RXSEQSTART_MASK));
   1791 
   1792         /* hold TX FIFO in reset */
   1793         SOC_IF_ERROR_RETURN
   1794             (MODIFY_HL65_DIGITAL_CONTROL1000X3r(unit, pc, 
   1795                                DIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK,
   1796                                DIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK));
   1797     }
   1798  
   1799     /* disable 100FX and 100FX auto-detect */
   1800     SOC_IF_ERROR_RETURN
   1801         (MODIFY_HL65_FX100_CONTROL1r(unit,pc,
   1802                               0,
   1803                               FX100_CONTROL1_AUTODET_EN_MASK |
   1804                               FX100_CONTROL1_ENABLE_MASK));
   1805 
   1806     /* disable 100FX idle detect */
   1807     SOC_IF_ERROR_RETURN
   1808             (MODIFY_HL65_FX100_CONTROL3r(unit,pc,
   1809                               FX100_CONTROL3_CORRELATOR_DISABLE_MASK,
   1810                               FX100_CONTROL3_CORRELATOR_DISABLE_MASK));
   1811 
   1812     SOC_IF_ERROR_RETURN
   1813         (MODIFY_HL65_DIGITAL_MISC1r(unit, pc, speed_val, mask));
   1814 
   1815     SOC_IF_ERROR_RETURN
   1816         (MODIFY_HL65_DIGITAL4_MISC3r(unit, pc, 
   1817                 (speed_val & 0x20)?  DIGITAL4_MISC3_FORCE_SPEED_B5_MASK:0,
   1818                 DIGITAL4_MISC3_FORCE_SPEED_B5_MASK));
   1819 
   1820     if (speed <= 1000) {
   1821         SOC_IF_ERROR_RETURN
   1822             (READ_HL65_DIGITAL_STATUS1000X1r(unit, pc, &sgmii_status));
   1823 
   1824         sgmii_status &= DIGITAL_STATUS1000X1_SGMII_MODE_MASK;
   1825         if (!sgmii_status && (speed == 100)) {
   1826 
   1827             /* fiber mode 100fx, enable */
   1828             SOC_IF_ERROR_RETURN
   1829                 (MODIFY_HL65_FX100_CONTROL1r(unit,pc,
   1830                                   FX100_CONTROL1_FAR_END_FAULT_EN_MASK |
   1831                                   FX100_CONTROL1_ENABLE_MASK,
   1832                                   FX100_CONTROL1_FAR_END_FAULT_EN_MASK |
   1833                                   FX100_CONTROL1_ENABLE_MASK));
   1834 
   1835             /* enable 100fx extended packet size */
   1836             SOC_IF_ERROR_RETURN
   1837                 (MODIFY_HL65_FX100_CONTROL2r(unit,pc,
   1838                                 FX100_CONTROL2_EXTEND_PKT_SIZE_MASK,
   1839                                 FX100_CONTROL2_EXTEND_PKT_SIZE_MASK));
   1840         } else {
   1841             SOC_IF_ERROR_RETURN
   1842                 (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, speed_mii,
   1843                                               MII_CTRL_SS_MASK));
   1844         }
   1845     }
   1846 
   1847     /* for speed above 10G, txcko_div must be cleared */
   1848     speed_val = (speed > 10000) ? 0: XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK;
   1849     SOC_IF_ERROR_RETURN
   1850         (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, speed_val, 
   1851                                      XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK));
   1852 
   1853     /* set tx half rate based on speed */
   1854     SOC_IF_ERROR_RETURN
   1855         (_phy_hl65_half_rate_set(unit,port,speed));
   1856 
   1857     if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   1858         /* Bring PLL out of reset */
   1859         SOC_IF_ERROR_RETURN
   1860             (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc,
   1861                                   XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK,
   1862                                   XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK));
   1863         (void) _phy_hl65_pll_lock_wait(unit, port);
   1864     } else {
   1865         /* release rxSeqStart */
   1866         SOC_IF_ERROR_RETURN
   1867             (HL65_REG_MODIFY(unit,pc,0x0,0x826E + (0x10 * pc->lane_num),
   1868                               0,
   1869                               DSC2B0_DSC_MISC_CTRL0_RXSEQSTART_MASK));
   1870 
   1871         /* release TX FIFO reset */
   1872         SOC_IF_ERROR_RETURN
   1873             (MODIFY_HL65_DIGITAL_CONTROL1000X3r(unit, pc, 
   1874                                0,
   1875                                DIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK));
   1876     }
   1877 
   1878     return SOC_E_NONE;
   1879 }
   1880 
   1881 STATIC int
   1882 _phy_hl65_tx_fifo_reset(int unit, soc_port_t port,uint32 speed)
   1883 {
   1884     uint16 data16;
   1885     phy_ctrl_t  *pc;
   1886     pc = INT_PHY_SW_STATE(unit, port);
   1887 
   1888     if (speed == 100) {
   1889         /* check if it is in 100fx mode */
   1890         SOC_IF_ERROR_RETURN
   1891             (READ_HL65_FX100_CONTROL1r(unit,pc,&data16));
   1892 
   1893         if (data16 & FX100_CONTROL1_ENABLE_MASK) {
   1894             /* reset TX FIFO  */
   1895             SOC_IF_ERROR_RETURN
   1896                 (HL65_REG_MODIFY(unit,pc,0x0,0x8061 + (0x10 * pc->lane_num),
   1897                                  TX0_ANATXACONTROL0_TX1G_FIFO_RST_MASK,
   1898                                  TX0_ANATXACONTROL0_TX1G_FIFO_RST_MASK));
   1899 
   1900             SOC_IF_ERROR_RETURN
   1901                 (HL65_REG_MODIFY(unit,pc,0x0,0x8061 + (0x10 * pc->lane_num),
   1902                               0,
   1903                               TX0_ANATXACONTROL0_TX1G_FIFO_RST_MASK));
   1904         }
   1905     }
   1906     return SOC_E_NONE;
   1907 }
   1908 
   1909 /*
   1910  * Function:
   1911  *      phy_hl65_fabric_mode_speed_get
   1912  * Purpose:
   1913  *      Get PHY speed
   1914  * Parameters:
   1915  *      unit - SBX device unit #.
   1916  *      port - SBX device port #. 
   1917  *      speed - link speed in Mbps
   1918  * Returns:     
   1919  *      SOC_E_NONE
   1920  */
   1921 
   1922 STATIC int
   1923 phy_hl65_fabric_mode_speed_get(int unit, soc_port_t port, int *speed)
   1924 {
   1925     phy_ctrl_t  *pc;
   1926     uint16 data;
   1927 
   1928     pc = INT_PHY_SW_STATE(unit, port);
   1929 
   1930     /* read speed from hardware */
   1931     /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, 0x8308, &uData) */
   1932     SOC_IF_ERROR_RETURN
   1933         (READ_HL65_DIGITAL_MISC1r(unit, pc, &data));
   1934 
   1935     if (data == 0x7720) {
   1936 	*speed = 6250;
   1937     } else if (data == 0x7820) {
   1938 	*speed = 6500;
   1939     } else {
   1940 	*speed = 3125;
   1941     }
   1942     return SOC_E_NONE;
   1943 
   1944 }
   1945 
   1946 /*
   1947  * Function:
   1948  *      phy_hl65_speed_get
   1949  * Purpose:
   1950  *      Get PHY speed
   1951  * Parameters:
   1952  *      unit - StrataSwitch unit #.
   1953  *      port - StrataSwitch port #. 
   1954  *      speed - current link speed in Mbps
   1955  * Returns:     
   1956  *      SOC_E_NONE
   1957  */
   1958 STATIC int
   1959 phy_hl65_speed_get(int unit, soc_port_t port, int *speed)
   1960 {
   1961     phy_ctrl_t *pc;
   1962     uint16 speed_val;
   1963 
   1964     if (PHY_HC65_FABRIC_MODE(unit, port)) {
   1965         return phy_hl65_fabric_mode_speed_get(unit, port, speed);
   1966     }
   1967 
   1968     pc = INT_PHY_SW_STATE(unit, port);
   1969 
   1970     if (PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   1971         uint16      sd_stat;
   1972 
   1973         SOC_IF_ERROR_RETURN
   1974             (READ_HL65_DIGITAL_STATUS1000X1r(unit, pc, &sd_stat));
   1975         sd_stat = (sd_stat & DIGITAL_STATUS1000X1_SPEED_STATUS_MASK)
   1976                       >> DIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT;
   1977         switch (sd_stat) {
   1978         case 2:
   1979             *speed = 1000;
   1980             break;
   1981         case 3:
   1982             *speed = 2500;
   1983             break;
   1984         case 0:
   1985             *speed = 10;
   1986             break;
   1987         case 1:
   1988             *speed = 100;
   1989             break;
   1990         default:
   1991             *speed = 0;
   1992         }
   1993         /* check dxgxs speeds 
   1994          * There is no speed status for second dxgxs block. We'll simply
   1995          * check what the speed is set. It should be OK since the dxgxs mode
   1996          * does not support autoneg 
   1997          */
   1998         if ((pc->phy_mode == PHYCTRL_DUAL_LANE_PORT) && 
   1999             (IS_HG_PORT(unit,port) || IS_XE_PORT(unit,port))) {
   2000             SOC_IF_ERROR_RETURN
   2001                 (READ_HL65_DIGITAL4_MISC3r(unit, pc, &speed_val));
   2002             if (speed_val & DIGITAL4_MISC3_FORCE_SPEED_B5_MASK) {
   2003                 SOC_IF_ERROR_RETURN
   2004                     (READ_HL65_DIGITAL_MISC1r(unit, pc, &speed_val));
   2005                 if ((speed_val & DIGITAL_MISC1_FORCE_SPEED_MASK) == 3) {
   2006                     *speed=12000;
   2007                 } else if ((speed_val & DIGITAL_MISC1_FORCE_SPEED_MASK) == 0 ||
   2008                            (speed_val & DIGITAL_MISC1_FORCE_SPEED_MASK) == 1) {
   2009                     *speed=10000;
   2010                 }
   2011             }
   2012         }
   2013     } else {
   2014         uint16      xgxs_stat;
   2015         uint16   xgxs20g_stat = 0;
   2016 
   2017         SOC_IF_ERROR_RETURN
   2018             (READ_HL65_GP_STATUS_XGXSSTATUS1r(unit, pc, &xgxs_stat));
   2019 
   2020         switch (xgxs_stat & GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_MASK) {
   2021         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_10M:
   2022             *speed = 10;
   2023             break;
   2024         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_100M:
   2025             *speed = 100;
   2026             break;
   2027         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_1G:
   2028             *speed = 1000;
   2029             break;
   2030         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_2p5G:
   2031             *speed = 2500;
   2032             break;
   2033         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_5G_X4:
   2034             *speed = 5000;
   2035             break;
   2036         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_6G_X4:
   2037             *speed = 6000;
   2038             break;
   2039         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_10G_HiG:
   2040             /* fall through */
   2041         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_10G_CX4:
   2042             *speed = 10000;
   2043             break;
   2044         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_12G_HiG:
   2045         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_12p5G_X4:
   2046             *speed = 12000;
   2047             break;
   2048         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_13G_X4:
   2049             *speed = 13000;
   2050             break;
   2051         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_15G_X4:
   2052             *speed = 15000;
   2053             break;
   2054         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_16G_X4:
   2055             *speed = 16000;
   2056             break;
   2057         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_1G_KX:
   2058             *speed = 1000;
   2059             break;
   2060         case GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_dr_10G_KX4:
   2061             *speed = 10000;
   2062             break;
   2063         default:
   2064             *speed = 0;
   2065         }
   2066 
   2067         /* check 20G and above and dxgxs speed */
   2068         SOC_IF_ERROR_RETURN
   2069           (READ_HL65_AN73_PDET_XGXSSTATUS4r(unit, pc, &xgxs20g_stat));
   2070         xgxs20g_stat &= AN73_PDET_XGXSSTATUS4_ACTUAL_SPEED_LN0_MASK;
   2071         switch (xgxs20g_stat) {
   2072             case AN73_PDET_XGXSSTATUS4_ACTUAL_SPEED_LN0_dr_20G_X4:
   2073                 *speed=20000;
   2074                 break;
   2075             case AN73_PDET_XGXSSTATUS4_ACTUAL_SPEED_LN0_dr_21G_X4:
   2076                 *speed=21000;
   2077                 break;
   2078             case AN73_PDET_XGXSSTATUS4_ACTUAL_SPEED_LN0_dr_25G_X4:
   2079                 *speed=25000;
   2080                 break;
   2081             case AN73_PDET_XGXSSTATUS4_ACTUAL_SPEED_LN0_dr_10G_HiG_DXGXS:
   2082                 /* fall through */
   2083             case AN73_PDET_XGXSSTATUS4_ACTUAL_SPEED_LN0_dr_10G_DXGXS:
   2084                 /* fall through */
   2085             case AN73_PDET_XGXSSTATUS4_ACTUAL_SPEED_LN0_dr_10p5G_HiG_DXGXS:
   2086                 /* fall through */
   2087             case AN73_PDET_XGXSSTATUS4_ACTUAL_SPEED_LN0_dr_10p5G_DXGXS:
   2088                 *speed = 10000;
   2089                 break;
   2090            case AN73_PDET_XGXSSTATUS4_ACTUAL_SPEED_LN0_dr_12p773G_HiG_DXGXS:                    /* fall through */
   2091            case AN73_PDET_XGXSSTATUS4_ACTUAL_SPEED_LN0_dr_12p773G_DXGXS:
   2092                 *speed = 12000;
   2093                 break;
   2094             default:
   2095                 break;
   2096         }
   2097 
   2098         LOG_INFO(BSL_LS_SOC_PHY,
   2099                  (BSL_META_U(unit,
   2100                              "phy_hl65_speed_get: u=%d p=%d GP_STATUS_TOPANSTATUS1 %04x speed= %d\n"),
   2101                   unit, port,
   2102                   ((xgxs_stat & GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_MASK) >>
   2103                   GP_STATUS_XGXSSTATUS1_ACTUAL_SPEED_LN0_SHIFT), *speed));
   2104 
   2105     }
   2106     return SOC_E_NONE;
   2107 }
   2108 
   2109 /*
   2110  * Function:    
   2111  *      phy_hl65_an_set
   2112  * Purpose:     
   2113  *      Enable or disabled auto-negotiation on the specified port.
   2114  * Parameters:
   2115  *      unit - StrataSwitch unit #.
   2116  *      port - StrataSwitch port #. 
   2117  *      an   - Boolean, if true, auto-negotiation is enabled 
   2118  *              (and/or restarted). If false, autonegotiation is disabled.
   2119  * Returns:     
   2120  *      SOC_E_XXX
   2121  */
   2122 int
   2123 phy_hl65_an_set(int unit, soc_port_t port, int an)
   2124 {
   2125     phy_ctrl_t  *pc;
   2126     uint16             an_enable;
   2127     uint16             auto_det;
   2128     uint16 data16;
   2129     uint16 mask16;
   2130 
   2131     pc = INT_PHY_SW_STATE(unit, port);
   2132 
   2133     LOG_INFO(BSL_LS_SOC_PHY,
   2134              (BSL_META_U(unit,
   2135                          "phy_hl65_an_set: u=%d p=%d an=%d\n"),
   2136               unit, port, an));
   2137 
   2138     an_enable = 0;
   2139     auto_det  = 0;
   2140 
   2141     if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   2142         data16 = 0;
   2143         mask16 = AN73_PDET_PARDET10GCONTROL_PARDET10G_EN_MASK;
   2144         if (soc_property_port_get(unit, port, spn_XGXS_PDETECT_10G, 1) && an) {
   2145             data16 = AN73_PDET_PARDET10GCONTROL_PARDET10G_EN_MASK;
   2146         }
   2147         SOC_IF_ERROR_RETURN
   2148             (MODIFY_HL65_AN73_PDET_PARDET10GCONTROLr(unit, pc, data16,
   2149                                                          mask16));
   2150 
   2151         /* Always enable 1000X parallel detect */
   2152         SOC_IF_ERROR_RETURN
   2153             (MODIFY_HL65_DIGITAL_CONTROL1000X2r(unit, pc, 
   2154               DIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK, 
   2155               DIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK));
   2156     }
   2157 
   2158     if (an) {
   2159 
   2160         /* disable 100FX and 100FX auto-detect */
   2161         SOC_IF_ERROR_RETURN
   2162             (MODIFY_HL65_FX100_CONTROL1r(unit,pc,
   2163                                   0,
   2164                                   FX100_CONTROL1_AUTODET_EN_MASK |
   2165                                   FX100_CONTROL1_ENABLE_MASK));
   2166 
   2167         /* disable 100FX idle detect */
   2168         SOC_IF_ERROR_RETURN
   2169                 (MODIFY_HL65_FX100_CONTROL3r(unit,pc,
   2170                                   FX100_CONTROL3_CORRELATOR_DISABLE_MASK,
   2171                                   FX100_CONTROL3_CORRELATOR_DISABLE_MASK));
   2172 
   2173         /* set tx half rate with default value before starting AN */
   2174         SOC_IF_ERROR_RETURN
   2175             (_phy_hl65_half_rate_set(unit,port,0)); 
   2176 
   2177         an_enable = MII_CTRL_AE | MII_CTRL_RAN;
   2178 
   2179         /*
   2180          * Should read one during init and cache it in Phy flags
   2181          */
   2182         if (soc_property_port_get(unit, port,
   2183                                   spn_SERDES_AUTOMEDIUM,
   2184                                   (PHY_INDEPENDENT_LANE_MODE(unit, port)) ?
   2185                                   FALSE : TRUE)) {
   2186             auto_det = DIGITAL_CONTROL1000X1_AUTODET_EN_MASK; 
   2187         }
   2188 
   2189         /* If auto-neg is enabled, make sure not forcing any speed */
   2190         SOC_IF_ERROR_RETURN
   2191             (MODIFY_HL65_DIGITAL_MISC1r(unit, pc, 0, 
   2192                                    DIGITAL_MISC1_FORCE_SPEED_MASK));
   2193         /* Enable/Disable auto detect */
   2194         SOC_IF_ERROR_RETURN
   2195              (MODIFY_HL65_DIGITAL_CONTROL1000X1r(unit, pc, auto_det,
   2196                                  DIGITAL_CONTROL1000X1_AUTODET_EN_MASK));
   2197 
   2198         if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   2199 
   2200             /* 
   2201              * Set the default value for DSP related registers which may be
   2202              * changed for 20G forced speed mode, otherwise AN won't work 
   2203              */
   2204             /* clear scrambler controls */
   2205             SOC_IF_ERROR_RETURN
   2206                  (MODIFY_HL65_XGXSBLK0_XGMIIRCONTROLr(unit,pc,
   2207                        0,
   2208                        XGXSBLK0_XGMIIRCONTROL_SCR_EN_4LANE_MASK));
   2209 
   2210             _phy_hl65_dsp_cfg(unit,pc,0); 
   2211 
   2212             /* clear 2wire XAUI configuration */
   2213             SOC_IF_ERROR_RETURN
   2214                 (_hl65_rxaui_config(unit,pc,FALSE));
   2215 
   2216             /* only in combo mode, reset the sequence. In independent mode,
   2217              * resetting sequence affects all lanes
   2218              */
   2219             SOC_IF_ERROR_RETURN
   2220                 (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, 0,
   2221                               XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK));
   2222 
   2223 
   2224             /* set BAM enable */
   2225             SOC_IF_ERROR_RETURN
   2226                 (WRITE_HL65_DIGITAL6_MP5_NEXTPAGECTRLr(unit,pc,1));
   2227 
   2228             /* enable autoneg */
   2229             SOC_IF_ERROR_RETURN
   2230                 (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, MII_CTRL_AE,
   2231                                       MII_CTRL_AE));
   2232             if (PHY_CLAUSE73_MODE(unit, port)) { 
   2233                 SOC_IF_ERROR_RETURN
   2234                     (MODIFY_HL65_AN_IEEE0BLK_AN_IEEECONTROL1r(unit, pc, 
   2235                                               MII_CTRL_AE,
   2236                                               MII_CTRL_AE));
   2237             }
   2238             /* restart the sequence */
   2239             SOC_IF_ERROR_RETURN
   2240                  (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, 
   2241                               XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK,
   2242                               XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK));
   2243             /* wait for PLL lock */
   2244             _phy_hl65_pll_lock_wait(unit, port);
   2245         }
   2246     } else {
   2247         /* Disable auto detect */
   2248         SOC_IF_ERROR_RETURN
   2249              (MODIFY_HL65_DIGITAL_CONTROL1000X1r(unit, pc, auto_det,
   2250                                  DIGITAL_CONTROL1000X1_AUTODET_EN_MASK));
   2251 
   2252         if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   2253             SOC_IF_ERROR_RETURN
   2254                 (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, 0,
   2255                               XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK));
   2256 
   2257             /* reset BAM enable */
   2258             SOC_IF_ERROR_RETURN
   2259                 (WRITE_HL65_DIGITAL6_MP5_NEXTPAGECTRLr(unit,pc,0));
   2260 
   2261             SOC_IF_ERROR_RETURN
   2262                 (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, 0,
   2263                                          MII_CTRL_AE));
   2264             if (PHY_CLAUSE73_MODE(unit, port)) { 
   2265                 SOC_IF_ERROR_RETURN
   2266                     (MODIFY_HL65_AN_IEEE0BLK_AN_IEEECONTROL1r(unit, pc, 
   2267                                               0,
   2268                                               MII_CTRL_AE));
   2269             }
   2270             SOC_IF_ERROR_RETURN
   2271                  (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, 
   2272                               XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK,
   2273                               XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK));
   2274             /* wait for PLL lock */
   2275             _phy_hl65_pll_lock_wait(unit, port);
   2276         }
   2277     }
   2278 
   2279     /* restart the autoneg if enabled, or disable the autoneg */
   2280     SOC_IF_ERROR_RETURN
   2281         (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, an_enable,
   2282                                       MII_CTRL_AE | MII_CTRL_RAN));
   2283 
   2284     if (PHY_CLAUSE73_MODE(unit, port)) { 
   2285         SOC_IF_ERROR_RETURN
   2286             (MODIFY_HL65_AN_IEEE0BLK_AN_IEEECONTROL1r(unit, pc, an_enable,
   2287                                       MII_CTRL_AE | MII_CTRL_RAN));
   2288     }
   2289     pc->fiber.autoneg_enable = an;
   2290 
   2291     return SOC_E_NONE;
   2292 }
   2293 
   2294 /*
   2295  * Function:    
   2296  *      phy_hl65_an_get
   2297  * Purpose:     
   2298  *      Get the current auto-negotiation status (enabled/busy)
   2299  * Parameters:
   2300  *      unit - StrataSwitch unit #.
   2301  *      port - StrataSwitch port #. 
   2302  *      an   - (OUT) if true, auto-negotiation is enabled.
   2303  *      an_done - (OUT) if true, auto-negotiation is complete. This
   2304  *              value is undefined if an == false.
   2305  * Returns:     
   2306  *      SOC_E_XXX
   2307  */
   2308 
   2309 STATIC int
   2310 phy_hl65_an_get(int unit, soc_port_t port, int *an, int *an_done)
   2311 {
   2312     uint16      mii_ctrl;
   2313     uint16      mii_stat;
   2314     phy_ctrl_t *pc;
   2315 
   2316     pc = INT_PHY_SW_STATE(unit, port);
   2317 
   2318     SOC_IF_ERROR_RETURN
   2319         (READ_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl));
   2320     SOC_IF_ERROR_RETURN
   2321         (READ_HL65_COMBO_IEEE0_MIISTATr(unit, pc, &mii_stat));
   2322 
   2323     *an = (mii_ctrl & MII_CTRL_AE) ? TRUE : FALSE;
   2324     *an_done = (mii_stat & MII_STAT_AN_DONE) ? TRUE : FALSE;
   2325     if (!((*an == TRUE) && (*an_done == TRUE))) {
   2326         if (PHY_CLAUSE73_MODE(unit, port)) { 
   2327             /* check clause 73 */
   2328             SOC_IF_ERROR_RETURN
   2329                 (READ_HL65_AN_IEEE0BLK_AN_IEEECONTROL1r(unit, pc, &mii_ctrl));
   2330             SOC_IF_ERROR_RETURN
   2331                 (READ_HL65_AN_IEEE0BLK_AN_IEEESTATUS1r(unit, pc, &mii_stat));
   2332 
   2333             *an = (mii_ctrl & MII_CTRL_AE) ? TRUE : FALSE;
   2334             *an_done = (mii_stat & MII_STAT_AN_DONE) ? TRUE : FALSE;
   2335         }
   2336     }
   2337     return SOC_E_NONE; 
   2338 }
   2339 
   2340 STATIC int
   2341 _phy_hl65_c73_adv_local_set(int unit, soc_port_t port,
   2342                             soc_port_ability_t *ability)
   2343 {
   2344     uint16            an_adv;
   2345     uint16            pause;
   2346     phy_ctrl_t       *pc;
   2347 
   2348     pc = INT_PHY_SW_STATE(unit, port);
   2349 
   2350     an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? 
   2351               CL73_AN_ADV_TECH_1G_KX : 0;
   2352     an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ? 
   2353               CL73_AN_ADV_TECH_10G_KX4 : 0;
   2354 
   2355     SOC_IF_ERROR_RETURN
   2356         (MODIFY_HL65_AN_IEEE1BLK_AN_ADVERTISEMENT1r(unit, pc, an_adv,
   2357                                      CL73_AN_ADV_TECH_SPEEDS_MASK));
   2358 
   2359     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   2360     case SOC_PA_PAUSE_TX:
   2361         pause = CL73_AN_ADV_ASYM_PAUSE;
   2362         break;
   2363     case SOC_PA_PAUSE_RX:
   2364         pause = CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE;
   2365         break;
   2366     case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   2367         pause = CL73_AN_ADV_PAUSE;
   2368         break;
   2369     default:
   2370         pause = 0;
   2371     }
   2372 
   2373     SOC_IF_ERROR_RETURN
   2374         (MODIFY_HL65_AN_IEEE1BLK_AN_ADVERTISEMENT0r(unit, pc, pause,
   2375                                      (CL73_AN_ADV_PAUSE |
   2376                                       CL73_AN_ADV_ASYM_PAUSE)));
   2377     
   2378     LOG_INFO(BSL_LS_SOC_PHY,
   2379              (BSL_META_U(unit,
   2380                          "_phy_hl65_c73_adv_local_set: u=%d p=%d pause=%08x speeds=%04x,adv=0x%x\n"),
   2381               unit, port, pause, an_adv,ability->speed_full_duplex));
   2382     return SOC_E_NONE;
   2383 }
   2384 
   2385 STATIC int
   2386 _phy_hl65_c73_adv_local_get(int unit, soc_port_t port,
   2387                             soc_port_ability_t *ability)
   2388 {
   2389     uint16            an_adv;
   2390     soc_port_mode_t   speeds,pause;
   2391     phy_ctrl_t       *pc;
   2392 
   2393     pc = INT_PHY_SW_STATE(unit, port);
   2394 
   2395     SOC_IF_ERROR_RETURN
   2396         (READ_HL65_AN_IEEE1BLK_AN_ADVERTISEMENT1r(unit, pc, &an_adv));
   2397 
   2398     speeds = (an_adv & CL73_AN_ADV_TECH_1G_KX) ? SOC_PA_SPEED_1000MB : 0;
   2399     speeds |= (an_adv & CL73_AN_ADV_TECH_10G_KX4) ? SOC_PA_SPEED_10GB : 0;
   2400     ability->speed_full_duplex |= speeds;
   2401 
   2402     SOC_IF_ERROR_RETURN
   2403         (READ_HL65_AN_IEEE1BLK_AN_ADVERTISEMENT0r(unit, pc, &an_adv));
   2404 
   2405     switch (an_adv & (CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE)) {
   2406         case CL73_AN_ADV_PAUSE:
   2407             pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   2408             break;
   2409         case CL73_AN_ADV_ASYM_PAUSE:
   2410             pause = SOC_PA_PAUSE_TX;
   2411             break;
   2412         case CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE:
   2413             pause = SOC_PA_PAUSE_RX;
   2414             break;
   2415         default:
   2416             pause = 0;
   2417     }
   2418     ability->pause = pause;
   2419 
   2420     LOG_INFO(BSL_LS_SOC_PHY,
   2421              (BSL_META_U(unit,
   2422                          "_phy_hl65_c73_adv_local_get: u=%d p=%d pause=%08x speeds=%04x\n"),
   2423               unit, port, pause, speeds));
   2424     return SOC_E_NONE;
   2425 }
   2426 
   2427 /*
   2428  * Function:
   2429  *      phy_hl65_ability_advert_set
   2430  * Purpose:
   2431  *      Set the current advertisement for auto-negotiation.
   2432  * Parameters:
   2433  *      unit - StrataSwitch unit #.
   2434  *      port - StrataSwitch port #.
   2435  *      mode - Port mode mask indicating supported options/speeds.
   2436  * Returns:
   2437  *      SOC_E_XXX
   2438  * Notes:
   2439  *      The advertisement is set only for the ACTIVE medium.
   2440  *      No synchronization performed at this level.
   2441  */
   2442 
   2443 STATIC int
   2444 phy_hl65_ability_advert_set(int unit, soc_port_t port,
   2445                        soc_port_ability_t *ability)
   2446 {
   2447     uint16           an_adv;
   2448     uint16           an_sp_20g;
   2449     soc_port_mode_t  mode;
   2450     phy_ctrl_t      *pc;
   2451 
   2452     if (NULL == ability) {
   2453         return (SOC_E_PARAM);
   2454     }
   2455 
   2456     pc = INT_PHY_SW_STATE(unit, port);
   2457 
   2458     /*
   2459      * Set advertised duplex (only FD supported).
   2460      */
   2461     an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? MII_ANA_C37_FD : 0;
   2462 
   2463     /*
   2464      * Set advertised pause bits in link code word.
   2465      */
   2466     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   2467     case SOC_PA_PAUSE_TX:
   2468         an_adv |= MII_ANA_C37_ASYM_PAUSE;
   2469         break;
   2470     case SOC_PA_PAUSE_RX:
   2471         an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE;
   2472         break;
   2473     case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   2474         an_adv |= MII_ANA_C37_PAUSE;
   2475         break;
   2476     }
   2477     /* Update less than 1G capability */ 
   2478     SOC_IF_ERROR_RETURN
   2479         (WRITE_HL65_COMBO_IEEE0_AUTONEGADVr(unit, pc, an_adv));
   2480   
   2481     mode = ability->speed_full_duplex;
   2482     an_adv = 0;
   2483     an_sp_20g = 0;
   2484     if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   2485         an_adv |= (mode & SOC_PA_SPEED_2500MB) ? 
   2486                     DIGITAL3_UP1_DATARATE_2P5GX1_MASK : 0;
   2487         an_adv |= (mode & SOC_PA_SPEED_12GB) ? 
   2488                     DIGITAL3_UP1_DATARATE_12GX4_MASK : 0;
   2489         an_adv |= (mode & SOC_PA_SPEED_13GB) ? 
   2490                     DIGITAL3_UP1_DATARATE_13GX4_MASK : 0;
   2491         an_adv |= (mode & SOC_PA_SPEED_16GB) ? 
   2492                     DIGITAL3_UP1_DATARATE_16GX4_MASK : 0;
   2493 
   2494         /* 20G operation in autoneg is not reliable.
   2495          * Use forced mode only. 
   2496          *an_adv |= (mode & SOC_PA_SPEED_20GB) ? 
   2497          *          DIGITAL3_UP1_DATARATE_20GX4_MASK : 0;
   2498          */
   2499 
   2500         an_sp_20g |= (mode & SOC_PA_SPEED_21GB) ? 
   2501                       DIGITAL3_UP3_DATARATE_21GX4_MASK : 0;
   2502         an_sp_20g |= (mode & SOC_PA_SPEED_25GB) ? 
   2503                       DIGITAL3_UP3_DATARATE_25P45GX4_MASK : 0;
   2504     }
   2505 
   2506     if (mode & SOC_PA_SPEED_10GB) {
   2507         if (IS_HG_PORT(unit, port)) {
   2508             /* For Draco and Hercules, use pre-CX4 signalling */
   2509             an_adv |= DIGITAL3_UP1_DATARATE_10GX4_MASK; 
   2510             if (soc_property_port_get(unit, port, spn_10G_IS_CX4, TRUE)) {
   2511                 /* Also include 10G CX4 signalling by default */
   2512                 an_adv |= DIGITAL3_UP1_DATARATE_10GCX4_MASK; 
   2513             }
   2514         } else {
   2515             an_adv |= DIGITAL3_UP1_DATARATE_10GCX4_MASK; 
   2516         }
   2517     }
   2518     SOC_IF_ERROR_RETURN
   2519         (WRITE_HL65_DIGITAL3_UP1r(unit, pc, an_adv));
   2520 
   2521     SOC_IF_ERROR_RETURN
   2522         (MODIFY_HL65_DIGITAL3_UP3r(unit, pc, an_sp_20g,
   2523                    OVER1G_UP3_20GPLUS_MASK));
   2524 
   2525     if (PHY_CLAUSE73_MODE(unit, port)) { 
   2526         SOC_IF_ERROR_RETURN
   2527             (_phy_hl65_c73_adv_local_set(unit, port, ability));
   2528     }
   2529 
   2530     LOG_INFO(BSL_LS_SOC_PHY,
   2531              (BSL_META_U(unit,
   2532                          "phy_hl65_ability_advert_set: u=%d p=%d pause=%08x OVER1G_UP1 %04x\n"),
   2533               unit, port, ability->pause, an_adv));
   2534     return SOC_E_NONE;
   2535 }
   2536 
   2537 /*
   2538  * Function:
   2539  *      phy_hl65_ability_advert_get
   2540  * Purpose:
   2541  *      Get the current advertisement for auto-negotiation.
   2542  * Parameters:
   2543  *      unit - StrataSwitch unit #.
   2544  *      port - StrataSwitch port #.
   2545  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   2546  * Returns:
   2547  *      SOC_E_XXX
   2548  * Notes:
   2549  *      The advertisement is retrieved for the ACTIVE medium.
   2550  *      No synchronization performed at this level.
   2551  */
   2552 
   2553 STATIC int
   2554 phy_hl65_ability_advert_get(int unit, soc_port_t port,
   2555                            soc_port_ability_t *ability)
   2556 {
   2557     uint16           an_adv;
   2558     uint16           an_sp_20g;
   2559     soc_port_mode_t  mode;
   2560     phy_ctrl_t      *pc;
   2561 
   2562     if (NULL == ability) {
   2563         return (SOC_E_PARAM);
   2564     }
   2565 
   2566     pc = INT_PHY_SW_STATE(unit, port);
   2567 
   2568     sal_memset(ability, 0, sizeof(*ability));
   2569     SOC_IF_ERROR_RETURN
   2570         (READ_HL65_DIGITAL3_UP1r(unit, pc, &an_adv));
   2571 
   2572     SOC_IF_ERROR_RETURN
   2573         (READ_HL65_DIGITAL3_UP3r(unit, pc, &an_sp_20g));
   2574 
   2575     mode = 0;
   2576     mode |= (an_sp_20g & DIGITAL3_UP3_DATARATE_25P45GX4_MASK) ?
   2577               SOC_PA_SPEED_25GB : 0;
   2578     mode |= (an_sp_20g & DIGITAL3_UP3_DATARATE_21GX4_MASK) ?
   2579               SOC_PA_SPEED_21GB : 0;
   2580     mode |= (an_adv & DIGITAL3_UP1_DATARATE_20GX4_MASK) ? SOC_PA_SPEED_20GB : 0;
   2581     mode |= (an_adv & DIGITAL3_UP1_DATARATE_16GX4_MASK) ? SOC_PA_SPEED_16GB : 0;
   2582     mode |= (an_adv & DIGITAL3_UP1_DATARATE_13GX4_MASK) ? SOC_PA_SPEED_13GB : 0;
   2583     mode |= (an_adv & DIGITAL3_UP1_DATARATE_12GX4_MASK) ? SOC_PA_SPEED_12GB : 0;
   2584     mode |= (an_adv & DIGITAL3_UP1_DATARATE_10GCX4_MASK) ? SOC_PA_SPEED_10GB: 0;
   2585     mode |= (an_adv & DIGITAL3_UP1_DATARATE_10GX4_MASK) ? SOC_PA_SPEED_10GB : 0;
   2586     mode |= (an_adv & DIGITAL3_UP1_DATARATE_2P5GX1_MASK) ? 
   2587                     SOC_PA_SPEED_2500MB : 0;
   2588 
   2589     SOC_IF_ERROR_RETURN
   2590         (READ_HL65_COMBO_IEEE0_AUTONEGADVr(unit, pc, &an_adv));
   2591       
   2592     mode |= (an_adv & MII_ANA_C37_FD) ? SOC_PA_SPEED_1000MB : 0;
   2593     ability->speed_full_duplex = mode;
   2594 
   2595     mode = 0;
   2596     switch (an_adv & (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE)) {
   2597         case MII_ANA_C37_PAUSE:
   2598             mode = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   2599             break;
   2600         case MII_ANA_C37_ASYM_PAUSE:
   2601             mode = SOC_PA_PAUSE_TX;
   2602             break;
   2603         case MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE:
   2604             mode = SOC_PA_PAUSE_RX;
   2605             break;
   2606     }
   2607     ability->pause = mode;
   2608 
   2609     /* check for clause73 */
   2610     if (PHY_CLAUSE73_MODE(unit, port)) {
   2611         SOC_IF_ERROR_RETURN
   2612             (_phy_hl65_c73_adv_local_get(unit, port, ability));
   2613     }
   2614 
   2615     LOG_INFO(BSL_LS_SOC_PHY,
   2616              (BSL_META_U(unit,
   2617                          "phy_hl65_ability_advert_get:unit=%d p=%d pause=%08x sp=%08x\n"),
   2618               unit, port, ability->pause, ability->speed_full_duplex));
   2619 
   2620     return SOC_E_NONE;
   2621 }
   2622 
   2623 STATIC int
   2624 _phy_hl65_c73_adv_remote_get(int unit, soc_port_t port,
   2625                              soc_port_ability_t *ability)
   2626 {
   2627     uint16            an_adv;
   2628     soc_port_mode_t   mode;
   2629     phy_ctrl_t       *pc;
   2630 
   2631     pc = INT_PHY_SW_STATE(unit, port);
   2632      SOC_IF_ERROR_RETURN
   2633         (READ_HL65_AN_IEEE1BLK_AN_LP_BASEPAGEABILITY1r(unit, pc, &an_adv));
   2634 
   2635     mode = (an_adv & CL73_AN_ADV_TECH_1G_KX) ? SOC_PA_SPEED_1000MB : 0;
   2636     mode |= (an_adv & CL73_AN_ADV_TECH_10G_KX4) ? SOC_PA_SPEED_10GB : 0;
   2637     ability->speed_full_duplex |= mode;
   2638 
   2639     SOC_IF_ERROR_RETURN
   2640         (READ_HL65_AN_IEEE1BLK_AN_LP_BASEPAGEABILITY0r(unit, pc, &an_adv));
   2641 
   2642     mode = 0;
   2643     switch (an_adv & (CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE)) {
   2644         case CL73_AN_ADV_PAUSE:
   2645             mode = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   2646             break;
   2647         case CL73_AN_ADV_ASYM_PAUSE:
   2648             mode = SOC_PA_PAUSE_TX;
   2649             break;
   2650         case CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE:
   2651             mode = SOC_PA_PAUSE_RX;
   2652             break;
   2653     }
   2654     ability->pause = mode;
   2655 
   2656     return SOC_E_NONE;
   2657 }
   2658 
   2659 /*
   2660  * Function:
   2661  *      phy_hl65_ability_remote_get
   2662  * Purpose:
   2663  *      Get the current advertisement for auto-negotiation.
   2664  * Parameters:
   2665  *      unit - StrataSwitch unit #.
   2666  *      port - StrataSwitch port #.
   2667  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   2668  * Returns:
   2669  *      SOC_E_XXX
   2670  * Notes:
   2671  *      The advertisement is retrieved for the ACTIVE medium.
   2672  *      No synchronization performed at this level.
   2673  */
   2674 
   2675 STATIC int
   2676 phy_hl65_ability_remote_get(int unit, soc_port_t port,
   2677                         soc_port_ability_t *ability)
   2678 {
   2679     uint16           an_adv;
   2680     uint16           an_sp_20g;
   2681     uint16           data16;
   2682     int              an_enable;
   2683     int              link_1000x = FALSE;
   2684     int              link_combo = FALSE;
   2685     soc_port_mode_t  mode;
   2686     phy_ctrl_t      *pc;
   2687 
   2688     pc = INT_PHY_SW_STATE(unit, port);
   2689 
   2690     SOC_IF_ERROR_RETURN
   2691         (READ_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, &data16));
   2692 
   2693     an_enable = (data16 & MII_CTRL_AE) ? TRUE : FALSE;
   2694 
   2695     if (PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   2696         SOC_IF_ERROR_RETURN
   2697             (READ_HL65_DIGITAL_STATUS1000X1r(unit, pc, &data16));
   2698         if (data16 & DIGITAL_STATUS1000X1_LINK_STATUS_MASK) {
   2699             link_1000x = TRUE;
   2700         }
   2701     } else {
   2702         SOC_IF_ERROR_RETURN
   2703             (READ_HL65_GP_STATUS_XGXSSTATUS1r(unit, pc, &data16));
   2704         if (data16 & (GP_STATUS_XGXSSTATUS1_LINKSTAT_MASK |
   2705                                GP_STATUS_XGXSSTATUS1_LINK10G_MASK)) {
   2706             link_combo = TRUE;
   2707         }
   2708     } 
   2709 
   2710     LOG_INFO(BSL_LS_SOC_PHY,
   2711              (BSL_META_U(unit,
   2712                          "u=%d p=%d an_enable=%04x link_1000x=%04x link_combo=%04x\n"),
   2713               unit, port, an_enable, link_1000x,link_combo));
   2714 
   2715     sal_memset(ability, 0, sizeof(*ability));
   2716     mode = 0;
   2717     if (an_enable && (link_1000x || link_combo)) {
   2718         /* Decode remote advertisement only when link is up and autoneg is 
   2719          * completed.
   2720          */
   2721  
   2722         SOC_IF_ERROR_RETURN
   2723             (READ_HL65_GP_STATUS_LP_UP3r(unit, pc, &an_sp_20g));
   2724 
   2725         SOC_IF_ERROR_RETURN
   2726             (READ_HL65_GP_STATUS_LP_UP1r(unit, pc, &an_adv));
   2727 
   2728         mode |= (an_sp_20g & GP_STATUS_LP_UP3_DATARATE_25P45GX4_MASK)?
   2729                 SOC_PA_SPEED_25GB: 0;
   2730         mode |= (an_sp_20g & GP_STATUS_LP_UP3_DATARATE_21GX4_MASK)?
   2731                 SOC_PA_SPEED_21GB: 0;
   2732         mode |= (an_adv & GP_STATUS_LP_UP1_DATARATE_20GX4_MASK) ? 
   2733                 SOC_PA_SPEED_20GB : 0;
   2734         mode |= (an_adv & GP_STATUS_LP_UP1_DATARATE_16GX4_MASK) ? 
   2735                 SOC_PA_SPEED_16GB : 0;
   2736         mode |= (an_adv & GP_STATUS_LP_UP1_DATARATE_13GX4_MASK) ? 
   2737                 SOC_PA_SPEED_13GB : 0;
   2738         mode |= (an_adv & GP_STATUS_LP_UP1_DATARATE_12GX4_MASK) ? 
   2739                 SOC_PA_SPEED_12GB : 0;
   2740         mode |= (an_adv & GP_STATUS_LP_UP1_DATARATE_10GCX4_MASK) ? 
   2741                 SOC_PA_SPEED_10GB : 0;
   2742         mode |= (an_adv & GP_STATUS_LP_UP1_DATARATE_10GX4_MASK) ? 
   2743                 SOC_PA_SPEED_10GB : 0;
   2744         mode |= (an_adv & GP_STATUS_LP_UP1_DATARATE_2P5GX1_MASK) ?
   2745                  SOC_PA_SPEED_2500MB : 0;
   2746 
   2747         LOG_INFO(BSL_LS_SOC_PHY,
   2748                  (BSL_META_U(unit,
   2749                              "u=%d p=%d over1G an_adv=%04x\n"),
   2750                   unit, port, an_adv));
   2751 
   2752         SOC_IF_ERROR_RETURN
   2753             (READ_HL65_COMBO_IEEE0_AUTONEGLPABILr(unit, pc, &an_adv));
   2754 
   2755         LOG_INFO(BSL_LS_SOC_PHY,
   2756                  (BSL_META_U(unit,
   2757                              "u=%d p=%d combo an_adv=%04x\n"),
   2758                   unit, port, an_adv));
   2759 
   2760         mode |= (an_adv & MII_ANP_C37_FD) ? SOC_PA_SPEED_1000MB : 0;
   2761         ability->speed_full_duplex = mode;
   2762           
   2763         switch (an_adv & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) {
   2764             case MII_ANP_C37_PAUSE:
   2765                 ability->pause |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   2766                 break;
   2767             case MII_ANP_C37_ASYM_PAUSE:
   2768                 ability->pause |= SOC_PA_PAUSE_TX;
   2769                 break;
   2770             case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE:
   2771                 ability->pause |= SOC_PA_PAUSE_RX;
   2772                 break;
   2773         }
   2774         if (PHY_CLAUSE73_MODE(unit, port)) {
   2775             SOC_IF_ERROR_RETURN
   2776                 (READ_HL65_AN_IEEE0BLK_AN_IEEESTATUS1r(unit, pc, &data16));
   2777             if (data16 & MII_STAT_AN_DONE) {
   2778                 SOC_IF_ERROR_RETURN
   2779                     (_phy_hl65_c73_adv_remote_get(unit, port, ability));
   2780             }
   2781         }
   2782     } else {
   2783         /* Simply return local abilities */
   2784         phy_hl65_ability_advert_get(unit, port, ability);
   2785     }
   2786  
   2787     LOG_INFO(BSL_LS_SOC_PHY,
   2788              (BSL_META_U(unit,
   2789                          "phy_hl65_ability_remote_get:unit=%d p=%d pause=%08x sp=%08x\n"),
   2790               unit, port, ability->pause, ability->speed_full_duplex));
   2791 
   2792     return SOC_E_NONE;
   2793 }
   2794 
   2795 /*
   2796  * Function:
   2797  *      phy_hl65_lb_set
   2798  * Purpose:
   2799  *      Put hc/FusionCore in PHY loopback
   2800  * Parameters:
   2801  *      unit - StrataSwitch unit #.
   2802  *      port - StrataSwitch port #. 
   2803  *      enable - binary value for on/off (1/0)
   2804  * Returns:     
   2805  *      SOC_E_NONE
   2806  */
   2807 
   2808 STATIC int
   2809 phy_hl65_lb_set(int unit, soc_port_t port, int enable)
   2810 {
   2811     phy_ctrl_t *pc;
   2812     uint16 serdes_id0;
   2813 
   2814     pc = INT_PHY_SW_STATE(unit, port);
   2815     SOC_IF_ERROR_RETURN
   2816         (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
   2817 
   2818     serdes_id0 = serdes_id0 & (TEST_SERDESID0_REV_NUMBER_MASK |
   2819                                 TEST_SERDESID0_REV_LETTER_MASK);
   2820 
   2821     if ((serdes_id0 == HL_SERDES_ID0_REVID_A0) ||
   2822         (serdes_id0 == HL_SERDES_ID0_REVID_A1) ||
   2823         (serdes_id0 == HL_SERDES_ID0_REVID_B0)) {
   2824         SOC_IF_ERROR_RETURN(MODIFY_HL65_DSC2BB_SM_CTRL0r(unit, pc, 
   2825                        enable? 0x0: DSC2BB_SM_CTRL0_TUNING_SM_EN_MASK,
   2826                        DSC2BB_SM_CTRL0_TUNING_SM_EN_MASK));
   2827     }
   2828 
   2829     if (PHY_HC65_FABRIC_MODE(unit, port)) {
   2830         uint16 lane_mask = 1 << pc->lane_num;
   2831         
   2832         if (enable) {
   2833             /* Set global and individual loopback control */
   2834             SOC_IF_ERROR_RETURN
   2835                 (MODIFY_HL65_IEEE0BLK_MIICNTLr(unit, pc, MII_CTRL_LE,
   2836                                                MII_CTRL_LE));
   2837 
   2838             SOC_IF_ERROR_RETURN
   2839                 (MODIFY_HL65_XGXSBLK1_LANECTRL2r(unit, pc, lane_mask, lane_mask));
   2840         } else {
   2841             /* Clear global and individual loopback control */
   2842             SOC_IF_ERROR_RETURN
   2843                 (MODIFY_HL65_IEEE0BLK_MIICNTLr(unit, pc, 0,
   2844                                                MII_CTRL_LE));
   2845             SOC_IF_ERROR_RETURN
   2846                 (MODIFY_HL65_XGXSBLK1_LANECTRL2r(unit, pc, 0, lane_mask));
   2847         }
   2848     } else if (PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   2849         if (enable) {
   2850             SOC_IF_ERROR_RETURN
   2851                 (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, 
   2852                                                   MII_CTRL_LE,
   2853                                                   MII_CTRL_AE | MII_CTRL_RAN |
   2854                                                   MII_CTRL_LE));
   2855             if(!IS_GE_PORT(unit, port)) {
   2856                 /* in case it is in dxgxs mode */
   2857                 SOC_IF_ERROR_RETURN
   2858                     (MODIFY_HL65_DTE_IEEE0BLK_DTE_IEEECONTROL1r(unit, pc, 
   2859                                   MII_CTRL_LE,MII_CTRL_LE));
   2860             }
   2861         } else {
   2862             SOC_IF_ERROR_RETURN
   2863                 (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, 
   2864                                                   0,
   2865                                                   MII_CTRL_LE));
   2866             if(!IS_GE_PORT(unit, port)) {
   2867                 /* in case it is in dxgxs mode */
   2868                 SOC_IF_ERROR_RETURN
   2869                     (MODIFY_HL65_DTE_IEEE0BLK_DTE_IEEECONTROL1r(unit, pc, 
   2870                                          0,MII_CTRL_LE));
   2871             }
   2872         }
   2873     } else {
   2874         uint16      misc_ctrl;
   2875         uint16      lb_bit;
   2876         uint16      lb_mask;
   2877         
   2878         if (enable) {
   2879             /* Disable TX serializer output in gloopback mode. Link partner will
   2880              * show link off
   2881              */
   2882             SOC_IF_ERROR_RETURN
   2883                     (MODIFY_HL65_TXB_ANATXACONTROL0r(unit, pc, 0x200,0x200));
   2884             
   2885         } else {
   2886             SOC_IF_ERROR_RETURN
   2887                     (MODIFY_HL65_TXB_ANATXACONTROL0r(unit, pc, 0x000,0x200));
   2888         }
   2889         /* Configure Loopback in XAUI */
   2890         SOC_IF_ERROR_RETURN
   2891             (READ_HL65_XGXSBLK0_MISCCONTROL1r(unit, pc, &misc_ctrl));
   2892         if (misc_ctrl & XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_MASK) {
   2893               /* PCS */
   2894               lb_bit  = (enable) ? IEEE0BLK_MIICNTL_GLOOPBACK_MASK : 0;
   2895               lb_mask = IEEE0BLK_MIICNTL_GLOOPBACK_MASK;
   2896               SOC_IF_ERROR_RETURN
   2897                   (MODIFY_HL65_DTE_IEEE0BLK_DTE_IEEECONTROL1r(unit, pc, 
   2898                                                            lb_bit, lb_mask));
   2899         } else if (misc_ctrl & XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_MASK) {
   2900               /* PMA/PMD */
   2901               lb_bit  = (enable) ? 1 : 0;
   2902               lb_mask = 1;
   2903               SOC_IF_ERROR_RETURN
   2904                   (MODIFY_HL65_PMD_IEEE0BLK_PMD_IEEECONTROL1r(unit, pc, 
   2905                                                            lb_bit, lb_mask));
   2906         } else {
   2907               /* PHY XS, DTE XS */
   2908               lb_bit  = (enable) ? IEEE0BLK_MIICNTL_GLOOPBACK_MASK : 0;
   2909               lb_mask = IEEE0BLK_MIICNTL_GLOOPBACK_MASK;
   2910               SOC_IF_ERROR_RETURN
   2911                   (MODIFY_HL65_DTE_IEEE0BLK_DTE_IEEECONTROL1r(unit, pc, 
   2912                                                            lb_bit, lb_mask));
   2913         }
   2914 
   2915         SOC_IF_ERROR_RETURN
   2916             (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, 
   2917                                               (enable) ?  MII_CTRL_LE : 0,
   2918                                               MII_CTRL_LE));
   2919     }
   2920 
   2921     return SOC_E_NONE;
   2922 }
   2923 
   2924 /*
   2925  * Function:
   2926  *      phy_hl65_lb_get
   2927  * Purpose:
   2928  *      Get hc/FusionCore PHY loopback state
   2929  * Parameters:
   2930  *      unit - StrataSwitch unit #.
   2931  *      port - StrataSwitch port #. 
   2932  *      enable - address of location to store binary value for on/off (1/0)
   2933  * Returns:     
   2934  *      SOC_E_NONE
   2935  */
   2936 
   2937 STATIC int
   2938 phy_hl65_lb_get(int unit, soc_port_t port, int *enable)
   2939 {
   2940     phy_ctrl_t *pc;
   2941     uint16      mii_ctrl;
   2942  
   2943     pc = INT_PHY_SW_STATE(unit, port);
   2944 
   2945    if (PHY_HC65_FABRIC_MODE(unit, port)) {
   2946         uint16 data;
   2947         uint16 lane_mask = 1 << pc->lane_num;
   2948 
   2949         SOC_IF_ERROR_RETURN
   2950             (READ_HL65_XGXSBLK1_LANECTRL2r(unit, pc, &data));
   2951  
   2952         *enable = ((data & lane_mask) == lane_mask);
   2953         LOG_INFO(BSL_LS_SOC_PHY,
   2954                  (BSL_META_U(unit,
   2955                              "phy_hc65_loopback_get: "
   2956                              "u=%d p=%d lb=%d\n"), unit, port, *enable));
   2957 
   2958     } else {
   2959         SOC_IF_ERROR_RETURN
   2960             (READ_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl));
   2961 
   2962         *enable = mii_ctrl & MII_CTRL_LE;
   2963     }
   2964     return SOC_E_NONE;
   2965 }
   2966 
   2967 STATIC int
   2968 phy_hl65_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   2969 {
   2970     COMPILER_REFERENCE(unit);
   2971     COMPILER_REFERENCE(port);
   2972     COMPILER_REFERENCE(pif);
   2973 
   2974     return SOC_E_NONE;
   2975 }
   2976 
   2977 STATIC int
   2978 phy_hl65_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   2979 {
   2980     COMPILER_REFERENCE(unit);
   2981     COMPILER_REFERENCE(port);
   2982 
   2983     if (PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   2984         *pif = SOC_PORT_IF_SGMII;
   2985     } else {
   2986         *pif = SOC_PORT_IF_XGMII;
   2987     }
   2988     return SOC_E_NONE;
   2989 }
   2990 
   2991 STATIC int
   2992 phy_hl65_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   2993 {
   2994     phy_ctrl_t *pc;
   2995     uint16 id_rev;
   2996 
   2997     if (NULL == ability) {
   2998         return SOC_E_PARAM;
   2999     }
   3000 
   3001     pc = INT_PHY_SW_STATE(unit, port);
   3002 
   3003     sal_memset(ability, 0, sizeof(*ability));
   3004 
   3005     if (PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   3006         /* dxgxs mode */
   3007         if (IS_HG_PORT(unit, port)) {
   3008             ability->speed_full_duplex  = SOC_PA_SPEED_10GB |
   3009                                            SOC_PA_SPEED_12GB;
   3010             ability->pause     = 0;
   3011             ability->interface = SOC_PA_INTF_XGMII;
   3012             ability->medium    = SOC_PA_MEDIUM_FIBER;
   3013             ability->loopback  = SOC_PA_LB_PHY;
   3014             ability->flags     = 0;
   3015         } else {
   3016             ability->speed_full_duplex  = SOC_PA_SPEED_1000MB;
   3017             if (IS_XE_PORT(unit,port)) {
   3018                 ability->speed_full_duplex  += SOC_PA_SPEED_10GB;
   3019             }
   3020 
   3021             ability->speed_half_duplex = SOC_PA_ABILITY_NONE;
   3022             if (PHY_FIBER_MODE(unit, port))   {
   3023                 ability->speed_full_duplex  |= SOC_PA_SPEED_2500MB;
   3024                 SOC_IF_ERROR_RETURN
   3025                     (READ_HL65_TEST_SERDESID0r(unit,pc,&id_rev));
   3026                 if (id_rev & TEST_SERDESID0_REV_LETTER_MASK) {
   3027                     ability->speed_full_duplex  |= SOC_PA_SPEED_100MB;
   3028                     ability->speed_half_duplex  = SOC_PA_SPEED_100MB;
   3029                 }
   3030             } else {
   3031                 ability->speed_half_duplex  = SOC_PA_SPEED_10MB |
   3032                                               SOC_PA_SPEED_100MB;
   3033                 ability->speed_full_duplex  |= SOC_PA_SPEED_10MB |
   3034                                            SOC_PA_SPEED_100MB;
   3035             }
   3036 
   3037             ability->interface = SOC_PA_INTF_GMII | SOC_PA_INTF_SGMII;
   3038             ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   3039             ability->medium    = SOC_PA_MEDIUM_FIBER;
   3040             ability->loopback  = SOC_PA_LB_PHY;
   3041             ability->flags     = SOC_PA_AUTONEG;
   3042        }
   3043     } else {
   3044 
   3045         if ( PHY_EXTERNAL_MODE(unit, port) ) {
   3046             ability->speed_half_duplex  = SOC_PA_SPEED_100MB | 
   3047                                           SOC_PA_SPEED_10MB;
   3048             ability->speed_full_duplex  = SOC_PA_SPEED_2500MB | 
   3049                                           SOC_PA_SPEED_1000MB |
   3050                                           SOC_PA_SPEED_100MB | 
   3051                                           SOC_PA_SPEED_10MB;
   3052         } else {
   3053             ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   3054             ability->speed_full_duplex  = SOC_PA_SPEED_1000MB | 
   3055                                           SOC_PA_SPEED_2500MB;
   3056         }
   3057 
   3058         switch(pc->speed_max) {
   3059             case 25000:
   3060                 ability->speed_full_duplex |= SOC_PA_SPEED_25GB;
   3061                 /* fall through */
   3062             case 21000:
   3063                 ability->speed_full_duplex |= SOC_PA_SPEED_21GB;
   3064                 /* fall through */
   3065             case 20000:
   3066                 ability->speed_full_duplex |= SOC_PA_SPEED_20GB;
   3067                 /* fall through */
   3068             case 16000:
   3069                 ability->speed_full_duplex |= SOC_PA_SPEED_16GB; 
   3070                 /* fall through */
   3071             case 13000:
   3072                 ability->speed_full_duplex |= SOC_PA_SPEED_13GB;
   3073                 /* fall through */
   3074             case 12000:
   3075                 ability->speed_full_duplex |= SOC_PA_SPEED_12GB;
   3076                 /* fall through */
   3077             default:
   3078                 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 
   3079         }
   3080         ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   3081         ability->interface = SOC_PA_INTF_XGMII;
   3082         ability->medium    = SOC_PA_MEDIUM_FIBER;
   3083         ability->loopback  = SOC_PA_LB_PHY;
   3084         ability->flags     = SOC_PA_AUTONEG;
   3085     }
   3086 
   3087     return (SOC_E_NONE);
   3088 }
   3089 
   3090 
   3091 STATIC int
   3092 _phy_hl65_control_scrambler_set(int unit, soc_port_t port, uint32 value)
   3093 {
   3094     uint16      data;
   3095     phy_ctrl_t *pc;
   3096     int         rv = SOC_E_NONE;
   3097 
   3098     if (SOC_IS_RELOADING(unit)) {
   3099         return SOC_E_NONE;
   3100     }
   3101 
   3102     pc = INT_PHY_SW_STATE(unit, port);
   3103     if (PHY_HC65_FABRIC_MODE(unit, port)) {
   3104         
   3105         /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, 0x833c, &uData);*/
   3106         SOC_IF_ERROR_RETURN
   3107             (READ_HL65_DIGITAL4_MISC3r(unit, pc, &data));
   3108    
   3109         if (value) { 
   3110             data |= (DIGITAL4_MISC3_SCR_EN_PER_LANE_BITS <<  
   3111                      DIGITAL4_MISC3_SCR_EN_PER_LANE_SHIFT);
   3112         } else {
   3113             data &= ~(DIGITAL4_MISC3_SCR_EN_PER_LANE_BITS <<  
   3114                       DIGITAL4_MISC3_SCR_EN_PER_LANE_SHIFT);
   3115         }
   3116 
   3117         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, 0x833c, uData);*/
   3118         SOC_IF_ERROR_RETURN
   3119             (WRITE_HL65_DIGITAL4_MISC3r(unit, pc, data));
   3120 
   3121     } else {
   3122         rv = SOC_E_UNAVAIL;
   3123     }
   3124     return rv;
   3125 }
   3126 
   3127 STATIC int
   3128 _phy_hl65_control_scrambler_get(int unit, soc_port_t port, uint32 *value)
   3129 {
   3130     uint16      data;
   3131     phy_ctrl_t *pc;
   3132     int         rv = SOC_E_NONE;
   3133 
   3134     pc = INT_PHY_SW_STATE(unit, port);
   3135     if (PHY_HC65_FABRIC_MODE(unit, port)) {
   3136         
   3137         SOC_IF_ERROR_RETURN
   3138             (READ_HL65_DIGITAL4_MISC3r(unit, pc, &data));
   3139    
   3140 	*value = ((data & DIGITAL4_MISC3_SCR_EN_PER_LANE_MASK) == 0x100);
   3141 
   3142     } else {
   3143         rv = SOC_E_UNAVAIL;
   3144     }
   3145     return rv;
   3146 }
   3147 
   3148 STATIC int
   3149 _phy_hl65_control_encoding_set(int unit, soc_port_t port, uint32 value)
   3150 {
   3151     uint16      data;
   3152     phy_ctrl_t *pc;
   3153     int         rv = SOC_E_NONE;
   3154 
   3155     if (SOC_IS_RELOADING(unit)) {
   3156         return SOC_E_NONE;
   3157     }
   3158 
   3159     pc = INT_PHY_SW_STATE(unit, port);
   3160     if (PHY_HC65_FABRIC_MODE(unit, port)) {
   3161         switch (value) {
   3162         case phyControlEncoding8b10b:
   3163 
   3164             /* 
   3165              * 8b10b only, disable 64/66 
   3166              * soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, 0x8015, &uData); 
   3167              */
   3168             SOC_IF_ERROR_RETURN
   3169                 (READ_HL65_XGXSBLK1_LANECTRL0r(unit, pc, &data));
   3170 
   3171             data &= ~(1 << (pc->lane_num + 12));	    
   3172             /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8015, uData); */
   3173             SOC_IF_ERROR_RETURN
   3174                 (WRITE_HL65_XGXSBLK1_LANECTRL0r(unit, pc, data));
   3175 
   3176             /* 
   3177              * Force the sync character to the lower byte of the parallel 
   3178              * interface 
   3179              * uRegAddr = 0x80b9 + (uLaneAddr * 0x10);
   3180              * soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, uRegAddr, &uData);
   3181              */
   3182             SOC_IF_ERROR_RETURN
   3183                 (HL65_REG_READ(unit, pc, 0x0, 0x80b9 + (0x10 * pc->lane_num),
   3184                                &data));
   3185             data = data | 0x0020;
   3186 
   3187             /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, uRegAddr, uData); */
   3188             SOC_IF_ERROR_RETURN
   3189                 (HL65_REG_WRITE(unit, pc, 0x0, 0x80b9 + (0x10 * pc->lane_num),
   3190                                 data));
   3191             break;
   3192 
   3193         case phyControlEncoding64b66b:
   3194 
   3195             /* 
   3196              * Force the sync character to the upper byte of the parallel 
   3197              * interface 
   3198              * uRegAddr = 0x80b9 + (uLaneAddr * 0x10);
   3199              * soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, uRegAddr, &uData);
   3200              */
   3201             SOC_IF_ERROR_RETURN
   3202                 (HL65_REG_READ(unit, pc, 0x0, 0x80b9 + (0x10 * pc->lane_num),
   3203                                &data));
   3204 
   3205             data = data & ~0x0020;
   3206 
   3207             /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, uRegAddr, uData); */
   3208             SOC_IF_ERROR_RETURN
   3209                 (HL65_REG_WRITE(unit, pc, 0x0, 0x80b9 + (0x10 * pc->lane_num),
   3210                                 data));
   3211 
   3212             /* 
   3213              * enable 64b66b 
   3214              * socd c_bm9600_mdio_hc_read(unit, uPhyAddr, 0, 0x8015, &uData);
   3215              */
   3216             SOC_IF_ERROR_RETURN
   3217                 (READ_HL65_XGXSBLK1_LANECTRL0r(unit, pc, &data));
   3218 
   3219             data |= 1 << (pc->lane_num + 12);	    
   3220 
   3221             /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8015, uData); */
   3222             SOC_IF_ERROR_RETURN
   3223                 (WRITE_HL65_XGXSBLK1_LANECTRL0r(unit, pc, data));
   3224 
   3225             break;
   3226 
   3227         default:
   3228             rv = SOC_E_UNAVAIL;
   3229         } 
   3230     } else {
   3231         rv = SOC_E_UNAVAIL;
   3232     }
   3233 
   3234     return rv;
   3235 }
   3236 
   3237 #define PHY_HL65_LANEPRBS_LANE_SHIFT   4
   3238 
   3239 STATIC int
   3240 _phy_hl65_control_prbs_polynomial_set(int unit, soc_port_t port, uint32 value)
   3241 {
   3242     uint16      data = 0;
   3243 
   3244     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3245         
   3246     SOC_IF_ERROR_RETURN
   3247         (READ_HL65_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   3248 
   3249     if (PHY_HC65_FABRIC_MODE(unit, pc->port)) {
   3250       uint32      prbs_lane_mask = 0;
   3251       prbs_lane_mask = 0x3 << (PHY_HL65_LANEPRBS_LANE_SHIFT * pc->lane_num);
   3252       data &= ~prbs_lane_mask;
   3253       data |= value << (PHY_HL65_LANEPRBS_LANE_SHIFT * pc->lane_num);
   3254     } else {
   3255         data &= ~(XGXSBLK1_LANEPRBS_PRBS_ORDER0_MASK |
   3256                   XGXSBLK1_LANEPRBS_PRBS_ORDER1_MASK |
   3257                   XGXSBLK1_LANEPRBS_PRBS_ORDER2_MASK |
   3258                   XGXSBLK1_LANEPRBS_PRBS_ORDER3_MASK);
   3259 
   3260         data |= ((value << XGXSBLK1_LANEPRBS_PRBS_ORDER0_SHIFT) |
   3261                  (value << XGXSBLK1_LANEPRBS_PRBS_ORDER1_SHIFT) |
   3262                  (value << XGXSBLK1_LANEPRBS_PRBS_ORDER2_SHIFT) |
   3263                  (value << XGXSBLK1_LANEPRBS_PRBS_ORDER3_SHIFT));
   3264     }
   3265 
   3266     SOC_IF_ERROR_RETURN
   3267       (WRITE_HL65_XGXSBLK1_LANEPRBSr(unit, pc, data));
   3268 
   3269     return SOC_E_NONE;
   3270 }
   3271 
   3272 STATIC int
   3273 _phy_hl65_control_prbs_polynomial_get(int unit, soc_port_t port, uint32 *value)
   3274 {
   3275     uint16      data;
   3276     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);;
   3277 
   3278     /*  soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, 0x8019, &uData);*/
   3279     SOC_IF_ERROR_RETURN
   3280         (READ_HL65_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   3281 
   3282     if (PHY_HC65_FABRIC_MODE(unit, pc->port)) {
   3283       /* Extract prbs polynomial setting from register */
   3284       *value = ((data >> (XGXSBLK1_LANEPRBS_PRBS_ORDER1_SHIFT * pc->lane_num)) &
   3285 	      XGXSBLK1_LANEPRBS_PRBS_ORDER0_MASK);
   3286     } else {
   3287         *value = ((data & 0x0003) | ((data >> 4) & 0x0003) |
   3288                 ((data >> 8) & 0x0003) | ((data >> 12) & 0x0003));
   3289     }  
   3290 
   3291     return SOC_E_NONE;
   3292 }
   3293 
   3294 
   3295 STATIC int
   3296 _phy_hl65_control_prbs_tx_invert_data_set(int unit, soc_port_t port, uint32 value)
   3297 {
   3298     uint16      data = 0;
   3299     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3300 
   3301     SOC_IF_ERROR_RETURN
   3302         (READ_HL65_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   3303 
   3304     if (PHY_HC65_FABRIC_MODE(unit, pc->port)) {
   3305       uint32      lane_mask = 0;
   3306       lane_mask = 0x4 << (PHY_HL65_LANEPRBS_LANE_SHIFT * pc->lane_num);
   3307       data &= ~lane_mask;
   3308       data |= value << (PHY_HL65_LANEPRBS_LANE_SHIFT * pc->lane_num);
   3309     } else {
   3310         data &= ~(XGXSBLK1_LANEPRBS_PRBS_INV0_MASK |
   3311                   XGXSBLK1_LANEPRBS_PRBS_INV1_MASK |
   3312                   XGXSBLK1_LANEPRBS_PRBS_INV2_MASK |
   3313                   XGXSBLK1_LANEPRBS_PRBS_INV3_MASK);
   3314 
   3315         value &= (1 << XGXSBLK1_LANEPRBS_PRBS_INV0_BITS) - 1;
   3316         data |= ((value << XGXSBLK1_LANEPRBS_PRBS_INV0_SHIFT) |
   3317                  (value << XGXSBLK1_LANEPRBS_PRBS_INV1_SHIFT) |
   3318                  (value << XGXSBLK1_LANEPRBS_PRBS_INV2_SHIFT) |
   3319                  (value << XGXSBLK1_LANEPRBS_PRBS_INV3_SHIFT));
   3320     }
   3321 
   3322     SOC_IF_ERROR_RETURN
   3323       (WRITE_HL65_XGXSBLK1_LANEPRBSr(unit, pc, data));
   3324 
   3325     return SOC_E_NONE;
   3326 }
   3327 
   3328 STATIC int
   3329 _phy_hl65_control_prbs_tx_invert_data_get(int unit, soc_port_t port, uint32 *value)
   3330 {
   3331     uint16      data;
   3332     uint16       inv_shifter = 0;
   3333     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3334 
   3335     /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, 0x8019, &uData) */
   3336     SOC_IF_ERROR_RETURN
   3337         (READ_HL65_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   3338     inv_shifter = (XGXSBLK1_LANEPRBS_PRBS_ORDER1_SHIFT * pc->lane_num) +
   3339                     XGXSBLK1_LANEPRBS_PRBS_INV0_SHIFT;
   3340     data &= (1 << inv_shifter);
   3341     *value = (data) ?  1 : 0;
   3342     
   3343     return SOC_E_NONE;
   3344 }
   3345 
   3346 STATIC int
   3347 _phy_hl65_control_fabric_prbs_tx_enable_set(int unit, soc_port_t port, 
   3348                                             uint32 value)
   3349 {
   3350     uint16      data;
   3351     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3352     uint32      lane_mask = 1 << (PHY_HL65_LANEPRBS_LANE_SHIFT * pc->lane_num);
   3353 
   3354     /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, 0x8019, &uData) */
   3355     SOC_IF_ERROR_RETURN
   3356         (READ_HL65_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   3357     
   3358     if (value) {
   3359         data |= lane_mask << XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT;
   3360     } else {
   3361         data &= ~(lane_mask << XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT);
   3362     }
   3363     /* write back updated configuration */
   3364     /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8019, uData) */ 
   3365     SOC_IF_ERROR_RETURN
   3366         (WRITE_HL65_XGXSBLK1_LANEPRBSr(unit, pc, data));
   3367 
   3368     SOC_IF_ERROR_RETURN(
   3369         phy_hl65_lb_set(unit, port, (value & 0x8000) ? 1 : 0));
   3370 
   3371     return SOC_E_NONE;
   3372 }
   3373 
   3374 STATIC int
   3375 _phy_hl65_control_xgxs_prbs_tx_enable_set(int unit, soc_port_t port,
   3376                                           uint32 value)
   3377 {
   3378     uint16      data;
   3379     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3380     uint16      pll_mode;
   3381 
   3382     if (value) {
   3383         /* Assume that the core has already been forced to the desired speed */
   3384         /* Get the current PLL operating mode */
   3385         SOC_IF_ERROR_RETURN(READ_HL65_TXPLL_ANAPLLSTATUSr(unit, pc, &data));
   3386         pll_mode = data & TXPLL_ANAPLLSTATUS_PLL_MODE_AFE_MASK;
   3387 
   3388         /* Change to independent lane mode */
   3389         SOC_IF_ERROR_RETURN(READ_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, &data));
   3390         data &= ~(XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK |
   3391                   XGXSBLK0_XGXSCONTROL_MODE_10G_MASK);
   3392         data |= ((XGXSBLK0_XGXSCONTROL_MODE_10G_Indlanes <<
   3393                     XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) |
   3394                   XGXSBLK0_XGXSCONTROL_MDIO_CONT_EN_MASK);
   3395         SOC_IF_ERROR_RETURN(WRITE_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, data));
   3396 
   3397         /* Set appropriate data width mode */
   3398         if (data & XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK) {
   3399             /* Half rate mode */
   3400             SOC_IF_ERROR_RETURN(WRITE_HL65_XGXSBLK1_LANECTRL1r(unit, pc,
   3401                                                                0x5555));
   3402         } else {
   3403             /* Full rate mode */
   3404             SOC_IF_ERROR_RETURN(WRITE_HL65_XGXSBLK1_LANECTRL1r(unit, pc,
   3405                                                                0xffff));
   3406         }
   3407 
   3408         /* Force the VCO based on the previously read mode */
   3409         SOC_IF_ERROR_RETURN(READ_HL65_DIGITAL_MISC1r(unit, pc, &data));
   3410         data &= ~(DIGITAL_MISC1_FORCE_PLL_MODE_AFE_MASK |
   3411                   DIGITAL_MISC1_FORCE_LN_MODE_MASK |
   3412                   DIGITAL_MISC1_FORCE_SPEED_MASK);
   3413         data |= (DIGITAL_MISC1_FORCE_PLL_MODE_AFE_SEL_MASK |
   3414                  (pll_mode << DIGITAL_MISC1_FORCE_PLL_MODE_AFE_SHIFT) |
   3415                  DIGITAL_MISC1_FORCE_LN_MODE_MASK);
   3416         SOC_IF_ERROR_RETURN(WRITE_HL65_DIGITAL_MISC1r(unit, pc, data));
   3417 
   3418         /* Disable CL36 PCS */
   3419         SOC_IF_ERROR_RETURN(READ_HL65_XGXSBLK1_LANECTRL0r(unit, pc, &data));
   3420         data &= ~(XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK |
   3421                   XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK);
   3422         SOC_IF_ERROR_RETURN(WRITE_HL65_XGXSBLK1_LANECTRL0r(unit, pc, data));
   3423 
   3424         /* Disable comma detect, error detect */
   3425         SOC_IF_ERROR_RETURN(READ_HL65_XGXSBLK1_LANECTRL2r(unit, pc, &data));
   3426         data &= ~(XGXSBLK1_LANECTRL2_CDET_EN1G_MASK |
   3427                   XGXSBLK1_LANECTRL2_EDEN1G_MASK);
   3428         SOC_IF_ERROR_RETURN(WRITE_HL65_XGXSBLK1_LANECTRL2r(unit, pc, data));
   3429 
   3430         /* Set loopback (if requested) */
   3431         if (value & 0x8000) {
   3432             SOC_IF_ERROR_RETURN(WRITE_HL65_XGXSBLK1_LANECTRL2r(unit, pc,
   3433                             XGXSBLK1_LANECTRL2_GLOOP1G_MASK));
   3434         }
   3435 
   3436         /* Enable PRBS transmit function */
   3437         SOC_IF_ERROR_RETURN(READ_HL65_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   3438         data |= (XGXSBLK1_LANEPRBS_PRBS_EN0_MASK |
   3439                  XGXSBLK1_LANEPRBS_PRBS_EN1_MASK |
   3440                  XGXSBLK1_LANEPRBS_PRBS_EN2_MASK |
   3441                  XGXSBLK1_LANEPRBS_PRBS_EN3_MASK);
   3442         SOC_IF_ERROR_RETURN(WRITE_HL65_XGXSBLK1_LANEPRBSr(unit, pc, data));
   3443 
   3444         /* Set receiver status to PRBS */
   3445         SOC_IF_ERROR_RETURN(READ_HL65_RXB_ANARXCONTROLr(unit, pc, &data));
   3446         data &= ~RXB_ANARXCONTROL_STATUS_SEL_MASK;
   3447         data |= 0x7; /* PRBS status */
   3448         SOC_IF_ERROR_RETURN(WRITE_HL65_RXB_ANARXCONTROLr(unit, pc, data));
   3449 
   3450         /* Start the PLL sequencer */
   3451         SOC_IF_ERROR_RETURN(READ_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, &data));
   3452         data |= XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK;
   3453         SOC_IF_ERROR_RETURN(WRITE_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc, data));
   3454 
   3455         /* Delay a while */
   3456         sal_usleep(250000);
   3457     } else {
   3458         /* Restore port */
   3459         return phy_hl65_init(unit, port);
   3460     }
   3461     return SOC_E_NONE;
   3462 }
   3463 
   3464 STATIC int
   3465 _phy_hl65_control_prbs_tx_enable_set(int unit, soc_port_t port, uint32 value)
   3466 {
   3467     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3468 
   3469     if (PHY_HC65_FABRIC_MODE(unit, pc->port)) {
   3470         SOC_IF_ERROR_RETURN(
   3471             _phy_hl65_control_fabric_prbs_tx_enable_set(unit, port, value));
   3472     } else {
   3473         SOC_IF_ERROR_RETURN(
   3474             _phy_hl65_control_xgxs_prbs_tx_enable_set(unit, port, value));
   3475     }
   3476 
   3477     return SOC_E_NONE;
   3478 }
   3479 
   3480 
   3481 STATIC int
   3482 _phy_hl65_control_prbs_tx_rx_enable_get(int unit, soc_port_t port, 
   3483                                         uint32 *value)
   3484 {
   3485     uint16      data;
   3486     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);;
   3487 
   3488     /*
   3489      * Hypercore PRBS - note that in the Hypercore there is only 1 enable 
   3490      * for both TX/RX 
   3491      */
   3492     /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, 0x8019, &uData) */
   3493     SOC_IF_ERROR_RETURN
   3494         (READ_HL65_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   3495 
   3496     data = data & ((1 << (XGXSBLK1_LANEPRBS_PRBS_ORDER1_SHIFT * pc->lane_num))
   3497                    << XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT);
   3498     
   3499     *value = (data) ?  1 : 0;
   3500   
   3501     return SOC_E_NONE;
   3502 }
   3503 
   3504 STATIC int
   3505 _phy_hl65_control_prbs_tx_enable_get(int unit, soc_port_t port, uint32 *value)
   3506 {
   3507     return _phy_hl65_control_prbs_tx_rx_enable_get(unit, port, value);
   3508 }
   3509 
   3510 STATIC int
   3511 _phy_hl65_control_prbs_rx_enable_set(int unit, soc_port_t port, uint32 value)
   3512 {
   3513     uint16      data;
   3514     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3515     uint32      lane_mask = 1 << (PHY_HL65_LANEPRBS_LANE_SHIFT * pc->lane_num);
   3516 
   3517     /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, 0x8019, &uData) */
   3518     SOC_IF_ERROR_RETURN
   3519         (READ_HL65_XGXSBLK1_LANEPRBSr(unit, pc, &data));
   3520     
   3521     /* if (value) {
   3522      *	    uData |= uLaneMask << BM9600_HYPERCORE_8019_PRBS_ENABLE_SHIFT;
   3523      * } else {
   3524      *    uData &= ~(uLaneMask << BM9600_HYPERCORE_8019_PRBS_ENABLE_SHIFT);
   3525      * }
   3526      */
   3527     if (value) {
   3528         data |= lane_mask <<  XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT;
   3529     }  else {
   3530         data &= ~(lane_mask << XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT);
   3531     }
   3532     
   3533     /* write back updated configuration */
   3534     /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8019, uData) */
   3535     SOC_IF_ERROR_RETURN
   3536         (WRITE_HL65_XGXSBLK1_LANEPRBSr(unit, pc, data));
   3537     
   3538     /* Set up status collection */
   3539     /* uPrbsRxControlReg = 0x80b1;
   3540      * uPrbsRxControlReg += uLaneAddr * 0x10;
   3541      * soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, uPrbsRxControlReg, &uData)
   3542      */
   3543     SOC_IF_ERROR_RETURN
   3544         (HL65_REG_READ(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), &data));
   3545     
   3546     /* if (value) {
   3547      *   uData &= ~BM9600_HYPERCORE_80B1_STATUS_MASK;
   3548      *   uData |= BM9600_HYPERCORE_80B1_PRBS_STATUS_VALUE;
   3549      * } else {
   3550      *   uData &= ~BM9600_HYPERCORE_80B1_STATUS_MASK;
   3551      *   uData &= ~BM9600_HYPERCORE_80B1_PRBS_STATUS_VALUE;
   3552      * }
   3553      */
   3554     data &= ~RX0_ANARXCONTROL_STATUS_SEL_MASK;
   3555     if (value) {
   3556         data |= RX0_ANARXCONTROL_STATUS_SEL_prbsStatus;
   3557     } else {
   3558         data &= ~RX0_ANARXCONTROL_STATUS_SEL_prbsStatus;
   3559     }
   3560     
   3561     /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, uPrbsRxControlReg, uData) */
   3562     SOC_IF_ERROR_RETURN
   3563         (HL65_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), data));
   3564 
   3565     return SOC_E_NONE;
   3566 }
   3567 
   3568 STATIC int
   3569 _phy_hl65_control_prbs_rx_enable_get(int unit, soc_port_t port, uint32 *value)
   3570 {
   3571     return _phy_hl65_control_prbs_tx_rx_enable_get(unit, port, value);
   3572 }
   3573 
   3574 /*
   3575  * Returns value 
   3576  *      ==  0: PRBS receive is in sync
   3577  *      == -1: PRBS receive never got into sync
   3578  *      ==  n: number of errors
   3579  */
   3580 STATIC int
   3581 _phy_hl65_control_fabric_prbs_rx_status_get(int unit, soc_port_t port, 
   3582                                             uint32 *value)
   3583 {
   3584     uint16      data;
   3585     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);;
   3586 
   3587     /* Get status */
   3588     /* uPrbsRxControlReg = 0x80b0;
   3589      * uPrbsRxControlReg += uLaneAddr * 0x10;
   3590      * soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, uPrbsRxControlReg, &uData);
   3591      */
   3592     SOC_IF_ERROR_RETURN
   3593         (HL65_REG_READ(unit, pc, 0x0, 0x80b0 + (0x10 * pc->lane_num), &data));
   3594 
   3595 
   3596     if (data == (RX0_ANARXSTATUS_PRBS_STATUS_PRBS_LOCK_BITS  <<
   3597                  RX0_ANARXSTATUS_PRBS_STATUS_PRBS_LOCK_SHIFT)) {
   3598         /* PRBS is in sync */
   3599         *value = 0;
   3600     } else if (data == 0) {
   3601         /* PRBS not in sync */
   3602         *value = -1;
   3603     } else { 
   3604         /* Get errors */
   3605         *value = data & RX0_ANARXSTATUS_PRBS_STATUS_PTBS_ERRORS_MASK;
   3606     }
   3607 
   3608     return SOC_E_NONE;
   3609 }
   3610 /*
   3611  * Returns value 
   3612  *      ==  0: PRBS receive is in sync
   3613  *      == -1: PRBS receive never got into sync
   3614  *      ==  n: number of errors
   3615  */
   3616 STATIC int
   3617 _phy_hl65_control_xgxs_prbs_rx_status_get(int unit, soc_port_t port, 
   3618                                           uint32 *value)
   3619 {
   3620     int         lane;
   3621     uint16      data;
   3622     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);;
   3623 
   3624     /* JOE */
   3625     /* Get status for all 4 lanes and check for sync
   3626      * 0x80b0, 0x80c0, 0x80d0, 0x80e0 
   3627      */
   3628     *value = 0;
   3629     for (lane = 0; lane < 4; lane++) {
   3630         SOC_IF_ERROR_RETURN
   3631             (HL65_REG_READ(unit, pc, 0x0, 0x80b0 + (0x10 * lane), &data));
   3632         if (data == (RX0_ANARXSTATUS_PRBS_STATUS_PRBS_LOCK_BITS  <<
   3633                      RX0_ANARXSTATUS_PRBS_STATUS_PRBS_LOCK_SHIFT)) {
   3634             /* PRBS is in sync */
   3635             continue;
   3636         } else if (data == 0) {
   3637             /* PRBS not in sync */
   3638             *value = -1;
   3639             break;
   3640         } else {
   3641             /* Get errors */
   3642             *value += data & RX0_ANARXSTATUS_PRBS_STATUS_PTBS_ERRORS_MASK;
   3643         }
   3644     }
   3645     return SOC_E_NONE;
   3646 }
   3647 
   3648 
   3649 STATIC int
   3650 _phy_hl65_control_prbs_rx_status_get(int unit, soc_port_t port, uint32 *value)
   3651 {
   3652     int         rv;
   3653     uint16      rx_sts, saved_rx_sts;
   3654     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3655 
   3656     /* Set up prbs rx status collection */
   3657     SOC_IF_ERROR_RETURN
   3658         (HL65_REG_READ(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), &rx_sts));
   3659     saved_rx_sts = rx_sts;
   3660     rx_sts = (rx_sts & ~RX0_ANARXCONTROL_STATUS_SEL_MASK) |
   3661              RX0_ANARXCONTROL_STATUS_SEL_prbsStatus;
   3662     SOC_IF_ERROR_RETURN
   3663         (HL65_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), rx_sts));
   3664 
   3665     if (PHY_HC65_FABRIC_MODE(unit, pc->port)) {
   3666         rv =  _phy_hl65_control_fabric_prbs_rx_status_get(unit, port, value);
   3667     } else {
   3668         rv = _phy_hl65_control_xgxs_prbs_rx_status_get(unit, port, value);
   3669     }
   3670 
   3671     /* Restore rx status */
   3672     SOC_IF_ERROR_RETURN
   3673         (HL65_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), saved_rx_sts));
   3674 
   3675     return rv;
   3676 }
   3677 
   3678 
   3679 
   3680 STATIC int
   3681 _phy_hl65_control_serdes_driver_tune_set(int unit, soc_port_t port,
   3682                                          int lane_num, 
   3683                                          uint32 value)
   3684 {
   3685     uint16      data;
   3686     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3687 
   3688     if (SOC_IS_RELOADING(unit)) {
   3689         return SOC_E_NONE;
   3690     }
   3691 
   3692     /* Start receive tuning via rxSeqStart */
   3693     /* uRegAddr = 0x826e + (uLaneAddr*0x10);
   3694      * soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, uRegAddr , &uData)
   3695      */
   3696     SOC_IF_ERROR_RETURN
   3697         (HL65_REG_READ(unit, pc, 0x0, 0x826E + (0x10 * lane_num), &data));
   3698     
   3699     /* tune by toggling rxSeqStart */
   3700     /* uData |= 0x8000; */
   3701     data |=  (DSC2B0_DSC_MISC_CTRL0_RXSEQSTART_BITS <<  
   3702               DSC2B0_DSC_MISC_CTRL0_RXSEQSTART_SHIFT);
   3703     
   3704     /* write back updated configuration */
   3705     /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData) */
   3706     SOC_IF_ERROR_RETURN
   3707         (HL65_REG_WRITE(unit, pc, 0x0, 0x826E + (0x10 * lane_num), data));
   3708     
   3709     /* tune by toggling rxSeqStart */
   3710     data &= ~ (DSC2B0_DSC_MISC_CTRL0_RXSEQSTART_BITS <<  
   3711                DSC2B0_DSC_MISC_CTRL0_RXSEQSTART_SHIFT);
   3712     
   3713     /* write back updated configuration */
   3714     /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData) */
   3715     SOC_IF_ERROR_RETURN
   3716         (HL65_REG_WRITE(unit, pc, 0x0, 0x826E + (0x10 * lane_num), data));
   3717 
   3718     LOG_INFO(BSL_LS_SOC_PHY,
   3719              (BSL_META_U(unit,
   3720                          "hl_65: Equalization tune start\n")));
   3721     return SOC_E_NONE;
   3722 }
   3723 
   3724 STATIC int
   3725 _phy_hl65_control_64b66b_set(int unit, soc_port_t port, uint32 value)
   3726 {
   3727     uint16      data;
   3728     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3729     uint32      lane_mask = 1 << pc->lane_num;
   3730 
   3731     /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, 0x8015, &uData) */
   3732     SOC_IF_ERROR_RETURN
   3733         (READ_HL65_XGXSBLK1_LANECTRL0r(unit, pc, &data));
   3734     
   3735     if (value) {
   3736         data |= lane_mask << XGXSBLK1_LANECTRL0_ED66EN_SHIFT;
   3737 
   3738         
   3739         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8015, uData);*/
   3740         SOC_IF_ERROR_RETURN
   3741             (WRITE_HL65_XGXSBLK1_LANECTRL0r(unit, pc, data));
   3742     } else {
   3743 
   3744         data &= ~(lane_mask << XGXSBLK1_LANECTRL0_ED66EN_SHIFT);
   3745 
   3746 	/* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8015, uData);*/
   3747         SOC_IF_ERROR_RETURN
   3748             (WRITE_HL65_XGXSBLK1_LANECTRL0r(unit, pc, data));
   3749     }
   3750     return SOC_E_NONE;
   3751 }
   3752 
   3753 
   3754 STATIC int
   3755 _phy_hl65_control_8b10b_set(int unit, soc_port_t port, uint32 value)
   3756 {
   3757     uint16      data;
   3758     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   3759     uint32      lane_mask = 1 << pc->lane_num;
   3760 
   3761     /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, 0x8017, &uData) */
   3762     SOC_IF_ERROR_RETURN
   3763         (READ_HL65_XGXSBLK1_LANECTRL2r(unit, pc, &data));
   3764     
   3765     if (value) {
   3766         /* uData |= uLaneMask << BM9600_HYPERCORE_8017_8B10B_SHIFT;
   3767          * uData |= uLaneMask << BM9600_HYPERCORE_8017_KCHAR_SHIFT;
   3768          */
   3769         data |= lane_mask << XGXSBLK1_LANECTRL2_CDET_EN1G_SHIFT;
   3770         data |= lane_mask << XGXSBLK1_LANECTRL2_EDEN1G_SHIFT;
   3771         
   3772         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8017, uData);*/
   3773         SOC_IF_ERROR_RETURN
   3774             (WRITE_HL65_XGXSBLK1_LANECTRL2r(unit, pc, data));
   3775     } else {
   3776         /* uData &= ~(uLaneMask << BM9600_HYPERCORE_8017_8B10B_SHIFT);
   3777          * uData &= ~(uLaneMask << BM9600_HYPERCORE_8017_KCHAR_SHIFT);
   3778          */
   3779         data &= ~(lane_mask << XGXSBLK1_LANECTRL2_CDET_EN1G_SHIFT);
   3780         data &= ~(lane_mask << XGXSBLK1_LANECTRL2_EDEN1G_SHIFT);
   3781         
   3782         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, 0x8017, uData);*/
   3783         SOC_IF_ERROR_RETURN
   3784             (WRITE_HL65_XGXSBLK1_LANECTRL2r(unit, pc, data));
   3785     }
   3786     return SOC_E_NONE;
   3787 }
   3788 
   3789 
   3790 
   3791 STATIC int
   3792 _phy_hl65_tx_driver_field_get(soc_phy_control_t type,int *ln_ctrl,uint16 *mask,int *shfter)
   3793 {
   3794     int lane_ctrl;
   3795 
   3796     lane_ctrl = TX_DRIVER_DFT_LN_CTRL;
   3797     *mask = 0;
   3798     *shfter = 0;
   3799     /* _LANEn(n=0-3) control type only applies to combo mode or dxgxs in
   3800      * independent channel mode
   3801      */
   3802     switch(type) {
   3803     case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   3804     /* fall through */
   3805     case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   3806     /* fall through */
   3807     case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   3808     /* fall through */
   3809     case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   3810     /* fall through */
   3811     case SOC_PHY_CONTROL_PREEMPHASIS:
   3812         *shfter = TXB_TX_OS_DRIVER_PREEMPHASIS_POST_SHIFT;
   3813         *mask = TXB_TX_OS_DRIVER_PREEMPHASIS_POST_MASK;
   3814         if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) {
   3815             lane_ctrl = 0;
   3816         } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) {
   3817             lane_ctrl = 1;
   3818         } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) {
   3819             lane_ctrl = 2;
   3820         } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) {
   3821             lane_ctrl = 3;
   3822         }
   3823         break;
   3824 
   3825     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   3826     /* fall through */
   3827     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   3828     /* fall through */
   3829     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   3830     /* fall through */
   3831     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   3832     /* fall through */
   3833     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   3834         *shfter = TXB_TX_OS_DRIVER_IDRIVER_SHIFT;
   3835         *mask = TXB_TX_OS_DRIVER_IDRIVER_MASK;
   3836         if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0) {
   3837             lane_ctrl = 0;
   3838         } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1) {
   3839             lane_ctrl = 1;
   3840         } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2) {
   3841             lane_ctrl = 2;
   3842         } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3) {
   3843             lane_ctrl = 3;
   3844         }
   3845         break;
   3846 
   3847     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   3848     /* fall through */
   3849     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   3850     /* fall through */
   3851     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   3852     /* fall through */
   3853     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   3854     /* fall through */
   3855     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   3856         *shfter = TXB_TX_OS_DRIVER_IPREDRIVER_SHIFT;
   3857         *mask = TXB_TX_OS_DRIVER_IPREDRIVER_MASK;
   3858         if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0) {
   3859             lane_ctrl = 0;
   3860         } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1) {
   3861             lane_ctrl = 1;
   3862         } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2) {
   3863             lane_ctrl = 2;
   3864           /* coverity[mixed_enums:FALSE] */
   3865         } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3) {
   3866             lane_ctrl = 3;
   3867         }
   3868         break;
   3869 
   3870     case SOC_PHY_CONTROL_PRE_PREEMPHASIS:
   3871         *shfter = TXB_TX_OS_DRIVER_PREEMPHASIS_PRE_SHIFT;
   3872         *mask = TXB_TX_OS_DRIVER_PREEMPHASIS_PRE_MASK;
   3873         break;
   3874     default:
   3875      /* should never get here */
   3876         return SOC_E_PARAM;
   3877     }
   3878     *ln_ctrl = lane_ctrl;
   3879     return SOC_E_NONE;
   3880 }
   3881 
   3882 STATIC int
   3883 _phy_hl65_control_tx_driver_set(int unit, phy_ctrl_t *pc,
   3884                                 soc_phy_control_t type, uint32 value)
   3885 {
   3886     uint16  data;             /* Temporary holder of reg value to be written */
   3887     uint16  mask;             /* Bit mask of reg value to be updated */
   3888     uint16  ivalue;
   3889     int     lane_ctrl;
   3890     int     lane_num;
   3891     int     shifter;
   3892 
   3893     /* Both cases 6.5G/3.125G handled the same, ignore MSB though it may be passed in*/
   3894     ivalue = value & 0x7fff;
   3895     if (ivalue > 15) {
   3896         return SOC_E_PARAM;
   3897     }
   3898 
   3899     SOC_IF_ERROR_RETURN
   3900         (_phy_hl65_tx_driver_field_get(type,&lane_ctrl,&mask,&shifter));
   3901 
   3902     data = ivalue << shifter;
   3903 
   3904     if ((lane_ctrl != TX_DRIVER_DFT_LN_CTRL) ||
   3905         PHY_INDEPENDENT_LANE_MODE(unit, pc->port) ||
   3906         PHY_HC65_FABRIC_MODE(unit, pc->port)) {
   3907         if (lane_ctrl != TX_DRIVER_DFT_LN_CTRL) {
   3908             lane_num = lane_ctrl;
   3909         } else {
   3910             lane_num = pc->lane_num;
   3911         }
   3912 	
   3913 	if (lane_num == 0) {
   3914 	    SOC_IF_ERROR_RETURN
   3915 		(MODIFY_HL65_TX0_TX_BR_DRIVERr(unit, pc, data, mask));
   3916 	    SOC_IF_ERROR_RETURN
   3917 		(MODIFY_HL65_TX0_TX_OS_DRIVERr(unit, pc, data, mask));
   3918 	} else if (lane_num == 1) {
   3919 	    SOC_IF_ERROR_RETURN
   3920 		(MODIFY_HL65_TX1_TX_BR_DRIVERr(unit, pc, data, mask));
   3921 	    SOC_IF_ERROR_RETURN
   3922 		(MODIFY_HL65_TX1_TX_OS_DRIVERr(unit, pc, data, mask));
   3923 	} else if (lane_num == 2) {
   3924 	    SOC_IF_ERROR_RETURN
   3925 		(MODIFY_HL65_TX2_TX_BR_DRIVERr(unit, pc, data, mask));
   3926 	    SOC_IF_ERROR_RETURN
   3927 		(MODIFY_HL65_TX2_TX_OS_DRIVERr(unit, pc, data, mask));
   3928 	} else if (lane_num == 3) {
   3929 	    SOC_IF_ERROR_RETURN
   3930 		(MODIFY_HL65_TX3_TX_BR_DRIVERr(unit, pc, data, mask));
   3931 	    SOC_IF_ERROR_RETURN
   3932 		(MODIFY_HL65_TX3_TX_OS_DRIVERr(unit, pc, data, mask));
   3933 	} 
   3934     } else { /* default control in combo mode: bcst to all lanes */
   3935 	/* set for both BR mode and OS mode */
   3936 	SOC_IF_ERROR_RETURN
   3937 	    (MODIFY_HL65_TX0_TX_BR_DRIVERr(unit, pc, data, mask));
   3938 	SOC_IF_ERROR_RETURN
   3939 	    (MODIFY_HL65_TX0_TX_OS_DRIVERr(unit, pc, data, mask));
   3940 	SOC_IF_ERROR_RETURN
   3941 	    (MODIFY_HL65_TX1_TX_BR_DRIVERr(unit, pc, data, mask));
   3942 	SOC_IF_ERROR_RETURN
   3943 	    (MODIFY_HL65_TX1_TX_OS_DRIVERr(unit, pc, data, mask));
   3944 	SOC_IF_ERROR_RETURN
   3945 	    (MODIFY_HL65_TX2_TX_BR_DRIVERr(unit, pc, data, mask));
   3946 	SOC_IF_ERROR_RETURN
   3947 	    (MODIFY_HL65_TX2_TX_OS_DRIVERr(unit, pc, data, mask));
   3948 	SOC_IF_ERROR_RETURN
   3949 	    (MODIFY_HL65_TX3_TX_BR_DRIVERr(unit, pc, data, mask));
   3950 	SOC_IF_ERROR_RETURN
   3951 	    (MODIFY_HL65_TX3_TX_OS_DRIVERr(unit, pc, data, mask));
   3952     }
   3953 
   3954     return SOC_E_NONE;
   3955 }
   3956 
   3957 STATIC int
   3958 _phy_hl65_control_tx_driver_get(int unit, phy_ctrl_t *pc,
   3959                                 soc_phy_control_t type, uint32 *value)
   3960 {
   3961     uint16  data16;           /* Temporary holder of 16 bit reg value */
   3962     uint16  mask;
   3963     int     shifter;
   3964     int     lane_ctrl;
   3965     int     lane_num;
   3966 
   3967     SOC_IF_ERROR_RETURN
   3968         (_phy_hl65_tx_driver_field_get(type,&lane_ctrl,&mask,&shifter));
   3969 
   3970      
   3971     /* Read preemphasis/driver/pre-driver current */
   3972     if ((lane_ctrl != TX_DRIVER_DFT_LN_CTRL) ||
   3973         PHY_INDEPENDENT_LANE_MODE(unit, pc->port) ||
   3974         PHY_HC65_FABRIC_MODE(unit, pc->port)) {
   3975         if (lane_ctrl != TX_DRIVER_DFT_LN_CTRL) {
   3976             lane_num = lane_ctrl;
   3977         } else {
   3978             lane_num = pc->lane_num;
   3979         }
   3980         if (lane_num == 0) {
   3981             SOC_IF_ERROR_RETURN
   3982                 (READ_HL65_TX0_TX_OS_DRIVERr(unit, pc, &data16));
   3983         } else if (lane_num == 1) {
   3984             SOC_IF_ERROR_RETURN
   3985                 (READ_HL65_TX1_TX_OS_DRIVERr(unit, pc, &data16));
   3986         } else if (lane_num == 2) {
   3987             SOC_IF_ERROR_RETURN
   3988                 (READ_HL65_TX2_TX_OS_DRIVERr(unit, pc, &data16));
   3989         } else if (lane_num == 3) {
   3990             SOC_IF_ERROR_RETURN
   3991                 (READ_HL65_TX3_TX_OS_DRIVERr(unit, pc, &data16));
   3992         } else {
   3993             return (SOC_E_PARAM);
   3994         }
   3995     } else {
   3996         SOC_IF_ERROR_RETURN
   3997             (READ_HL65_TX0_TX_OS_DRIVERr(unit, pc, &data16));
   3998     }
   3999 
   4000     *value = (data16 & mask) >> shifter;
   4001 
   4002     return SOC_E_NONE;
   4003 }
   4004 
   4005 
   4006 STATIC int
   4007 _phy_hl65_tuning_done_get(int unit, soc_port_t port,int lane_num, uint16 *done)
   4008 {
   4009     uint16      data;
   4010     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4011 
   4012     /* *bTuningDone = FALSE;*/
   4013     *done = 0;
   4014 
   4015     /* Read tuning status */
   4016     /* uRegAddr = 0x82b7 + (uLaneAddr*0x10);
   4017      * rv = soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, uRegAddr, &uData);
   4018      */
   4019     SOC_IF_ERROR_RETURN
   4020         (HL65_REG_READ(unit,pc,0x0,0x82B7 + (0x10 * lane_num), &data));
   4021 
   4022 #if 0
   4023     /* If tuning is done */
   4024     if (uData & 0x2000) {
   4025 	LOG_ERROR(BSL_LS_SOC_PHY,
   4026 		  (BSL_META_U(unit,
   4027 			      "hc(%02d:%02d) Tuning Done indication received\n"),
   4028 		   uPhyAddr, uLaneAddr));
   4029 	*bTuningDone = TRUE;
   4030     }
   4031 #endif
   4032     *done = (data & 
   4033              (DSC3B0_SM_STATUS0_TUNING_DONE_BITS <<
   4034               DSC3B0_SM_STATUS0_TUNING_DONE_SHIFT)) ? 1 : 0;
   4035 
   4036     return SOC_E_NONE;
   4037 }
   4038 
   4039 
   4040 /* #define BCM_BM9600_HYPERCORE_PORT_TUNING_AVG 40 */
   4041 #define PHY_HL65_PORT_TUNING_AVG    40
   4042 
   4043 STATIC int
   4044 _phy_hl65_tuning_status_get(int unit, soc_port_t port, 
   4045                             int lane_num,
   4046                             uint16 *vga_sum_avg, 
   4047                             uint16 *dfe_tap_bin_avg)
   4048 {
   4049     uint16      data, cnt;
   4050     uint16      cur_vga, avg_vga, cur_dfe, avg_dfe;
   4051     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4052 
   4053     avg_vga = 0;
   4054     avg_dfe = 0;
   4055 
   4056     for (cnt=0; cnt < PHY_HL65_PORT_TUNING_AVG; cnt++) {
   4057 
   4058 	/* uRegAddr = 0x82b5 + (uLaneAddr*0x10);
   4059          * rv = soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, uRegAddr, &uData);
   4060          */
   4061         SOC_IF_ERROR_RETURN
   4062             (HL65_REG_READ(unit,pc,0x0,0x82b5 + (0x10 * lane_num), &data));
   4063 
   4064 	/* uCurrentVga = (uData & 0x07c0)>>6;
   4065          * uCurrentDfe = (uData & 0x003f);
   4066          */
   4067         cur_vga = (data & DSC3B0_DFE_VGA_STATUS0_VGA_SUM_MASK) >>  
   4068                   DSC3B0_DFE_VGA_STATUS0_VGA_SUM_SHIFT;
   4069         cur_dfe = (data & DSC3B0_DFE_VGA_STATUS0_DFE_TAP_BIN_MASK);
   4070 
   4071 	/*uAvgVga += uCurrentVga;
   4072          *uAvgDfe += uCurrentDfe;
   4073          */
   4074         avg_vga += cur_vga;
   4075         avg_dfe += cur_dfe;
   4076     }
   4077 
   4078     /* Divide to get the average value */
   4079     /* uAvgVga = uAvgVga/BCM_BM9600_HYPERCORE_PORT_TUNING_AVG;
   4080      * uAvgDfe = uAvgDfe/BCM_BM9600_HYPERCORE_PORT_TUNING_AVG;
   4081      */
   4082     avg_vga = avg_vga / PHY_HL65_PORT_TUNING_AVG;
   4083     avg_dfe = avg_dfe / PHY_HL65_PORT_TUNING_AVG;
   4084 
   4085     /*   *pVgaSumAvg = uAvgVga;
   4086      *   *pDfeTapBinAvg = uAvgDfe;
   4087      */
   4088     *vga_sum_avg = avg_vga;
   4089 
   4090 
   4091     *dfe_tap_bin_avg = avg_dfe;
   4092 
   4093 #if 0
   4094     LOG_ERROR(BSL_LS_SOC_PHY,
   4095               (BSL_META_U(unit,
   4096                           "hc(%02d:%02d) VGA avg(%d)\n"),
   4097                uPhyAddr, uLaneAddr, uAvgVga));
   4098     LOG_ERROR(BSL_LS_SOC_PHY,
   4099               (BSL_META_U(unit,
   4100                           "hc(%02d:%02d) DFE avg(%d)\n"),
   4101                uPhyAddr, uLaneAddr, uAvgDfe));
   4102 #endif
   4103     LOG_INFO(BSL_LS_SOC_PHY,
   4104              (BSL_META_U(unit,
   4105                          "hc(%02d) VGA avg(%d)\n"), port, avg_vga));
   4106     LOG_INFO(BSL_LS_SOC_PHY,
   4107              (BSL_META_U(unit,
   4108                          "hc(%02d) DFE avg(%d)\n"), port, avg_dfe));
   4109 
   4110     return SOC_E_NONE;
   4111 }
   4112 
   4113 STATIC int
   4114 _phy_hl65_fine_tune(int unit, soc_port_t port, int lane_num)
   4115 {
   4116     uint16   data, cnt;
   4117     uint16   tuning_done;
   4118     uint32   reg_addr;
   4119     int      avg_vga_sum;
   4120     int      rv = SOC_E_NONE;
   4121     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4122     uint16      serdes_id0;
   4123 
   4124     SOC_IF_ERROR_RETURN
   4125         (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
   4126     
   4127     serdes_id0 = serdes_id0 & (TEST_SERDESID0_REV_NUMBER_MASK |
   4128                                TEST_SERDESID0_REV_LETTER_MASK);
   4129     
   4130     if ((serdes_id0 == HL_SERDES_ID0_REVID_A0) ||
   4131         (serdes_id0 == HL_SERDES_ID0_REVID_A1) ||
   4132         (serdes_id0 == HL_SERDES_ID0_REVID_B0)) {
   4133         /* Disable DSC tuning state machine */
   4134         /* uRegAddr = 0x8260 + (uLaneAddr*0x10);
   4135          * rv = soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, uRegAddr, &uData);
   4136          */
   4137         reg_addr = 0x8260 + (lane_num * 0x10);
   4138         SOC_IF_ERROR_RETURN
   4139             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4140         
   4141         /* tuning_sm_en: bit 0 */
   4142         /* uData &= ~0x1; */
   4143         data &= ~DSC2B0_SM_CTRL0_TUNING_SM_EN_BITS; 
   4144         
   4145 	    /*rv = soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4146         SOC_IF_ERROR_RETURN
   4147             (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4148         
   4149         /* Enable training mode in state machine */
   4150         /* uRegAddr = 0x8262 + (uLaneAddr*0x10);
   4151          * rv = soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, uRegAddr, &uData);
   4152          */
   4153         reg_addr = 0x8262 + (lane_num * 0x10);
   4154         SOC_IF_ERROR_RETURN
   4155             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4156         
   4157         /* uData |= 1; */ /* train_mode_en */
   4158         data |= DSC2B0_SM_CTRL2_TRAIN_MODE_EN_BITS;
   4159         
   4160         /*rv = soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4161         SOC_IF_ERROR_RETURN
   4162             (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4163     }
   4164     
   4165     /* Bypass BR peaking filter calibration */
   4166     /* uRegAddr = 0x8260 + (uLaneAddr*0x10);
   4167      *  soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, uRegAddr, &uData);
   4168      */
   4169     reg_addr = 0x8260 + (lane_num * 0x10);
   4170     SOC_IF_ERROR_RETURN
   4171         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4172 
   4173     /* bypass_br_pf_cal */
   4174     /* uData |= 0x200; */
   4175     data |=  (DSC2B0_SM_CTRL0_BYPASS_BR_PF_CAL_BITS <<  
   4176               DSC2B0_SM_CTRL0_BYPASS_BR_PF_CAL_SHIFT);
   4177 
   4178     if (serdes_id0 == HL_SERDES_ID0_REVID_C0) {
   4179         /* bypass _tx_postc_calibration */
   4180         data |=  (DSC2B0_SM_CTRL0_BYPASS_TX_POSTC_CAL_BITS <<  
   4181                   DSC2B0_SM_CTRL0_BYPASS_TX_POSTC_CAL_SHIFT);
   4182     }
   4183     /*rv = soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4184     SOC_IF_ERROR_RETURN
   4185         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4186 
   4187     if ((serdes_id0 == HL_SERDES_ID0_REVID_A0) ||
   4188         (serdes_id0 == HL_SERDES_ID0_REVID_A1) ||
   4189         (serdes_id0 == HL_SERDES_ID0_REVID_B0)) {
   4190         
   4191         /* DSC Analog control 0 odd ctrl register setup */
   4192         /* uRegAddr = 0x821a + (uLaneAddr*0x10);
   4193          * uData = 0x8000; 
   4194          */
   4195         /* Write 0 to p1_odd_ctrl, d_odd_ctrl and m1_odd_ctrl and set force_odd_ctrl to 1 */
   4196         reg_addr = 0x821a + (lane_num * 0x10);
   4197         data = (DSC1B0_DSC_ANA_CTRL0_FORCE_ODD_CTRL_BITS <<
   4198                 DSC1B0_DSC_ANA_CTRL0_FORCE_ODD_CTRL_SHIFT);
   4199         
   4200         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4201         SOC_IF_ERROR_RETURN
   4202             (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4203         
   4204         
   4205         /* DSC Analog control 0 even ctrl register setup */
   4206         /* uRegAddr = 0x821b + (uLaneAddr*0x10);
   4207          * uData = 0x8000; 
   4208          */
   4209         reg_addr =  0x821b + (lane_num * 0x10);
   4210         /* Write 0 to p1_evn_ctrl, d_evn_ctrl and m1_evn_ctrl and set force_evn_ctrl to 1 */
   4211         data = (DSC1B0_DSC_ANA_CTRL1_FORCE_EVN_CTRL_BITS <<
   4212                 DSC1B0_DSC_ANA_CTRL1_FORCE_EVN_CTRL_SHIFT);
   4213         
   4214         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4215         SOC_IF_ERROR_RETURN
   4216             (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4217         
   4218         
   4219         /* read vga_sum 10 times and average */
   4220         /* uRegAddr = 0x82b5 + (uLaneAddr*0x10);
   4221          * uAvgVgaSum = 0;
   4222          */
   4223         reg_addr = 0x82b5 + (lane_num * 0x10);
   4224         avg_vga_sum = 0;
   4225         for (cnt=0; cnt < 10; cnt++) {
   4226             /* rv = soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, uRegAddr, &uData); */
   4227             SOC_IF_ERROR_RETURN
   4228                 (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4229             /*uAvgVgaSum += (uData & 0x07c0) >> 6;*/
   4230             avg_vga_sum += ((data & DSC3B0_DFE_VGA_STATUS0_VGA_SUM_MASK) >> 
   4231                             DSC3B0_DFE_VGA_STATUS0_VGA_SUM_SHIFT);
   4232         }
   4233         /* uAvgVgaSum = uAvgVgaSum/10; */
   4234         avg_vga_sum = avg_vga_sum / 10;
   4235         
   4236         LOG_INFO(BSL_LS_SOC_PHY,
   4237                  (BSL_META_U(unit,
   4238                              "hc(%02d) VGA avg sum(%d)\n"), 
   4239                   port, avg_vga_sum));
   4240         
   4241         if (avg_vga_sum > 31) {
   4242             LOG_ERROR(BSL_LS_SOC_PHY,
   4243                       (BSL_META_U(unit,
   4244                                   "ERROR: hc(%02d) VGA avg sum out of range(%d) maximum allowed 31\n"), 
   4245                        port, avg_vga_sum));
   4246             return SOC_E_FAIL;
   4247         }
   4248         
   4249         /* write vga average into vga_write_val */
   4250         /* uRegAddr = 0x8215 + (uLaneAddr*0x10);
   4251          * rv = soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, uRegAddr, &uData);
   4252          */
   4253         reg_addr = 0x8215 + (lane_num * 0x10);
   4254         SOC_IF_ERROR_RETURN
   4255             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4256         
   4257         /*uData = uData & ~0x03e;
   4258          * uData |= uAvgVgaSum << 1;
   4259          */
   4260         data = data &  (~DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_VAL_MASK);
   4261         data |= (avg_vga_sum << DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_VAL_SHIFT);
   4262         
   4263         /* rv = soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4264         SOC_IF_ERROR_RETURN
   4265             (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4266         
   4267         
   4268         /* Toggle vga_write_en to complete the VGA write */
   4269         /* uData |= 1;*/
   4270         data |= DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_BITS;
   4271         
   4272         /*rv = soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4273         SOC_IF_ERROR_RETURN
   4274             (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4275         
   4276         /* uData &=~1; */
   4277         data &= ~DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_BITS;
   4278         
   4279         /*rv = soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4280         SOC_IF_ERROR_RETURN
   4281             (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4282         
   4283 
   4284         
   4285         /* DSC Analog control 0 odd ctrl register setup */
   4286         /* uRegAddr = 0x821a + (uLaneAddr*0x10);
   4287          * uData = 0x0000; 
   4288          */
   4289         /* Write 0 to p1_odd_ctrl, d_odd_ctrl and m1_odd_ctrl and set force_odd_ctrl to 0 */
   4290         reg_addr = 0x821a + (lane_num * 0x10);
   4291         data = 0;
   4292         
   4293         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4294         SOC_IF_ERROR_RETURN
   4295             (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4296         
   4297         
   4298         /* DSC Analog control 0 even ctrl register setup */
   4299         /* uRegAddr = 0x821b + (uLaneAddr*0x10);
   4300          * uData = 0x0000; 
   4301          */
   4302         reg_addr =  0x821b + (lane_num * 0x10);
   4303         /* Write 0 to p1_evn_ctrl, d_evn_ctrl and m1_evn_ctrl and set force_evn_ctrl to 0 */
   4304         data = 0;
   4305         
   4306         /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4307         SOC_IF_ERROR_RETURN
   4308             (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4309         
   4310     }
   4311     /* Enable DSC tuning state machine */
   4312     /* uRegAddr = 0x8260 + (uLaneAddr*0x10);*/
   4313     reg_addr =  0x8260 + (lane_num * 0x10 );
   4314     /*rv = soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, uRegAddr, &uData);*/
   4315     SOC_IF_ERROR_RETURN
   4316         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4317     
   4318     /* uData |= 0x1; */
   4319     /* tuning_sm_en: bit 0 */
   4320     data |= DSC2B0_SM_CTRL0_TUNING_SM_EN_BITS;
   4321     
   4322     /*rv = soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4323     SOC_IF_ERROR_RETURN
   4324         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4325     
   4326     /* Restart tuning */
   4327     /* uData |= 2;*/
   4328     data |= (DSC2B0_SM_CTRL0_RESTART_TUNING_BITS << 
   4329              DSC2B0_SM_CTRL0_RESTART_TUNING_SHIFT);
   4330     
   4331     /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4332     SOC_IF_ERROR_RETURN
   4333         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4334     
   4335     
   4336     /* Wait for tuning done signal (timeout) */
   4337     for (cnt = 0; cnt < 50; cnt++) {
   4338         /* _bcm_bm9600_hypercore_tuning_done_get(unit, uPhyAddr, uLaneAddr, &bTuningDone);*/
   4339         SOC_IF_ERROR_RETURN
   4340             (_phy_hl65_tuning_done_get(unit, port, lane_num,&tuning_done));
   4341         
   4342         if (tuning_done) {
   4343             break;
   4344         }
   4345         
   4346         /*thin_delay(10000000);*/
   4347         /* 10 milliseconds */
   4348         sal_usleep(10000);
   4349     }
   4350     
   4351     if (!tuning_done) {
   4352         LOG_ERROR(BSL_LS_SOC_PHY,
   4353                   (BSL_META_U(unit,
   4354                               "ERROR: hc(%02d) tuning done timed out during BR fine tuning\n"), 
   4355                    port));
   4356         
   4357         rv = SOC_E_TIMEOUT;
   4358     }
   4359     
   4360     /* restore br_pf_calibration and disable training mode */
   4361     /* uRegAddr = 0x8260 + (uLaneAddr*0x10);*/
   4362     reg_addr =  0x8260 + (lane_num * 0x10);
   4363     
   4364     /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, uRegAddr, &uData);*/
   4365     SOC_IF_ERROR_RETURN
   4366         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4367 
   4368     /*uData &= ~0x200; */
   4369     /* bypass_br_pf_cal */
   4370     data &= ~(DSC2B0_SM_CTRL0_BYPASS_BR_PF_CAL_BITS <<
   4371                DSC2B0_SM_CTRL0_BYPASS_BR_PF_CAL_SHIFT);
   4372 
   4373     if (serdes_id0 == HL_SERDES_ID0_REVID_C0) {
   4374         /* bypass _tx_postc_calibration */
   4375         data &=  ~(DSC2B0_SM_CTRL0_BYPASS_TX_POSTC_CAL_BITS <<  
   4376                    DSC2B0_SM_CTRL0_BYPASS_TX_POSTC_CAL_SHIFT);
   4377     }
   4378     
   4379     /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4380     SOC_IF_ERROR_RETURN
   4381         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4382     
   4383     /* disable training mode */
   4384     /* uRegAddr = 0x8262 + (uLaneAddr*0x10); */
   4385     reg_addr =  0x8262 + (lane_num * 0x10);
   4386     
   4387     /* soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, uRegAddr, &uData);*/
   4388     SOC_IF_ERROR_RETURN
   4389         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4390     
   4391     /* uData &= ~1; */
   4392     /* train_mode_en */
   4393     data &= ~DSC2B0_SM_CTRL2_TRAIN_MODE_EN_BITS;
   4394 
   4395     /* soc_bm9600_mdio_hc_write(unit, uPhyAddr, uLaneAddr, uRegAddr, uData);*/
   4396     SOC_IF_ERROR_RETURN
   4397         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4398 
   4399     return rv;
   4400 }
   4401 
   4402 
   4403 STATIC int
   4404 _phy_hl65_control_eq_tune_status_get(int unit, 
   4405                                      soc_port_t port, 
   4406                                      int lane_num,
   4407                                      uint32 *value)
   4408 {
   4409     uint16      data;
   4410     uint16      sig_detected;
   4411     uint16      saved_status_select;
   4412     uint16      tuning_done;
   4413     uint16      avg_vga, avg_dfe;
   4414     uint16      postc_metric, negative;
   4415     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4416     int cnt;
   4417     uint16      serdes_id0;
   4418 
   4419     SOC_IF_ERROR_RETURN
   4420         (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
   4421 
   4422     serdes_id0 = serdes_id0 & (TEST_SERDESID0_REV_NUMBER_MASK |
   4423                             TEST_SERDESID0_REV_LETTER_MASK);
   4424 
   4425 
   4426     *value = FALSE;
   4427     
   4428     /*  Make sure we have signal detect */
   4429     /* status = _bcm_bm9600_hypercore_sigdet_status_get(unit, uPhyAddr, uLaneAddr, &bSigDetected)
   4430      * --->  code for this function brought here---
   4431      * uRegAddr = 0x80b1;
   4432      * uRegAddr += uLaneAddr * 0x10;
   4433      *
   4434      * Save off current value of 0x80b1 status_sel 
   4435      *
   4436      * rv = soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, uRegAddr, &uData);
   4437      */
   4438     SOC_IF_ERROR_RETURN
   4439         (HL65_REG_READ(unit,pc,0x0,0x80B1 + (0x10 * lane_num), &data));
   4440 
   4441     /* uSavedStatusSelect = uData; */
   4442     saved_status_select = data;
   4443 
   4444     /* Set register 0x80b1 status_sel to get sigDetStatus=0 */
   4445     /* uData &= ~BM9600_HYPERCORE_80B1_STATUS_MASK;
   4446      * uData |= BM9600_HYPERCORE_80B1_SIGDET_STATUS_VALUE;
   4447      */
   4448     data &= ~RX0_ANARXCONTROL_STATUS_SEL_MASK;
   4449     data |= RX0_ANARXCONTROL_STATUS_SEL_sigdetStatus;
   4450 
   4451     /*rv = soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, uRegAddr, uData);*/
   4452     SOC_IF_ERROR_RETURN
   4453         (HL65_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * lane_num), data));
   4454 
   4455     /* read to clear latched status */
   4456     SOC_IF_ERROR_RETURN
   4457         (HL65_REG_READ(unit,pc,0x0,0x80B0 + (0x10 * lane_num), &data));
   4458 
   4459     /* read register 0x80b0 to get status and fill in bSigDetected */
   4460     /* uRegAddr = 0x80b0;
   4461      * uRegAddr += uLaneAddr * 0x10;
   4462      * rv = soc_bm9600_mdio_hc_read(unit, uPhyAddr, 0, uRegAddr, &uData);
   4463      */
   4464     SOC_IF_ERROR_RETURN
   4465         (HL65_REG_READ(unit,pc,0x0,0x80B0 + (0x10 * lane_num), &data));
   4466 
   4467     /* if (uData & 0x8000) {
   4468      *	*bSigDetected = TRUE;
   4469      * }else {
   4470      *	*bSigDetected = FALSE;
   4471      * }
   4472      */
   4473     sig_detected = (data & 
   4474                     (RX0_ANARXSTATUS_SIGDET_STATUS_CX4_SIGDET_BITS <<  
   4475                      RX0_ANARXSTATUS_SIGDET_STATUS_CX4_SIGDET_SHIFT)) ? 1 : 0;
   4476 
   4477     /* write back old value of 0x80b1 status_sel */
   4478     /*rv = soc_bm9600_mdio_hc_write(unit, uPhyAddr, 0, uRegAddr, uSavedStatusSelect); */
   4479     SOC_IF_ERROR_RETURN
   4480         (HL65_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * lane_num), saved_status_select));
   4481 
   4482 #if 0
   4483     if (!bSigDetected) {
   4484         LOG_ERROR(BSL_LS_SOC_PHY,
   4485                   (BSL_META_U(unit,
   4486                               "ERROR: Receiver indicates that no signal detected, check far end enable.\n")));
   4487     }
   4488 #endif
   4489     if (!sig_detected) {
   4490         LOG_ERROR(BSL_LS_SOC_PHY,
   4491                   (BSL_META_U(unit,
   4492                               "Receiver indicates that no signal detected. "
   4493                               "Checking far end enable.\n")));
   4494     }
   4495 
   4496     /* Wait for tuning done signal (timeout) */
   4497     for (cnt = 0; cnt < 50; cnt++) {
   4498         /* _bcm_bm9600_hypercore_tuning_done_get(unit, uPhyAddr, uLaneAddr, &bTuningDone);*/
   4499         SOC_IF_ERROR_RETURN
   4500             (_phy_hl65_tuning_done_get(unit, port, lane_num,&tuning_done));
   4501 
   4502         if (tuning_done) {
   4503             break;
   4504         }
   4505 
   4506         /*thin_delay(10000000);*/         /* 10 milliseconds */
   4507         sal_usleep(10000);
   4508     }
   4509 
   4510 #if 0
   4511     if (!bTuningDone) {
   4512         LOG_ERROR(BSL_LS_SOC_PHY,
   4513                   (BSL_META_U(unit,
   4514                               "ERROR: Tuning error port(%d), no tuning done indication from hardware\n"),
   4515                    port));
   4516     }
   4517 #endif
   4518     if (!tuning_done) {
   4519         LOG_ERROR(BSL_LS_SOC_PHY,
   4520                   (BSL_META_U(unit,
   4521                               "No tune done indication received on port %d\n"),
   4522                    port));
   4523 
   4524     } else {
   4525         /* _bcm_bm9600_hypercore_tuning_status_get(unit, uPhyAddr, uLaneAddr, &uAvgVga, &uAvgDfe);*/
   4526         SOC_IF_ERROR_RETURN
   4527             (_phy_hl65_tuning_status_get(unit, port, lane_num,
   4528                                         &avg_vga, &avg_dfe));
   4529 
   4530 	if ((serdes_id0 == HL_SERDES_ID0_REVID_A0) ||
   4531 	    (serdes_id0 == HL_SERDES_ID0_REVID_A1) ||
   4532 	    (serdes_id0 == HL_SERDES_ID0_REVID_B0)) {
   4533 
   4534 	    /* If (uAvgDfe < 8) {
   4535 	     *   postc_metric = 0x400;     -1023 11 bit 2s complement number 
   4536 	     * } else if (uAvgDfe > 56) {
   4537 	     *   postc_metric = 0x3ff;      1023 11 bit 2s complement number 
   4538 	     * } else {
   4539 	     */
   4540 	    if (avg_dfe < 8) {
   4541 		postc_metric = 0x400; /* -1023 11 bit 2s complement number */
   4542 	    } else if (avg_dfe > 56) {
   4543 		postc_metric = 0x3ff; /* 1023 11 bit 2s complement number */
   4544 	    } else {
   4545 		/* uRegAddr = 0x82b8 + (uLaneAddr*0x10);
   4546 		 * status = soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, uRegAddr, &uData);
   4547 		 */
   4548 		SOC_IF_ERROR_RETURN
   4549 		    (HL65_REG_READ(unit,pc,0x0,0x82b8 + (0x10 * lane_num), &data));
   4550 		
   4551 		/* postc_metric = uData & 0x7ff;*/
   4552 		postc_metric = data &  DSC3B0_SM_STATUS1_POSTC_METRIC_MASK;
   4553 	    }
   4554 	} else { /* C0 */
   4555 	    /* uRegAddr = 0x82b8 + (uLaneAddr*0x10);
   4556 	     * status = soc_bm9600_mdio_hc_read(unit, uPhyAddr, uLaneAddr, uRegAddr, &uData);
   4557 	     */
   4558 	    SOC_IF_ERROR_RETURN
   4559 		(HL65_REG_READ(unit,pc,0x0,0x82b8 + (0x10 * lane_num), &data));
   4560 	    
   4561 	    /* postc_metric = uData & 0x7ff;*/
   4562 	    postc_metric = data &  DSC3B0_SM_STATUS1_POSTC_METRIC_MASK;
   4563 	}
   4564 
   4565 	/* negative = postc_metric >> 10; */
   4566 	/* Extract the sign bit */
   4567 	negative = postc_metric >> (DSC3B0_SM_STATUS1_POSTC_METRIC_BITS - 1);
   4568 	
   4569 	/* Get rid of the sign on the metric now */
   4570 	if (postc_metric > 1023) postc_metric -= 1024;
   4571 	   	
   4572 	/* if (!negative && (uAvgDfe < 30) && (postc_metric < 15)) { */
   4573 	if ((!negative) && (avg_dfe < 30)) { 
   4574 	    LOG_WARN(BSL_LS_SOC_PHY,
   4575                      (BSL_META_U(unit,
   4576                                  "port(%d) postc_metric(0x%x) is positive\n"),
   4577                       port, postc_metric));
   4578 	    
   4579 	    *value = FALSE;
   4580 	    
   4581         } else {
   4582             LOG_INFO(BSL_LS_SOC_PHY,
   4583                      (BSL_META_U(unit,
   4584                                  "port(%d) remote equalization calibration complete\n"), 
   4585                       port));
   4586 
   4587 	    *value = TRUE;
   4588         }
   4589         
   4590         /* Perform fine tuning operation */
   4591         /*status = _bcm_bm9600_hypercore_fine_tune(unit, uPhyAddr, uLaneAddr);*/
   4592 
   4593         if (_phy_hl65_fine_tune(unit, port,lane_num) != SOC_E_NONE) {
   4594             LOG_WARN(BSL_LS_SOC_PHY,
   4595                      (BSL_META_U(unit,
   4596                                  "port(%d) hl65_fine_tune fail\n"), port));
   4597         }
   4598     }
   4599     return SOC_E_NONE;
   4600 }
   4601 
   4602 
   4603 STATIC int
   4604 _phy_hl65_control_linkdown_transmit_set(int unit, soc_port_t port, uint32 value)
   4605 {
   4606     uint16      ctrl2_data;
   4607     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4608 
   4609     if (value) {
   4610         ctrl2_data = (DIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_BITS << 
   4611                       DIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_SHIFT) |
   4612                      (DIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_BITS  <<
   4613                       DIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_SHIFT) |
   4614                      (DIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_BITS <<
   4615                       DIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_SHIFT);
   4616         SOC_IF_ERROR_RETURN
   4617             (WRITE_HL65_DIGITAL_CONTROL1000X2r(unit, pc, ctrl2_data));
   4618 
   4619     } else {
   4620         ctrl2_data = (DIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_BITS <<
   4621                       DIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_SHIFT) |   
   4622                      (DIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_BITS <<
   4623                       DIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_SHIFT) | 
   4624                      (DIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_BITS <<
   4625                       DIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_SHIFT);
   4626         SOC_IF_ERROR_RETURN
   4627             (WRITE_HL65_DIGITAL_CONTROL1000X2r(unit, pc, ctrl2_data));
   4628     }
   4629 
   4630     return SOC_E_NONE;
   4631 }
   4632 
   4633 STATIC int
   4634 _phy_hl65_control_linkdown_transmit_get(int unit, soc_port_t port, uint32 *value)
   4635 {
   4636     uint16      data;
   4637     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4638 
   4639     SOC_IF_ERROR_RETURN
   4640         (READ_HL65_DIGITAL_CONTROL1000X2r(unit, pc, &data));
   4641 
   4642     /* Check if FORCE_XMIT_DATA_ON_TXSIDE is set */
   4643     *value = (data & (DIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_BITS <<
   4644                       DIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_SHIFT))
   4645              ? 1 : 0;
   4646 
   4647     return SOC_E_NONE;
   4648 }
   4649 
   4650 
   4651     
   4652 /*
   4653  * Get current DSC config
   4654  */
   4655 STATIC int
   4656 _phy_hl65_dsc_cfg_get(int unit, soc_port_t port, int lane_num, 
   4657                          phy_hl65_dsc_cfg_t *dsc_cfg) 
   4658                                        
   4659 {
   4660     int         rv = SOC_E_NONE;
   4661     uint16      data;
   4662     uint32      reg_addr;
   4663     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4664 
   4665     reg_addr = 0x82b2 + (lane_num * 0x10);
   4666     SOC_IF_ERROR_RETURN
   4667         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4668 
   4669     if (data & DSC3B0_CDR_STATUS2_BR_CDR_ENABLED_MASK) {
   4670         *dsc_cfg = PHY_HL65_DSC_CFG_BR_CDR;
   4671     } else {
   4672         data = (data & DSC3B0_CDR_STATUS2_OSCDR_MODE_MASK) >>
   4673                DSC3B0_CDR_STATUS2_OSCDR_MODE_SHIFT;
   4674         switch (data) {
   4675         case 0:
   4676             *dsc_cfg = PHY_HL65_DSC_CFG_1X_OSR;
   4677             break;
   4678         case 1:
   4679             *dsc_cfg = PHY_HL65_DSC_CFG_2X_OSR;
   4680             break;
   4681         case 2:
   4682             *dsc_cfg = PHY_HL65_DSC_CFG_4X_OSR;
   4683             break;
   4684         case 3:
   4685             *dsc_cfg = PHY_HL65_DSC_CFG_5X_OSR;
   4686             break;
   4687         default:
   4688             *dsc_cfg = PHY_HL65_DSC_CFG_UNKNOWN;
   4689             rv = SOC_E_INTERNAL;
   4690             break;
   4691         }
   4692     }
   4693 
   4694     return rv;
   4695 }
   4696 
   4697 /*
   4698  * Return value range
   4699  */
   4700 STATIC int
   4701 _phy_hl65_control_serdes_tune_margin_max_get(int unit, soc_port_t port, 
   4702                                              int lane_num, uint32 *max)
   4703                                        
   4704 {
   4705     phy_hl65_dsc_cfg_t dsc_cfg;
   4706 
   4707     /* Get DSC config */
   4708     SOC_IF_ERROR_RETURN
   4709         (_phy_hl65_dsc_cfg_get(unit, port, lane_num, &dsc_cfg));
   4710 
   4711     switch  (dsc_cfg) {
   4712     case PHY_HL65_DSC_CFG_BR_CDR:
   4713         /* vertical diag */
   4714         *max = (1 << DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_BITS);
   4715         break;
   4716     case PHY_HL65_DSC_CFG_1X_OSR:
   4717     case PHY_HL65_DSC_CFG_2X_OSR:
   4718         /* horizontal diag 1xOSR 
   4719          * pi_phase_delta for 1xOSR == 1 so return full range
   4720          */
   4721         *max = (1 << DSC3B0_PI_STATUS0_CLK90_PHASE_OFFSET_BITS);
   4722         break;
   4723     default:
   4724         LOG_ERROR(BSL_LS_SOC_PHY,
   4725                   (BSL_META_U(unit,
   4726                               "Tune margin supported for 1XOSR, 2XOSR, "
   4727                               "BR CDR DSC")));
   4728         return SOC_E_UNAVAIL;
   4729     }
   4730     return SOC_E_NONE;
   4731 
   4732 }
   4733 
   4734 STATIC int
   4735 _phy_hl65_serdes_tune_margin_common_start(int unit, soc_port_t port, 
   4736                                           int lane_num)
   4737 {
   4738     uint16      data;
   4739     uint16      vga_sum_avg;
   4740     uint16      dfe_tap_bin_avg;
   4741     uint32      reg_addr;
   4742     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4743 
   4744     /* Step 1: check tuning done */
   4745     LOG_INFO(BSL_LS_SOC_PHY,
   4746              (BSL_META_U(unit,
   4747                          "Step 1: check tuning done\n")));
   4748     reg_addr = 0x82b7 + (lane_num * 0x10);
   4749     SOC_IF_ERROR_RETURN
   4750         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4751 
   4752     if (!(data & DSC3B0_SM_STATUS0_TUNING_DONE_MASK)) {
   4753         LOG_ERROR(BSL_LS_SOC_PHY,
   4754                   (BSL_META_U(unit,
   4755                               "ERROR: hc(%02d) tuning has not finished\n"), port));
   4756         return SOC_E_FAIL;
   4757     }
   4758 
   4759     /* Step 2: average vga_sum and dfe_tap_bin */
   4760     LOG_INFO(BSL_LS_SOC_PHY,
   4761              (BSL_META_U(unit,
   4762                          "Step 2: compute vga_sum, dfe_tap_bin average\n")));
   4763     SOC_IF_ERROR_RETURN
   4764         (_phy_hl65_tuning_status_get(unit, port, pc->lane_num,
   4765                                      &vga_sum_avg, &dfe_tap_bin_avg));
   4766 
   4767     /* Step 3: fix vga_sum and dfe_tab_bin  */
   4768     LOG_INFO(BSL_LS_SOC_PHY,
   4769              (BSL_META_U(unit,
   4770                          "Step 3: fix vga_sum, dfe_tap_bin\n")));
   4771     reg_addr = 0x8215 + (lane_num * 0x10);
   4772     SOC_IF_ERROR_RETURN
   4773         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4774 
   4775     data &= ~(DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_VAL_MASK |
   4776               DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_EN_MASK |
   4777               DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_VAL_MASK | 
   4778               DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_MASK);
   4779     data |= (vga_sum_avg << DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_VAL_SHIFT) |
   4780             (dfe_tap_bin_avg << DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_VAL_SHIFT);
   4781 
   4782     SOC_IF_ERROR_RETURN
   4783         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4784 
   4785     /* Now toggle the write enable bits */
   4786     data &= ~((DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_BITS << 
   4787                DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_SHIFT) |
   4788               (DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_EN_BITS <<
   4789                DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_EN_SHIFT));
   4790 
   4791     SOC_IF_ERROR_RETURN
   4792         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4793 
   4794     data |= (DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_BITS << 
   4795              DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_SHIFT) |
   4796             (DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_EN_BITS <<
   4797              DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_EN_SHIFT);
   4798 	
   4799     SOC_IF_ERROR_RETURN
   4800         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4801     /*
   4802      * Leave vga_write and dfe_write enabled - will be disabled
   4803      * when diag stops
   4804      */
   4805     return SOC_E_NONE;
   4806 }
   4807 
   4808 STATIC int
   4809 _phy_hl65_serdes_tune_margin_horizontal_start(int unit, soc_port_t port, 
   4810                                               int lane_num, 
   4811                                               phy_hl65_dsc_cfg_t dsc_cfg)
   4812 {
   4813     uint16      data, delta, exp_clk90_po;
   4814     uint32      reg_addr;
   4815     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4816 
   4817     SOC_IF_ERROR_RETURN
   4818         (_phy_hl65_serdes_tune_margin_common_start(unit, port, lane_num));
   4819 
   4820     /* 
   4821      * Step 4: verify clk90_phase_offset
   4822      *     ==32  1xOSR 
   4823      *     ==0   2xOSR 
   4824      */
   4825     LOG_INFO(BSL_LS_SOC_PHY,
   4826              (BSL_META_U(unit,
   4827                          "Step 4: verify clk90_phase_offset\n")));
   4828     reg_addr = 0x82b3 + (lane_num * 0x10);
   4829     SOC_IF_ERROR_RETURN
   4830         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4831     data = (data & DSC3B0_PI_STATUS0_CLK90_PHASE_OFFSET_MASK) >>
   4832            DSC3B0_PI_STATUS0_CLK90_PHASE_OFFSET_SHIFT;
   4833 
   4834     exp_clk90_po = (dsc_cfg == PHY_HL65_DSC_CFG_1X_OSR) ? 32 : 0;
   4835     if (data != exp_clk90_po) {
   4836         LOG_WARN(BSL_LS_SOC_PHY,
   4837                  (BSL_META_U(unit,
   4838                              "WARNING: hc(%02d) diag clk90 phase offset=%d " 
   4839                              "expected %d\nMake sure DSC is properly configured "
   4840                              "and tuning is done before running diag\n"),
   4841                   port, data, exp_clk90_po));
   4842     }
   4843 
   4844     /* Step 5: clk90 offset override */
   4845     LOG_INFO(BSL_LS_SOC_PHY,
   4846              (BSL_META_U(unit,
   4847                          "Step 5: enable clk90 offset override\n")));
   4848     reg_addr = 0x8213 + (lane_num * 0x10);
   4849     SOC_IF_ERROR_RETURN
   4850         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4851     data |= (DSC1B0_PI_CTRL0_PI_CLK90_OFFSET_OVERRIDE_BITS  << 
   4852              DSC1B0_PI_CTRL0_PI_CLK90_OFFSET_OVERRIDE_SHIFT);
   4853     SOC_IF_ERROR_RETURN
   4854         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4855 
   4856     /* Step 6:  pi_phase_delta */
   4857     LOG_INFO(BSL_LS_SOC_PHY,
   4858              (BSL_META_U(unit,
   4859                          "Step 6: set pi_phase_delta\n")));
   4860     if (dsc_cfg == PHY_HL65_DSC_CFG_1X_OSR) {
   4861         /* 1xOSR */
   4862         delta = 1;
   4863     } else if (dsc_cfg == PHY_HL65_DSC_CFG_2X_OSR) {
   4864         delta = 2;
   4865     } else {
   4866         LOG_ERROR(BSL_LS_SOC_PHY,
   4867                   (BSL_META_U(unit,
   4868                               "ERROR: hc(%02d) invalid DSC config\n"), 
   4869                               port));
   4870         return SOC_E_PARAM;
   4871     }
   4872         
   4873     data = (data & ~(DSC1B0_PI_CTRL0_PI_PHASE_DELTA_MASK)) |
   4874            (delta << DSC1B0_PI_CTRL0_PI_PHASE_DELTA_SHIFT);
   4875     SOC_IF_ERROR_RETURN
   4876         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4877 
   4878     return SOC_E_NONE;
   4879 }
   4880 
   4881 STATIC int
   4882 _phy_hl65_serdes_tune_margin_horizontal_adjust(int unit, soc_port_t port, 
   4883                                                int lane_num, uint32 inc)
   4884 {
   4885     uint16      data;
   4886     uint32      reg_addr;
   4887     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4888 
   4889     /* 
   4890      * Step 7: set phase offset moving direction 
   4891      */
   4892     LOG_INFO(BSL_LS_SOC_PHY,
   4893              (BSL_META_U(unit,
   4894                          "Step 7: set phase offset moving direction\n")));
   4895     reg_addr = 0x8213 + (lane_num * 0x10);
   4896     SOC_IF_ERROR_RETURN
   4897         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4898 
   4899     data &= ~(DSC1B0_PI_CTRL0_PI_PHASE_INC_MASK |
   4900               DSC1B0_PI_CTRL0_PI_PHASE_DEC_MASK);
   4901 
   4902     if (inc == 1) {
   4903         data |= (DSC1B0_PI_CTRL0_PI_PHASE_INC_BITS <<
   4904                  DSC1B0_PI_CTRL0_PI_PHASE_INC_SHIFT);
   4905     } else if (inc == 0) {
   4906         data |= (DSC1B0_PI_CTRL0_PI_PHASE_DEC_BITS <<
   4907                  DSC1B0_PI_CTRL0_PI_PHASE_DEC_SHIFT);
   4908     } else {
   4909         LOG_ERROR(BSL_LS_SOC_PHY,
   4910                   (BSL_META_U(unit,
   4911                               "ERROR: hc(%02d) diag invalid adjust\n"),
   4912                    port));
   4913         return SOC_E_PARAM;
   4914     }
   4915              
   4916     /* Step 8: toggle pi phase strobe */
   4917     LOG_INFO(BSL_LS_SOC_PHY,
   4918              (BSL_META_U(unit,
   4919                          "Step 8: toggle pi phase strobe\n")));
   4920     data &= ~(DSC1B0_PI_CTRL0_PI_PHASE_STROBE_BITS <<
   4921               DSC1B0_PI_CTRL0_PI_PHASE_STROBE_SHIFT);
   4922     SOC_IF_ERROR_RETURN
   4923         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4924 
   4925     data |= (DSC1B0_PI_CTRL0_PI_PHASE_STROBE_BITS <<
   4926              DSC1B0_PI_CTRL0_PI_PHASE_STROBE_SHIFT);
   4927     SOC_IF_ERROR_RETURN
   4928         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4929 
   4930     data &= ~(DSC1B0_PI_CTRL0_PI_PHASE_STROBE_BITS <<
   4931               DSC1B0_PI_CTRL0_PI_PHASE_STROBE_SHIFT);
   4932     SOC_IF_ERROR_RETURN
   4933         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4934 
   4935     return SOC_E_NONE;
   4936 }
   4937 
   4938 
   4939 STATIC int
   4940 _phy_hl65_serdes_tune_margin_horizontal_stop(int unit, soc_port_t port,
   4941                                              int lane_num, 
   4942                                              phy_hl65_dsc_cfg_t dsc_cfg) 
   4943                                        
   4944 {
   4945     uint16      data;
   4946     uint32      reg_addr;
   4947     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4948 
   4949     /* 
   4950      * Step 11: restore pi_clk90_offset_override, 
   4951      *          pi_phase_data, pi_phase_inc/dec
   4952      */
   4953     LOG_INFO(BSL_LS_SOC_PHY,
   4954              (BSL_META_U(unit,
   4955                          "Step 11: restore values\n")));
   4956     reg_addr = 0x8213 + (lane_num * 0x10);
   4957     SOC_IF_ERROR_RETURN
   4958         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4959 
   4960     data &= ~(DSC1B0_PI_CTRL0_PI_CLK90_OFFSET_OVERRIDE_MASK |
   4961               DSC1B0_PI_CTRL0_PI_PHASE_DELTA_MASK |
   4962               DSC1B0_PI_CTRL0_PI_PHASE_INC_MASK |
   4963               DSC1B0_PI_CTRL0_PI_PHASE_DEC_MASK);
   4964     SOC_IF_ERROR_RETURN
   4965         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4966 
   4967     /* Step 12,13: release vga_write and dfe_write */
   4968     LOG_INFO(BSL_LS_SOC_PHY,
   4969              (BSL_META_U(unit,
   4970                          "Step 12: release vga_write, dfe_write enable\n")));
   4971     reg_addr = 0x8215 + (lane_num * 0x10);
   4972     SOC_IF_ERROR_RETURN
   4973         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   4974     data &= ~(DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_VAL_MASK |
   4975               DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_VAL_MASK);
   4976     SOC_IF_ERROR_RETURN
   4977         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4978 
   4979     data &= ~((DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_EN_BITS <<
   4980               DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_EN_SHIFT) |
   4981               (DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_BITS <<
   4982                DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_SHIFT));
   4983     SOC_IF_ERROR_RETURN
   4984         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   4985 
   4986     return SOC_E_NONE;
   4987 }
   4988 
   4989 STATIC int
   4990 _phy_hl65_serdes_tune_margin_horizontal_value_get(int unit, soc_port_t port, 
   4991                                                     int lane_num, 
   4992                                                     uint32 *value)
   4993 {
   4994     uint16      data;
   4995     uint32      reg_addr;
   4996     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   4997 
   4998     reg_addr = 0x82b3 + (lane_num * 0x10);
   4999     SOC_IF_ERROR_RETURN
   5000         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   5001 
   5002     *value = (data & DSC3B0_PI_STATUS0_CLK90_PHASE_OFFSET_MASK) >>
   5003              DSC3B0_PI_STATUS0_CLK90_PHASE_OFFSET_SHIFT;
   5004 
   5005     /* 
   5006      * External values are scaled 
   5007      *
   5008      * Internal range 0..127
   5009      *
   5010      *    Internal Value        Scaled Value
   5011      *   Signed / Unsigned       Unsigned
   5012      *      0        0               64
   5013      *      1        1               65
   5014      *      2        2               66
   5015      *     ..       ..               ..
   5016      *     63       63               127
   5017      *    -64       64               0 
   5018      *    -63       65               1
   5019      *     -1      127               63
   5020  */
   5021     *value = (*value + 64) & 
   5022              (DSC3B0_PI_STATUS0_CLK90_PHASE_OFFSET_MASK >>
   5023               DSC3B0_PI_STATUS0_CLK90_PHASE_OFFSET_SHIFT);
   5024     return SOC_E_NONE;
   5025 }
   5026 
   5027 /* 
   5028  * Horizontal adjust 
   5029  */
   5030 STATIC int
   5031 _phy_hl65_serdes_tune_margin_horizontal_value_set(int unit, soc_port_t port, 
   5032                                                   int lane_num, 
   5033                                                   phy_hl65_dsc_cfg_t dsc_cfg,
   5034                                                   uint32 value)
   5035 {
   5036     uint32              max, cur_value, 
   5037                         inc = 0;
   5038     int                 i, steps;
   5039 
   5040     SOC_IF_ERROR_RETURN
   5041         (_phy_hl65_control_serdes_tune_margin_max_get(unit, port, lane_num, 
   5042                                                       &max));
   5043     
   5044     if (value > max) {
   5045         LOG_ERROR(BSL_LS_SOC_PHY,
   5046                   (BSL_META_U(unit,
   5047                               "Invalid value %d (0..%d)\n"), 
   5048                               value, max-1));
   5049         return SOC_E_PARAM;
   5050     }
   5051 
   5052     SOC_IF_ERROR_RETURN
   5053         (_phy_hl65_serdes_tune_margin_horizontal_value_get(unit, port, 
   5054                                                            lane_num, 
   5055                                                            &cur_value));
   5056     if (value < cur_value) {
   5057         steps = cur_value - value;
   5058         inc = 0;
   5059     } else if (value > cur_value) {
   5060         steps = value - cur_value;
   5061         inc = 1;
   5062     } else {
   5063         return SOC_E_NONE;
   5064     }
   5065     if (dsc_cfg == PHY_HL65_DSC_CFG_2X_OSR) {
   5066         /* 2xOSR steps by 2 */
   5067         steps /= 2;
   5068     }
   5069 
   5070     LOG_INFO(BSL_LS_SOC_PHY,
   5071              (BSL_META_U(unit,
   5072                          "horizontal adjusting to %d from %d steps %d\n"),
   5073                          value, cur_value, steps));
   5074 
   5075     /* Adjust to value */
   5076     for (i = 0; i < steps; i++) {
   5077         SOC_IF_ERROR_RETURN
   5078             (_phy_hl65_serdes_tune_margin_horizontal_adjust(unit, port, 
   5079                                                             lane_num, inc));
   5080     }
   5081 
   5082     /* Verify if got there */
   5083     SOC_IF_ERROR_RETURN
   5084         (_phy_hl65_serdes_tune_margin_horizontal_value_get(unit, port, 
   5085                                                            lane_num, 
   5086                                                            &cur_value));
   5087 
   5088     /* Adjust if 2xOSR to increment in steps by 2 */
   5089     if ((dsc_cfg == PHY_HL65_DSC_CFG_2X_OSR) && (value % 2)) {
   5090         value--;
   5091     }
   5092 
   5093     if (cur_value != value) {
   5094         LOG_WARN(BSL_LS_SOC_PHY,
   5095                  (BSL_META_U(unit,
   5096                              "WARNING: Adjusted value %d does not match requested "
   5097                              "value  %d\n"), cur_value, value));
   5098     }
   5099     return SOC_E_NONE;
   5100 }
   5101     
   5102 
   5103 STATIC int
   5104 _phy_hl65_serdes_tune_margin_vertical_start(int unit, soc_port_t port, 
   5105                                             int lane_num)
   5106 {
   5107     uint16      data;
   5108     uint16      slicer_offset_me, slicer_offset_ze, slicer_offset_pe;
   5109     uint32      reg_addr;
   5110     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   5111 
   5112 
   5113     SOC_IF_ERROR_RETURN
   5114         (_phy_hl65_serdes_tune_margin_common_start(unit, port, lane_num));
   5115 
   5116     /* Step 4: read slicer offset status */
   5117     LOG_INFO(BSL_LS_SOC_PHY,
   5118              (BSL_META_U(unit,
   5119                          "Step 4: read slice offset status\n")));
   5120     reg_addr = 0x82ba + (lane_num * 0x10);
   5121     SOC_IF_ERROR_RETURN
   5122         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   5123 
   5124     slicer_offset_me = (data & DSC3B0_SM_STATUS3_SLICER_OFFSET_ME_MASK) >>
   5125                        DSC3B0_SM_STATUS3_SLICER_OFFSET_ME_SHIFT;
   5126 
   5127     slicer_offset_ze = (data & DSC3B0_SM_STATUS3_SLICER_OFFSET_ZE_MASK) >>
   5128                        DSC3B0_SM_STATUS3_SLICER_OFFSET_ZE_SHIFT;
   5129 
   5130     slicer_offset_pe = (data & DSC3B0_SM_STATUS3_SLICER_OFFSET_PE_MASK) >>
   5131                        DSC3B0_SM_STATUS3_SLICER_OFFSET_PE_SHIFT;
   5132 
   5133     /* Step 5: write slicer offsets to control */
   5134     LOG_INFO(BSL_LS_SOC_PHY,
   5135              (BSL_META_U(unit,
   5136                          "Step 5: write slice offset status\n")));
   5137     reg_addr = 0x821b + (lane_num * 0x10);
   5138     SOC_IF_ERROR_RETURN
   5139         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   5140 
   5141     data &= ~( DSC1B0_DSC_ANA_CTRL1_P1_EVN_CTRL_MASK |
   5142                DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_MASK |
   5143                DSC1B0_DSC_ANA_CTRL1_M1_EVN_CTRL_MASK);
   5144     data |= (slicer_offset_me << DSC1B0_DSC_ANA_CTRL1_M1_EVN_CTRL_SHIFT) |
   5145             (slicer_offset_ze << DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_SHIFT) |
   5146             (slicer_offset_pe << DSC1B0_DSC_ANA_CTRL1_P1_EVN_CTRL_SHIFT);
   5147     SOC_IF_ERROR_RETURN
   5148         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   5149 
   5150     return SOC_E_NONE;
   5151 }
   5152 
   5153 STATIC int
   5154 _phy_hl65_serdes_tune_margin_vertical_adjust(int unit, soc_port_t port, 
   5155                                              int lane_num, uint32 inc)
   5156 {
   5157     uint16      data;
   5158     int16       tmp;
   5159     uint32      reg_addr;
   5160     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   5161 
   5162     /* 
   5163      * Step 6: perturb data even slicer
   5164      */
   5165     LOG_INFO(BSL_LS_SOC_PHY,
   5166              (BSL_META_U(unit,
   5167                          "Step 6: perturb data even slicer\n")));
   5168     reg_addr = 0x821b + (lane_num * 0x10);
   5169     SOC_IF_ERROR_RETURN
   5170         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   5171     
   5172     tmp = (data & DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_MASK)
   5173            >> DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_SHIFT;
   5174     
   5175     if (inc == 1) {
   5176         /* increment */
   5177         if (tmp == 0xf) {
   5178             LOG_ERROR(BSL_LS_SOC_PHY,
   5179                       (BSL_META_U(unit,
   5180                                   "ERROR: hc(%02d) cannot increment anymore\n"),
   5181                        port));
   5182             return SOC_E_PARAM;
   5183         }
   5184         tmp++;
   5185     } else if (inc == 0) {
   5186         /* decrement */
   5187         if (tmp == 0x10) {
   5188             LOG_ERROR(BSL_LS_SOC_PHY,
   5189                       (BSL_META_U(unit,
   5190                                   "ERROR: hc(%02d) cannot decrement anymore\n"),
   5191                        port));
   5192             return SOC_E_PARAM;
   5193         }
   5194         tmp--;
   5195     } else {
   5196         LOG_ERROR(BSL_LS_SOC_PHY,
   5197                   (BSL_META_U(unit,
   5198                               "ERROR: hc(%02d) diag invalid operation\n"), 
   5199                               port));
   5200         return SOC_E_PARAM;
   5201     }
   5202     data &= ~(DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_MASK);
   5203     data |= (tmp << DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_SHIFT) |
   5204             (DSC1B0_DSC_ANA_CTRL1_FORCE_EVN_CTRL_BITS <<
   5205              DSC1B0_DSC_ANA_CTRL1_FORCE_EVN_CTRL_SHIFT);
   5206     SOC_IF_ERROR_RETURN
   5207         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   5208 
   5209     /* Toggle force even - required? */
   5210     data &= ~(DSC1B0_DSC_ANA_CTRL1_FORCE_EVN_CTRL_BITS <<
   5211               DSC1B0_DSC_ANA_CTRL1_FORCE_EVN_CTRL_SHIFT);
   5212     SOC_IF_ERROR_RETURN
   5213         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   5214 
   5215     return SOC_E_NONE;
   5216 }
   5217 
   5218 
   5219 STATIC int
   5220 _phy_hl65_serdes_tune_margin_vertical_value_get(int unit, soc_port_t port, 
   5221                                                 int lane_num, uint32 *value)
   5222 {
   5223     uint16      data;
   5224     uint32      reg_addr;
   5225     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   5226 
   5227     reg_addr = 0x821b + (lane_num * 0x10);
   5228     SOC_IF_ERROR_RETURN
   5229         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   5230     
   5231     *value = (data & DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_MASK)
   5232                >> DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_SHIFT;
   5233 
   5234     /* Scale value */
   5235     *value = (*value + 16) &
   5236              (DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_MASK >>
   5237               DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_SHIFT);
   5238     return SOC_E_NONE;
   5239 }
   5240 
   5241 STATIC int
   5242 _phy_hl65_serdes_tune_margin_vertical_value_set(int unit, soc_port_t port, 
   5243                                                 int lane_num, uint32 value)
   5244 {
   5245     int         i, steps;
   5246     uint32      cur_value, max, inc = 0;
   5247 
   5248     
   5249     SOC_IF_ERROR_RETURN
   5250         (_phy_hl65_control_serdes_tune_margin_max_get(unit, port, lane_num, 
   5251                                                       &max));
   5252     
   5253     if (value > max) {
   5254         LOG_ERROR(BSL_LS_SOC_PHY,
   5255                   (BSL_META_U(unit,
   5256                               "Invalid value %d (0..%d)\n"), value, max));
   5257         return SOC_E_PARAM;
   5258     }
   5259 
   5260     SOC_IF_ERROR_RETURN
   5261         (_phy_hl65_serdes_tune_margin_vertical_value_get(unit, port, 
   5262                                                          lane_num, 
   5263                                                          &cur_value));
   5264     if (value < cur_value) {
   5265         steps = cur_value - value;
   5266         inc = 0;
   5267     } else if (value > cur_value) {
   5268         steps = value - cur_value;
   5269         inc = 1;
   5270     } else {
   5271         return SOC_E_NONE;
   5272     }
   5273     
   5274     /* Adjust to value */
   5275     for (i = 0; i < steps; i++) {
   5276         SOC_IF_ERROR_RETURN
   5277             (_phy_hl65_serdes_tune_margin_vertical_adjust(unit, port, 
   5278                                                           lane_num, 
   5279                                                           inc));
   5280     }
   5281 
   5282     /* Verify if got there */
   5283     SOC_IF_ERROR_RETURN
   5284         (_phy_hl65_serdes_tune_margin_vertical_value_get(unit, port, 
   5285                                                          lane_num, 
   5286                                                          &cur_value));
   5287     if (cur_value != value) {
   5288         LOG_WARN(BSL_LS_SOC_PHY,
   5289                  (BSL_META_U(unit,
   5290                              "Adjusted value %d does not match "
   5291                              "requested value %d\n"), cur_value, value));
   5292     }
   5293     return SOC_E_NONE;
   5294 }
   5295 
   5296 STATIC int
   5297 _phy_hl65_serdes_tune_margin_vertical_stop(int unit, soc_port_t port, 
   5298                                            int lane_num)
   5299 {
   5300     uint16      data;
   5301     uint32      reg_addr;
   5302     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   5303 
   5304     /* 
   5305      * Step 9: restore all slice offset control registers to 0
   5306      */
   5307     LOG_INFO(BSL_LS_SOC_PHY,
   5308              (BSL_META_U(unit,
   5309                          "Step 9: restore slice offset\n")));
   5310     reg_addr = 0x821b + (lane_num * 0x10);
   5311     SOC_IF_ERROR_RETURN
   5312         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   5313 
   5314     data &= ~( DSC1B0_DSC_ANA_CTRL1_P1_EVN_CTRL_MASK |
   5315                DSC1B0_DSC_ANA_CTRL1_D_EVN_CTRL_MASK |
   5316                DSC1B0_DSC_ANA_CTRL1_M1_EVN_CTRL_MASK);
   5317     SOC_IF_ERROR_RETURN
   5318         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   5319 
   5320     /*
   5321      * Step 10: release and restore vga_write and dfe_write 
   5322      */
   5323     LOG_INFO(BSL_LS_SOC_PHY,
   5324              (BSL_META_U(unit,
   5325                          "Step 10: release vga_write, dfe_write enable\n")));
   5326     reg_addr = 0x8215 + (lane_num * 0x10);
   5327     SOC_IF_ERROR_RETURN
   5328         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   5329     data &= ~(DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_VAL_MASK |
   5330               DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_VAL_MASK);
   5331     SOC_IF_ERROR_RETURN
   5332         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   5333 
   5334     data &= ~((DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_EN_BITS <<
   5335               DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_EN_SHIFT) |
   5336               (DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_BITS <<
   5337                DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_SHIFT));
   5338     SOC_IF_ERROR_RETURN
   5339         (HL65_REG_WRITE(unit,pc,0x0,reg_addr, data));
   5340 
   5341     return SOC_E_NONE;
   5342 }
   5343 
   5344 
   5345 STATIC int
   5346 _phy_hl65_serdes_tune_margin_horizontal_mode_set(int unit, 
   5347                                                  soc_port_t port, int lane_num, 
   5348                                                  uint32 start,
   5349                                                  phy_hl65_dsc_cfg_t dsc_cfg) 
   5350 {
   5351     if (start) {
   5352         SOC_IF_ERROR_RETURN
   5353             (_phy_hl65_serdes_tune_margin_horizontal_start(unit, port, 
   5354                                                            lane_num,
   5355                                                            dsc_cfg));
   5356     } else {
   5357         SOC_IF_ERROR_RETURN
   5358             (_phy_hl65_serdes_tune_margin_horizontal_stop(unit, port, 
   5359                                                           lane_num,
   5360                                                           dsc_cfg));
   5361     }
   5362     return SOC_E_NONE;
   5363 }
   5364 
   5365 
   5366 STATIC int
   5367 _phy_hl65_serdes_tune_margin_vertical_mode_set(int unit, 
   5368                                                soc_port_t port, 
   5369                                                int lane_num,
   5370                                                uint32 start) 
   5371 {
   5372     if (start) {
   5373         SOC_IF_ERROR_RETURN
   5374             (_phy_hl65_serdes_tune_margin_vertical_start(unit, port, 
   5375                                                          lane_num));
   5376     } else {
   5377         SOC_IF_ERROR_RETURN
   5378             (_phy_hl65_serdes_tune_margin_vertical_stop(unit, port, 
   5379                                                         lane_num));
   5380     }
   5381     return SOC_E_NONE;
   5382 
   5383 }
   5384 
   5385 /*
   5386  * Start/stop HC diag 
   5387  */
   5388 STATIC int
   5389 _phy_hl65_control_serdes_tune_margin_mode_set(int unit, soc_port_t port, 
   5390                                               int lane_num, uint32 start) 
   5391                                        
   5392 {
   5393     phy_hl65_dsc_cfg_t dsc_cfg;
   5394 
   5395     /* Get DSC config */
   5396     SOC_IF_ERROR_RETURN
   5397         (_phy_hl65_dsc_cfg_get(unit, port, lane_num, &dsc_cfg));
   5398 
   5399     switch  (dsc_cfg) {
   5400     case PHY_HL65_DSC_CFG_BR_CDR:
   5401         /* vertical diag */
   5402         SOC_IF_ERROR_RETURN
   5403             (_phy_hl65_serdes_tune_margin_vertical_mode_set(unit, port, 
   5404                                                             lane_num, start));
   5405         break;
   5406     case PHY_HL65_DSC_CFG_1X_OSR:
   5407     case PHY_HL65_DSC_CFG_2X_OSR:
   5408         /* horizontal diag */
   5409         SOC_IF_ERROR_RETURN
   5410             (_phy_hl65_serdes_tune_margin_horizontal_mode_set(unit, port, 
   5411                                                               lane_num, start,
   5412                                                               dsc_cfg));
   5413         break;
   5414     default:
   5415         LOG_WARN(BSL_LS_SOC_PHY,
   5416                  (BSL_META_U(unit,
   5417                              "Tune margin supported for 1XOSR, 2XOSR, BR CDR DSC")));
   5418         return SOC_E_UNAVAIL;
   5419     }
   5420     return SOC_E_NONE;
   5421 }
   5422 
   5423 /*
   5424  * Check whether diag is running or not 
   5425  */
   5426 STATIC int
   5427 _phy_hl65_control_serdes_tune_margin_mode_get(int unit, soc_port_t port, 
   5428                                               int lane_num, uint32 *value) 
   5429                                        
   5430 {
   5431 
   5432     uint16      data;
   5433     uint32      reg_addr;
   5434     phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);
   5435 
   5436     /* Read write enable */    
   5437     reg_addr = 0x8215 + (lane_num * 0x10);
   5438     SOC_IF_ERROR_RETURN
   5439         (HL65_REG_READ(unit,pc,0x0,reg_addr, &data));
   5440 
   5441     /* 
   5442      * Assumption here is that DFE and VGA write is only enabled
   5443      * while running diag
   5444      */
   5445     *value =  ((data & DSC1B0_DFE_VGA_CTRL1_DFE_WRITE_EN_MASK) &&
   5446                (data & DSC1B0_DFE_VGA_CTRL1_VGA_WRITE_EN_MASK)) ? 1 : 0;
   5447 
   5448     return SOC_E_NONE;
   5449 }
   5450 
   5451 
   5452 
   5453 /*
   5454  * Return value depending on DSC configuration
   5455  */
   5456 STATIC int
   5457 _phy_hl65_control_serdes_tune_margin_value_get(int unit, soc_port_t port, 
   5458                                                int lane_num, uint32 *value)
   5459                                        
   5460 {
   5461     phy_hl65_dsc_cfg_t dsc_cfg;
   5462 
   5463     /* Get DSC config */
   5464     SOC_IF_ERROR_RETURN
   5465         (_phy_hl65_dsc_cfg_get(unit, port, lane_num, &dsc_cfg));
   5466 
   5467     switch  (dsc_cfg) {
   5468     case PHY_HL65_DSC_CFG_BR_CDR:
   5469         /* vertical diag */
   5470         SOC_IF_ERROR_RETURN
   5471             (_phy_hl65_serdes_tune_margin_vertical_value_get(unit, port, 
   5472                                                              lane_num,
   5473                                                              value));
   5474         break;
   5475     case PHY_HL65_DSC_CFG_1X_OSR:
   5476     case PHY_HL65_DSC_CFG_2X_OSR:
   5477         /* horizontal diag 1xOSR */
   5478         SOC_IF_ERROR_RETURN
   5479             (_phy_hl65_serdes_tune_margin_horizontal_value_get(unit, port, 
   5480                                                                lane_num,
   5481                                                                value));
   5482         break;
   5483     default:
   5484         LOG_WARN(BSL_LS_SOC_PHY,
   5485                  (BSL_META_U(unit,
   5486                              "Tune margin supported for 1XOSR, 2XOSR, "
   5487                              "BR CDR DSC\n")));
   5488         return SOC_E_UNAVAIL;
   5489     }
   5490     return SOC_E_NONE;
   5491 }
   5492 
   5493 
   5494 /*
   5495  * Adjust to requested value
   5496  */
   5497 STATIC int
   5498 _phy_hl65_control_serdes_tune_margin_value_set(int unit, soc_port_t port, 
   5499                                                int lane_num, uint32 value)
   5500                                        
   5501 {
   5502     phy_hl65_dsc_cfg_t dsc_cfg;
   5503 
   5504     /* Get DSC config */
   5505     SOC_IF_ERROR_RETURN
   5506         (_phy_hl65_dsc_cfg_get(unit, port, lane_num, &dsc_cfg));
   5507 
   5508     switch  (dsc_cfg) {
   5509     case PHY_HL65_DSC_CFG_BR_CDR:
   5510         /* vertical diag */
   5511         SOC_IF_ERROR_RETURN
   5512             (_phy_hl65_serdes_tune_margin_vertical_value_set(unit, port, 
   5513                                                              lane_num, value));
   5514         break;
   5515     case PHY_HL65_DSC_CFG_1X_OSR:
   5516     case PHY_HL65_DSC_CFG_2X_OSR:
   5517         SOC_IF_ERROR_RETURN
   5518             (_phy_hl65_serdes_tune_margin_horizontal_value_set(unit, port, 
   5519                                                                lane_num, 
   5520                                                                dsc_cfg,
   5521                                                                value));
   5522         break;
   5523     default:
   5524         LOG_WARN(BSL_LS_SOC_PHY,
   5525                  (BSL_META_U(unit,
   5526                              "Tune margin supported for 1XOSR, 2XOSR, BR CDR DSC")));
   5527         return SOC_E_UNAVAIL;
   5528     }
   5529     return SOC_E_NONE;
   5530 }
   5531 
   5532 /*
   5533  * Function:
   5534  *      phy_hl65_control_set
   5535  * Purpose:
   5536  *      Configure PHY device specific control fucntion. 
   5537  * Parameters:
   5538  *      unit  - StrataSwitch unit #.
   5539  *      port  - StrataSwitch port #. 
   5540  *      type  - Control to update 
   5541  *      value - New setting for the control 
   5542  * Returns:     
   5543  *      SOC_E_NONE
   5544  */
   5545 STATIC int
   5546 phy_hl65_control_set(int unit, soc_port_t port,
   5547                      soc_phy_control_t type, uint32 value)
   5548 {
   5549     int rv;
   5550     phy_ctrl_t *pc;
   5551     int i;
   5552     /* coverity[mixed_enums] */
   5553     if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) {
   5554         return SOC_E_PARAM;
   5555     }
   5556    
   5557     pc = INT_PHY_SW_STATE(unit, port);
   5558     rv = SOC_E_UNAVAIL;
   5559     switch(type) {
   5560     case SOC_PHY_CONTROL_PREEMPHASIS:
   5561         /* fall through */
   5562     case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   5563         /* fall through */
   5564     case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   5565         /* fall through */
   5566     case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   5567         /* fall through */
   5568     case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   5569         /* fall through */
   5570     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   5571         /* fall through */
   5572     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   5573         /* fall through */
   5574     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   5575         /* fall through */
   5576     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   5577         /* fall through */
   5578     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   5579         /* fall through */
   5580     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   5581         /* fall through */
   5582     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   5583         /* fall through */
   5584     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   5585         /* fall through */
   5586     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   5587         /* fall through */
   5588     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   5589         /* fall through */
   5590     case SOC_PHY_CONTROL_PRE_PREEMPHASIS:
   5591         rv = _phy_hl65_control_tx_driver_set(unit, pc, type, value);
   5592         break;
   5593     case SOC_PHY_CONTROL_ENCODING:
   5594         rv = _phy_hl65_control_encoding_set(unit, port, value);
   5595         break;
   5596     case SOC_PHY_CONTROL_SCRAMBLER:
   5597         rv = _phy_hl65_control_scrambler_set(unit, port, value);
   5598         break;
   5599     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   5600         rv = _phy_hl65_control_prbs_polynomial_set(unit, port, value);
   5601         break;
   5602     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   5603         rv = _phy_hl65_control_prbs_tx_invert_data_set(unit, port, value);
   5604         break;
   5605     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   5606         rv = _phy_hl65_control_prbs_tx_enable_set(unit, port, value);
   5607         break;
   5608     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   5609         rv = _phy_hl65_control_prbs_rx_enable_set(unit, port, value);
   5610         break;
   5611     case SOC_PHY_CONTROL_SERDES_DRIVER_TUNE:
   5612         if (PHY_INDEPENDENT_LANE_MODE(unit, port) || 
   5613             PHY_HC65_FABRIC_MODE(unit, port)) {
   5614             rv = _phy_hl65_control_serdes_driver_tune_set(unit, port, 
   5615                   pc->lane_num,value);
   5616         } else {
   5617             for (i = 0; i < HL65_NUM_LANES; i++) {
   5618                 rv = _phy_hl65_control_serdes_driver_tune_set(unit, port, 
   5619                           i ,value);
   5620                 if (rv != SOC_E_NONE) {
   5621                     break;
   5622                 }
   5623             }
   5624         } 
   5625         break;
   5626     case SOC_PHY_CONTROL_8B10B:
   5627         rv = _phy_hl65_control_8b10b_set(unit, port, value);
   5628         break;
   5629     case SOC_PHY_CONTROL_64B66B:
   5630         rv = _phy_hl65_control_64b66b_set(unit, port, value);
   5631 	break;
   5632     case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT:
   5633         rv = _phy_hl65_control_linkdown_transmit_set(unit, port, value);
   5634         break;
   5635     case SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_MODE:
   5636         if (PHY_HC65_FABRIC_MODE(unit, port)) {    
   5637             rv = _phy_hl65_control_serdes_tune_margin_mode_set(unit, port, 
   5638                                                                pc->lane_num, 
   5639                                                                value);
   5640         } else {
   5641            rv = SOC_E_UNAVAIL;
   5642         }
   5643         break;
   5644     case SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_VALUE:
   5645         if (PHY_HC65_FABRIC_MODE(unit, port)) {    
   5646             rv = _phy_hl65_control_serdes_tune_margin_value_set(unit, port, 
   5647                                                             pc->lane_num,
   5648                                                             value);
   5649         } else {
   5650             rv = SOC_E_UNAVAIL;
   5651         }
   5652         break;
   5653     case SOC_PHY_CONTROL_PARALLEL_DETECTION:
   5654         /* enable 1000X parallel detect */
   5655         SOC_IF_ERROR_RETURN
   5656             (MODIFY_HL65_DIGITAL_CONTROL1000X2r(unit, pc, 
   5657               value? DIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK:0, 
   5658               DIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK));
   5659         rv = SOC_E_NONE;
   5660         break;
   5661     case SOC_PHY_CONTROL_EQUALIZER_BOOST:
   5662        /*
   5663           RX Equalizer Boost settings for stack ports
   5664           So modifying register 0x1C(RX0/1/2/3_ANACONTROL) 
   5665           of block 0x8250 (reg 0x825C)
   5666         */
   5667         SOC_IF_ERROR_RETURN
   5668             (HL65_REG_WRITE(unit, pc, 0x0, 0x825C, value));
   5669         rv = SOC_E_NONE;
   5670         break;
   5671     default:
   5672         rv = SOC_E_UNAVAIL;
   5673         break; 
   5674     }
   5675     return rv;
   5676 }
   5677 
   5678 /*
   5679  * Function:
   5680  *      phy_hl65_control_get
   5681  * Purpose:
   5682  *      Get current control settign of the PHY. 
   5683  * Parameters:
   5684  *      unit  - StrataSwitch unit #.
   5685  *      port  - StrataSwitch port #. 
   5686  *      type  - Control to update 
   5687  *      value - (OUT)Current setting for the control 
   5688  * Returns:     
   5689  *      SOC_E_NONE
   5690  */
   5691 STATIC int
   5692 phy_hl65_control_get(int unit, soc_port_t port,
   5693                      soc_phy_control_t type, uint32 *value)
   5694 {
   5695     int rv;
   5696     phy_ctrl_t *pc;
   5697     int i;
   5698     uint16 data16 = 0;
   5699 
   5700     if (NULL == value) {
   5701         return SOC_E_PARAM;
   5702     }
   5703     /* coverity[mixed_enums] */
   5704     if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) {
   5705         return SOC_E_PARAM;
   5706     }
   5707    
   5708     pc = INT_PHY_SW_STATE(unit, port);
   5709     rv = SOC_E_UNAVAIL;
   5710     switch(type) {
   5711     case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   5712         /* fall through */
   5713     case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   5714         /* fall through */
   5715     case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   5716         /* fall through */
   5717     case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   5718         /* fall through */
   5719     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   5720         /* fall through */
   5721     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   5722         /* fall through */
   5723     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   5724         /* fall through */
   5725     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   5726         /* fall through */
   5727     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   5728         /* fall through */
   5729     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   5730         /* fall through */
   5731     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   5732         /* fall through */
   5733     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   5734         /* fall through */
   5735     case SOC_PHY_CONTROL_PREEMPHASIS:
   5736         /* fall through */
   5737     case SOC_PHY_CONTROL_PRE_PREEMPHASIS:
   5738         /* fall through */
   5739     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   5740         /* fall through */
   5741     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   5742         rv = _phy_hl65_control_tx_driver_get(unit, pc, type, value);
   5743         break;
   5744     case SOC_PHY_CONTROL_SCRAMBLER:
   5745         rv = _phy_hl65_control_scrambler_get(unit, port, value);
   5746         break;
   5747     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   5748         rv = _phy_hl65_control_prbs_polynomial_get(unit, port, value);
   5749         break;
   5750     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   5751         rv = _phy_hl65_control_prbs_tx_invert_data_get(unit, port, value);
   5752         break;
   5753     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   5754         rv = _phy_hl65_control_prbs_tx_enable_get(unit, port, value);
   5755         break;
   5756     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   5757         rv = _phy_hl65_control_prbs_rx_enable_get(unit, port, value);
   5758         break;
   5759     case SOC_PHY_CONTROL_PRBS_RX_STATUS:
   5760         rv = _phy_hl65_control_prbs_rx_status_get(unit, port, value);
   5761         break;
   5762     case SOC_PHY_CONTROL_SERDES_DRIVER_EQUALIZATION_TUNE_STATUS_FAR_END:
   5763         if (PHY_INDEPENDENT_LANE_MODE(unit, port) || 
   5764             PHY_HC65_FABRIC_MODE(unit, port)) {
   5765             rv = _phy_hl65_control_eq_tune_status_get(unit, port, 
   5766                                                      pc->lane_num,value);
   5767         } else {
   5768             for (i = 0; i < HL65_NUM_LANES; i++) {
   5769                 rv = _phy_hl65_control_eq_tune_status_get(unit, port, 
   5770                                                      i,value);
   5771                 if ((*value != TRUE) || (rv != SOC_E_NONE)) {
   5772                     break;
   5773                 }
   5774             }
   5775         }
   5776         break;
   5777     case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT:
   5778         rv = _phy_hl65_control_linkdown_transmit_get(unit, port, value);
   5779         break;
   5780     case SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_MODE:
   5781         if (PHY_HC65_FABRIC_MODE(unit, port)) {    
   5782             rv = _phy_hl65_control_serdes_tune_margin_mode_get(unit, port, 
   5783                                                                pc->lane_num,
   5784                                                                value);
   5785         } else {
   5786             rv = SOC_E_UNAVAIL;
   5787         }
   5788         break;
   5789     case SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_MAX:
   5790         if (PHY_HC65_FABRIC_MODE(unit, port)) {    
   5791             rv = _phy_hl65_control_serdes_tune_margin_max_get(unit, port, 
   5792                                                               pc->lane_num,
   5793                                                               value);
   5794         } else {
   5795             rv = SOC_E_UNAVAIL;
   5796         }
   5797         break;
   5798     case SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_VALUE:
   5799         if (PHY_HC65_FABRIC_MODE(unit, port)) {    
   5800             rv = _phy_hl65_control_serdes_tune_margin_value_get(unit, port, 
   5801                                                                 pc->lane_num,
   5802                                                                 value);
   5803         } else {
   5804             rv = SOC_E_UNAVAIL;
   5805         }
   5806         break;
   5807     case SOC_PHY_CONTROL_PARALLEL_DETECTION:
   5808         SOC_IF_ERROR_RETURN
   5809             (READ_HL65_DIGITAL_CONTROL1000X2r(unit, pc,&data16));
   5810         *value = data16 & DIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK?
   5811                  TRUE: FALSE;
   5812         rv = SOC_E_NONE;
   5813         break;
   5814     case SOC_PHY_CONTROL_EQUALIZER_BOOST:
   5815        /*
   5816           RX Equalizer Boost settings for stack ports
   5817           Reading register 0x1C(RX0/1/2/3_ANACONTROL) 
   5818           of block 0x8250 (reg 0x825C)
   5819         */
   5820         SOC_IF_ERROR_RETURN
   5821             (HL65_REG_READ(unit, pc, 0x0, 0x825C, &data16));
   5822         *value = data16;
   5823         rv = SOC_E_NONE;
   5824         break;
   5825     default:
   5826         rv = SOC_E_UNAVAIL;
   5827         break; 
   5828     }
   5829     return rv;
   5830 }     
   5831 
   5832 /*
   5833  * Function:
   5834  *      phy_hl65_reg_read
   5835  * Purpose:
   5836  *      Routine to read PHY register
   5837  * Parameters:
   5838  *      uint         - BCM unit number
   5839  *      pc           - PHY state
   5840  *      flags        - Flags which specify the register type
   5841  *      phy_reg_addr - Encoded register address
   5842  *      phy_data     - (OUT) Value read from PHY register
   5843  * Note:
   5844  *      This register read function is not thread safe. Higher level
   5845  * function that calls this function must obtain a per port lock
   5846  * to avoid overriding register page mapping between threads.
   5847  */
   5848 STATIC int
   5849 phy_hl65_reg_read(int unit, soc_port_t port, uint32 flags,
   5850                   uint32 phy_reg_addr, uint32 *phy_data)
   5851 {
   5852     uint16               data;     /* Temporary holder for phy_data */
   5853     phy_ctrl_t          *pc;      /* PHY software state */
   5854 
   5855     pc = INT_PHY_SW_STATE(unit, port);
   5856 
   5857     SOC_IF_ERROR_RETURN
   5858         (phy_reg_aer_read(unit, pc, phy_reg_addr, &data));
   5859 
   5860    *phy_data = data;
   5861 
   5862     return SOC_E_NONE;
   5863 }
   5864 
   5865 /*
   5866  * Function:
   5867  *      phy_hl65_reg_write
   5868  * Purpose:
   5869  *      Routine to write PHY register
   5870  * Parameters:
   5871  *      uint         - BCM unit number
   5872  *      pc           - PHY state
   5873  *      flags        - Flags which specify the register type
   5874  *      phy_reg_addr - Encoded register address
   5875  *      phy_data     - Value write to PHY register
   5876  * Note:
   5877  *      This register read function is not thread safe. Higher level
   5878  * function that calls this function must obtain a per port lock
   5879  * to avoid overriding register page mapping between threads.
   5880  */
   5881 STATIC int
   5882 phy_hl65_reg_write(int unit, soc_port_t port, uint32 flags,
   5883                    uint32 phy_reg_addr, uint32 phy_data)
   5884 {
   5885     uint16               data;     /* Temporary holder for phy_data */
   5886     phy_ctrl_t          *pc;      /* PHY software state */
   5887 
   5888     pc = INT_PHY_SW_STATE(unit, port);
   5889 
   5890     data      = (uint16) (phy_data & 0x0000FFFF);
   5891 
   5892     SOC_IF_ERROR_RETURN
   5893         (phy_reg_aer_write(unit, pc, phy_reg_addr, data));
   5894 
   5895     return SOC_E_NONE;
   5896 }  
   5897 
   5898 /*
   5899  * Function:
   5900  *      phy_hl65_reg_modify
   5901  * Purpose:
   5902  *      Routine to write PHY register
   5903  * Parameters:
   5904  *      uint         - BCM unit number
   5905  *      pc           - PHY state
   5906  *      flags        - Flags which specify the register type
   5907  *      phy_reg_addr - Encoded register address
   5908  *      phy_mo_data  - New value for the bits specified in phy_mo_mask
   5909  *      phy_mo_mask  - Bit mask to modify
   5910  * Note:
   5911  *      This register read function is not thread safe. Higher level
   5912  * function that calls this function must obtain a per port lock
   5913  * to avoid overriding register page mapping between threads.
   5914  */
   5915 STATIC int
   5916 phy_hl65_reg_modify(int unit, soc_port_t port, uint32 flags,
   5917                     uint32 phy_reg_addr, uint32 phy_data,
   5918                     uint32 phy_data_mask)
   5919 {
   5920     uint16               data;     /* Temporary holder for phy_data */
   5921     uint16               mask;
   5922     phy_ctrl_t    *pc;      /* PHY software state */
   5923 
   5924     pc = INT_PHY_SW_STATE(unit, port);
   5925 
   5926     data      = (uint16) (phy_data & 0x0000FFFF);
   5927     mask      = (uint16) (phy_data_mask & 0x0000FFFF);
   5928 
   5929     SOC_IF_ERROR_RETURN
   5930         (phy_reg_aer_modify(unit, pc, phy_reg_addr, data, mask));
   5931 
   5932     return SOC_E_NONE;
   5933 }
   5934 
   5935 STATIC int
   5936 phy_hl65_probe(int unit, phy_ctrl_t *pc)
   5937 {
   5938     uint16      serdes_id0;
   5939    
   5940     SOC_IF_ERROR_RETURN
   5941         (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
   5942 
   5943     if (!(((serdes_id0 & TEST_SERDESID0_MODEL_NUMBER_MASK) ==
   5944              SERDES_ID0_MODEL_NUMBER_HYPERLITE) || 
   5945           ((serdes_id0 & TEST_SERDESID0_MODEL_NUMBER_MASK) ==
   5946              SERDES_ID0_MODEL_NUMBER_HYPERCORE))) {
   5947         return SOC_E_NOT_FOUND;
   5948     }
   5949 
   5950     if ((serdes_id0 & TEST_SERDESID0_TECH_PROC_MASK) !=
   5951         SERDES_ID0_TECH_PROC_65NM) {
   5952         return SOC_E_NOT_FOUND;
   5953     }
   5954 
   5955     return SOC_E_NONE;
   5956 }
   5957 
   5958 STATIC int
   5959 phy_hl65_notify(int unit, soc_port_t port,
   5960                        soc_phy_event_t event, uint32 value)
   5961 {
   5962     int             rv;
   5963 
   5964     if (event >= phyEventCount) {
   5965         return SOC_E_PARAM;
   5966     }
   5967 
   5968     rv = SOC_E_NONE;
   5969     switch(event) {
   5970     case phyEventInterface:
   5971         rv = (_phy_hl65_notify_interface(unit, port, value));
   5972         break;
   5973     case phyEventDuplex:
   5974         rv = (_phy_hl65_notify_duplex(unit, port, value));
   5975         break;
   5976     case phyEventSpeed:
   5977         rv = (_phy_hl65_notify_speed(unit, port, value));
   5978         break;
   5979     case phyEventStop:
   5980         rv = (_phy_hl65_notify_stop(unit, port, value));
   5981         break;
   5982     case phyEventResume:
   5983         rv = (_phy_hl65_notify_resume(unit, port, value));
   5984         break;
   5985     case phyEventAutoneg:
   5986         rv = (phy_hl65_an_set(unit, port, value));
   5987         break;
   5988     case phyEventTxFifoReset:
   5989         rv = (_phy_hl65_tx_fifo_reset(unit, port, value));
   5990         break;
   5991     default:
   5992         rv = SOC_E_UNAVAIL;
   5993     }
   5994 
   5995     return rv;
   5996 }
   5997 
   5998 STATIC int
   5999 phy_hl65_linkup_evt (int unit, soc_port_t port)
   6000 {
   6001     phy_ctrl_t  *pc;
   6002     int an,an_done,speed;
   6003                                                                                 
   6004     pc = INT_PHY_SW_STATE(unit, port);
   6005 
   6006     phy_hl65_an_get(unit,port,&an,&an_done);
   6007 
   6008     LOG_INFO(BSL_LS_SOC_PHY,
   6009              (BSL_META_U(unit,
   6010                          "phy_hl65_linkup_evt: "
   6011                          "u=%d p=%d an=%d\n"), unit, port, an));
   6012     /* check if the link is established due to the auto-negotiation. If so,
   6013      * configure the tx half rate and DSP related registers. These settings
   6014      * can only be done after the autoneg speed is determined.
   6015      */
   6016     if (an == TRUE) {
   6017 
   6018         /* check the autoneg speed */
   6019         phy_hl65_speed_get(unit,port,&speed);
   6020                                                                                 
   6021         /* set tx half rate. */
   6022         SOC_IF_ERROR_RETURN
   6023             (_phy_hl65_half_rate_set(unit,port,speed));
   6024                                                                                 
   6025         if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   6026                                                                                 
   6027             /* configure DSP related registers based on speed */
   6028             _phy_hl65_dsp_cfg(unit,pc,speed);
   6029         }
   6030 
   6031         /* for speed above 10G, txcko_div must be cleared */
   6032         if (speed > 10000) {
   6033             SOC_IF_ERROR_RETURN
   6034                 (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc,
   6035                                       0,
   6036                                       XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK));
   6037         } else {
   6038             SOC_IF_ERROR_RETURN
   6039                 (MODIFY_HL65_XGXSBLK0_XGXSCONTROLr(unit, pc,
   6040                                       XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK,
   6041                                       XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK));
   6042         }
   6043     }
   6044     return SOC_E_NONE;
   6045 }
   6046 
   6047 STATIC int
   6048 phy_hl65_linkdown_evt (int unit, soc_port_t port)
   6049 {
   6050     phy_ctrl_t  *pc;
   6051     int an,an_done; 
   6052     uint16 dfe_brcdr;
   6053                                                   
   6054     pc = INT_PHY_SW_STATE(unit, port);
   6055                                                                                 
   6056     phy_hl65_an_get(unit,port,&an,&an_done);
   6057                                                                                 
   6058     LOG_INFO(BSL_LS_SOC_PHY,
   6059              (BSL_META_U(unit,
   6060                          "phy_hl65_linkdown_evt: "
   6061                          "u=%d p=%d an=%d\n"), unit, port, an));
   6062 
   6063     /* The DSP related registers must be set to the default
   6064      * values before the autoneg starts.
   6065      */
   6066     if (an == TRUE) {
   6067         if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   6068 
   6069             /* check if DFE/BR CDR(20G speed). if so, restart AN */
   6070             SOC_IF_ERROR_RETURN
   6071                 (READ_HL65_DSC2BB_DSC_MISC_CTRL0r(unit, pc, &dfe_brcdr));
   6072 
   6073             if ((dfe_brcdr == HL65_A0A1_DSC_DFE_BRCDR) ||
   6074                 (dfe_brcdr == HL65_B0C0_DSC_DFE_BRCDR) ) {
   6075                 phy_hl65_an_set(unit,port,TRUE);
   6076             }
   6077         }
   6078     }
   6079     return SOC_E_NONE;
   6080 }
   6081 
   6082 /*
   6083  * Function:
   6084  *      phy_hl65_duplex_set
   6085  * Purpose:
   6086  *      Set the current duplex mode (forced).
   6087  * Parameters:
   6088  *      unit - StrataSwitch unit #.
   6089  *      port - StrataSwitch port #.
   6090  *      duplex - Boolean, true indicates full duplex, false indicates half.
   6091  * Returns:
   6092  *      SOC_E_XXX
   6093  */
   6094 
   6095 STATIC int
   6096 phy_hl65_duplex_set(int unit, soc_port_t port, int duplex)
   6097 {
   6098     uint16       data16;
   6099     phy_ctrl_t  *pc;
   6100     uint16      serdes_id0;
   6101     int duplex_value;
   6102 
   6103     if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   6104         return SOC_E_NONE;
   6105     }
   6106 
   6107     pc = INT_PHY_SW_STATE(unit, port);
   6108 
   6109     SOC_IF_ERROR_RETURN
   6110         (READ_HL65_DIGITAL_STATUS1000X1r(unit, pc, &data16));
   6111 
   6112     if (!(data16 & DIGITAL_STATUS1000X1_SGMII_MODE_MASK)) {
   6113 
   6114         SOC_IF_ERROR_RETURN
   6115             (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
   6116 
   6117         /* 1000X fiber mode, 100fx  */
   6118             
   6119         if ((serdes_id0 & TEST_SERDESID0_REV_LETTER_MASK) > 0) { 
   6120             duplex_value = duplex? FX100_CONTROL1_FULL_DUPLEX_MASK:0;
   6121             SOC_IF_ERROR_RETURN
   6122                 (MODIFY_HL65_FX100_CONTROL1r(unit,pc,
   6123                        duplex_value,
   6124                        FX100_CONTROL1_FULL_DUPLEX_MASK));
   6125         }
   6126         /* 1000X should always be full duplex */
   6127         duplex = TRUE;
   6128     }
   6129 
   6130     data16 = duplex? MII_CTRL_FD: 0;
   6131 
   6132     /* program the duplex setting */
   6133     SOC_IF_ERROR_RETURN
   6134         (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, data16,MII_CTRL_FD));
   6135 
   6136     return SOC_E_NONE;
   6137 }
   6138 
   6139 STATIC int
   6140 phy_hl65_duplex_get(int unit, soc_port_t port, int *duplex)
   6141 {
   6142     uint16       reg0_16;
   6143     uint16       mii_ctrl;
   6144     phy_ctrl_t  *pc;
   6145 
   6146     pc = INT_PHY_SW_STATE(unit, port);
   6147 
   6148     if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   6149         *duplex = TRUE;
   6150         return SOC_E_NONE;
   6151     }
   6152 
   6153     SOC_IF_ERROR_RETURN
   6154         (READ_HL65_DIGITAL_STATUS1000X1r(unit, pc, &reg0_16));
   6155 
   6156     /* default to fiber mode duplex */
   6157     *duplex = (reg0_16 & DIGITAL_STATUS1000X1_DUPLEX_STATUS_MASK)?
   6158               TRUE:FALSE;
   6159 
   6160     if (reg0_16 & DIGITAL_STATUS1000X1_SGMII_MODE_MASK) {
   6161 
   6162     /* retrieve the duplex setting in SGMII mode */
   6163         SOC_IF_ERROR_RETURN
   6164             (READ_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl));
   6165 
   6166         if (mii_ctrl & MII_CTRL_AE) {
   6167             SOC_IF_ERROR_RETURN
   6168                 (READ_HL65_COMBO_IEEE0_AUTONEGLPABILr(unit,pc,&reg0_16));
   6169 
   6170             /* make sure link partner is also in SGMII mode
   6171              * otherwise fall through to use the FD bit in MII_CTRL reg
   6172              */
   6173             if (reg0_16 & MII_ANP_SGMII_MODE) {
   6174                 if (reg0_16 & MII_ANP_SGMII_FD) {
   6175                     *duplex = TRUE;
   6176                 } else {
   6177                     *duplex = FALSE;
   6178                 }
   6179                 return SOC_E_NONE;
   6180             }
   6181         }
   6182         *duplex = (mii_ctrl & MII_CTRL_FD) ? TRUE : FALSE;
   6183     } 
   6184 
   6185     return SOC_E_NONE;
   6186 }
   6187 
   6188 /*
   6189  * Function:
   6190  *      phy_hl65_diag_ctrl
   6191  * Purpose:
   6192  * Parameters:
   6193  *      unit - StrataSwitch unit #.
   6194  *      port - StrataSwitch port #.
   6195  * Returns:
   6196  *      SOC_E_NONE
   6197  * Notes:
   6198  */
   6199 
   6200 STATIC int
   6201 phy_hl65_diag_ctrl(
   6202    int unit, /* unit */
   6203    soc_port_t port, /* port */
   6204    uint32 inst, /* the specific device block the control action directs to */
   6205    int op_type,  /* operation types: read,write or command sequence */
   6206    int op_cmd,   /* command code */
   6207    void *arg)     /* command argument based on op_type/op_cmd */
   6208 {
   6209     int rv;
   6210 
   6211     rv = SOC_E_NONE;
   6212 
   6213     switch(op_cmd) {
   6214 
   6215         case PHY_DIAG_CTRL_DSC:
   6216              LOG_INFO(BSL_LS_SOC_PHY,
   6217                       (BSL_META_U(unit,
   6218                                   "phy_hl65_diag_ctrl: "
   6219                                   "u=%d p=%d PHY_DIAG_CTRL_DSC 0x%x\n"),
   6220                        unit, port, PHY_DIAG_CTRL_DSC));
   6221             (void)phy_hl65_uc_status_dump(unit, port);
   6222         break;
   6223 
   6224         default:
   6225             if (op_type == PHY_DIAG_CTRL_SET) {
   6226                 rv = phy_hl65_control_set(unit, port, op_cmd, PTR_TO_INT(arg));
   6227             } else if (op_type == PHY_DIAG_CTRL_GET) {
   6228                 rv = phy_hl65_control_get(unit, port, op_cmd, (uint32 *)arg);
   6229             }
   6230         break;
   6231     }
   6232     return rv;
   6233 }
   6234 
   6235 #define HL65_UC_DEBUG
   6236 #ifdef HL65_UC_DEBUG
   6237 typedef struct {
   6238     int postc_metric;
   6239     int pf_ctrl;
   6240     int vga_sum;
   6241     int dfe_bin;
   6242     int integ_reg;
   6243     int integ_reg_xfer;
   6244     int clk90_offset;
   6245     int slicer_target;
   6246     int offset_pe;
   6247     int offset_ze;
   6248     int offset_me;
   6249     int offset_po;
   6250     int offset_zo;
   6251     int offset_mo;
   6252     int tx_os;
   6253     int tx_br;
   6254 } HL65_DESC;
   6255 #define LANE0_ACCESS      1
   6256 #define LANE1_ACCESS      2
   6257 #define LANE2_ACCESS      3
   6258 #define LANE3_ACCESS      4
   6259 #define MAX_LANES 4
   6260 static HL65_DESC hl65_desc;
   6261     
   6262 int
   6263 phy_hl65_uc_status_dump(int unit, soc_port_t port)
   6264 {
   6265     phy_ctrl_t  *pc;
   6266     HL65_DESC * pDesc;
   6267     int lane_num;
   6268     uint16 data16;
   6269     int regval, reg_addr;
   6270     uint8 print_menu = TRUE;
   6271 
   6272     pc = INT_PHY_SW_STATE(unit, port);
   6273 
   6274     for (lane_num = 0; lane_num < MAX_LANES; lane_num++) {
   6275         sal_memset((char *)&hl65_desc, 0, (sizeof(HL65_DESC)));
   6276         pDesc = &hl65_desc;
   6277         
   6278         /* integ_reg(lane) = rd22_integ_reg (phy, lane) */
   6279         reg_addr = 0x82b0 + (lane_num * 0x10);
   6280         SOC_IF_ERROR_RETURN
   6281             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6282         regval = data16;
   6283         regval &= 65535;
   6284         if (regval >= 32768) {
   6285             regval -=65536;
   6286         }
   6287         regval /= 84;
   6288         pDesc->integ_reg = regval;
   6289      
   6290         /* integ_reg_xfer(lane) = rd22_integ_reg_xfer (phy, lane)   */
   6291         reg_addr = 0x82b1 + (lane_num * 0x10);
   6292         SOC_IF_ERROR_RETURN
   6293             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6294         regval = data16;
   6295         regval &= 65535;
   6296         if (regval >= 32768) {
   6297             regval -=65536;
   6298         }
   6299         regval /= 84;
   6300         pDesc->integ_reg_xfer = regval;
   6301 
   6302         /* clk90_offset(lane) = rd22_clk90_phase_offset (phy, lane)   */
   6303         reg_addr = 0x82b3 + (lane_num * 0x10);
   6304         SOC_IF_ERROR_RETURN
   6305             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6306         regval = data16;
   6307         regval /= 128;
   6308         regval &= 127;
   6309         pDesc->clk90_offset = regval;
   6310         
   6311         /* pf_ctrl(lane) = rd22_pf_ctrl (phy, lane) */
   6312         reg_addr = 0x82bb + (lane_num * 0x10);
   6313         SOC_IF_ERROR_RETURN
   6314             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6315         regval = data16;
   6316         regval &= 0x7;
   6317         pDesc->pf_ctrl = regval;
   6318         
   6319         /* slicer_target(lane) = ((25*rd22_rx_thresh_sel (phy, lane)) + 125)   */
   6320         reg_addr = 0x821c + (lane_num * 0x10);
   6321         SOC_IF_ERROR_RETURN
   6322             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6323         regval = data16;
   6324         regval /= 32;
   6325         regval &= 3;
   6326         pDesc->slicer_target = regval * 25 + 125;
   6327 
   6328         /* vga_sum(lane) = rd22_vga_sum (phy, lane) */
   6329         reg_addr = 0x82b5 + (lane_num * 0x10);
   6330         SOC_IF_ERROR_RETURN
   6331             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6332         regval = data16;
   6333         regval /= 64;
   6334         regval &= 0x1f;
   6335         pDesc->vga_sum = regval;
   6336        
   6337         /* dfe_bin(lane) = rd22_dfe_tap_bin (phy, lane) */ 
   6338         reg_addr = 0x82b5 + (lane_num * 0x10);
   6339         SOC_IF_ERROR_RETURN
   6340             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6341         regval = data16;
   6342         regval &= 0x3f;
   6343         pDesc->dfe_bin = regval;
   6344          
   6345         /* postc_metric(lane) = rd22_postc_metric (phy, lane)*/
   6346         reg_addr = 0x82b8 + (lane_num * 0x10);
   6347         SOC_IF_ERROR_RETURN
   6348             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6349         regval = data16;
   6350         regval &= 0x7ff;
   6351         if (regval >=1024) {
   6352             regval -= 2048;
   6353         } 
   6354         pDesc->postc_metric = regval;
   6355 
   6356         /* offset_mo(lane) = rd22_slicer_offset_mo (phy, lane) */
   6357         reg_addr = 0x82b9 + (lane_num * 0x10);
   6358         SOC_IF_ERROR_RETURN
   6359             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6360         regval = data16;
   6361         regval &= 0x1f;
   6362         if(regval > 16) {
   6363             regval -= 32;
   6364         }
   6365         pDesc->offset_mo = regval;
   6366 
   6367         /* offset_zo(lane) = rd22_slicer_offset_zo (phy, lane) */
   6368         regval = data16;
   6369         regval /= 32;
   6370         regval &= 0x1f;
   6371         if(regval > 16) {
   6372             regval -= 32;
   6373         }
   6374         pDesc->offset_zo = regval;
   6375 
   6376         /* offset_po(lane) = rd22_slicer_offset_po (phy, lane) */
   6377         regval = data16;
   6378         regval /= 1024;
   6379         regval &= 0x1f;
   6380         if(regval > 16) {
   6381             regval -= 32;
   6382         }
   6383         pDesc->offset_po = regval;
   6384        
   6385         /* offset_me(lane) = rd22_slicer_offset_me (phy, lane)   */
   6386         reg_addr = 0x82ba + (lane_num * 0x10);
   6387         SOC_IF_ERROR_RETURN
   6388             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6389         regval = data16;
   6390         regval &= 0x1f;
   6391         if(regval > 16) {
   6392             regval -= 32;
   6393         }
   6394         pDesc->offset_me = regval;
   6395 
   6396         /* offset_ze(lane) = rd22_slicer_offset_ze (phy, lane)   */
   6397         regval = data16;
   6398         regval /= 32;
   6399         regval &= 0x1f;
   6400         if(regval > 16) {
   6401             regval -= 32;
   6402         }
   6403         pDesc->offset_ze = regval;
   6404 
   6405         /* offset_pe(lane) = rd22_slicer_offset_pe (phy, lane)   */
   6406         regval = data16;
   6407         regval /= 1024;
   6408         regval &= 0x1f;
   6409         if(regval > 16) {
   6410             regval -= 32;
   6411         }
   6412         pDesc->offset_pe = regval;
   6413     
   6414         reg_addr = 0x8067 + (lane_num * 0x10);
   6415         SOC_IF_ERROR_RETURN
   6416             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6417         regval = data16;
   6418         pDesc->tx_os = regval;
   6419         
   6420         reg_addr = 0x8068 + (lane_num * 0x10);
   6421         SOC_IF_ERROR_RETURN
   6422             (HL65_REG_READ(unit,pc,0x0,reg_addr, &data16));
   6423         regval = data16;
   6424         pDesc->tx_br = regval;
   6425         
   6426         SOC_IF_ERROR_RETURN
   6427             (READ_HL65_TXPLL_ANAPLLASTATUS1r(unit, pc, &data16));
   6428         /* regval = (data16 >> 8) & 0xf; */
   6429 
   6430         if( print_menu == TRUE) { 
   6431             LOG_CLI((BSL_META_U(unit,
   6432                                 "\n\nDSC parameters for port %d\n\n"), port));
   6433             LOG_CLI((BSL_META_U(unit,
   6434                                 "PLL Range: %d\n\n"),data16));
   6435 
   6436             LOG_CLI((BSL_META_U(unit,
   6437                                 "LN PPM  PPM_XFR clk90_ofs " 
   6438                      "PF   SL_TRGT VGA  DFE  " 
   6439                                 "TXDIR_OS TXDR_BR  MTRC PE   "
   6440                                 "ZE   ME  PO  ZO  "
   6441                                 "MO\n")));
   6442             print_menu = FALSE;
   6443         }
   6444         LOG_CLI((BSL_META_U(unit,
   6445                             "%02d %04d %07d %09d "
   6446                  "%04d %07d %04d %04d "
   6447                             "0x%06x 0x%06x %04d %04d "
   6448                             "%04d %2d %3d %3d "
   6449                             "%2d\n"),
   6450                  lane_num, pDesc->integ_reg, pDesc->integ_reg_xfer,
   6451                  pDesc->clk90_offset, pDesc->pf_ctrl,
   6452                  pDesc->slicer_target, pDesc->vga_sum, pDesc->dfe_bin,
   6453                  pDesc->tx_os, pDesc->tx_br,
   6454                  pDesc->postc_metric, pDesc->offset_pe,
   6455                  pDesc->offset_ze, pDesc->offset_me,
   6456                  pDesc->offset_po, pDesc->offset_zo, 
   6457                  pDesc->offset_mo));
   6458 
   6459     }
   6460 
   6461     return SOC_E_NONE;
   6462 }
   6463 #endif
   6464 
   6465 /*
   6466  * Variable:
   6467  *      phy_hl65_drv
   6468  * Purpose:
   6469  *      Phy Driver for 10G (XAUI x 4) Serdes PHY. 
   6470  */
   6471 phy_driver_t phy_hl65_hg = {
   6472     /* .drv_name                      = */ "HyperLite PHY Driver",
   6473     /* .pd_init                       = */ phy_hl65_init,
   6474     /* .pd_reset                      = */ phy_null_reset,
   6475     /* .pd_link_get                   = */ phy_hl65_link_get,
   6476     /* .pd_enable_set                 = */ phy_hl65_enable_set,
   6477     /* .pd_enable_get                 = */ phy_hl65_enable_get,
   6478     /* .pd_duplex_set                 = */ phy_hl65_duplex_set,
   6479     /* .pd_duplex_get                 = */ phy_hl65_duplex_get,
   6480     /* .pd_speed_set                  = */ phy_hl65_speed_set,
   6481     /* .pd_speed_get                  = */ phy_hl65_speed_get,
   6482     /* .pd_master_set                 = */ phy_null_set,
   6483     /* .pd_master_get                 = */ phy_null_zero_get,
   6484     /* .pd_an_set                     = */ phy_hl65_an_set,
   6485     /* .pd_an_get                     = */ phy_hl65_an_get,
   6486     /* .pd_adv_local_set              = */ NULL, /* Deprecated */
   6487     /* .pd_adv_local_get              = */ NULL, /* Deprecated */
   6488     /* .pd_adv_remote_get             = */ NULL, /* Deprecated */
   6489     /* .pd_lb_set                     = */ phy_hl65_lb_set,
   6490     /* .pd_lb_get                     = */ phy_hl65_lb_get,
   6491     /* .pd_interface_set              = */ phy_hl65_interface_set,
   6492     /* .pd_interface_get              = */ phy_hl65_interface_get,
   6493     /* .pd_ability                    = */ NULL, /* Deprecated */
   6494     /* .pd_linkup_evt                 = */ phy_hl65_linkup_evt,
   6495     /* .pd_linkdn_evt                 = */ phy_hl65_linkdown_evt,
   6496     /* .pd_mdix_set                   = */ phy_null_mdix_set,
   6497     /* .pd_mdix_get                   = */ phy_null_mdix_get,
   6498     /* .pd_mdix_status_get            = */ phy_null_mdix_status_get,
   6499     /* .pd_medium_config_set          = */ NULL,
   6500     /* .pd_medium_config_get          = */ NULL, 
   6501     /* .pd_medium_get                 = */ phy_null_medium_get,
   6502     /* .pd_cable_diag                 = */ NULL,
   6503     /* .pd_link_change                = */ NULL,
   6504     /* .pd_control_set                = */ phy_hl65_control_set,    
   6505     /* .pd_control_get                = */ phy_hl65_control_get,
   6506     /* .pd_reg_read                   = */ phy_hl65_reg_read,
   6507     /* .pd_reg_write                  = */ phy_hl65_reg_write, 
   6508     /* .pd_reg_modify                 = */ phy_hl65_reg_modify,
   6509     /* .pd_notify                     = */ phy_hl65_notify,
   6510     /* .pd_probe                      = */ phy_hl65_probe,
   6511     /* .pd_ability_advert_set         = */ phy_hl65_ability_advert_set,
   6512     /* .pd_ability_advert_get         = */ phy_hl65_ability_advert_get,
   6513     /* .pd_ability_remote_get         = */ phy_hl65_ability_remote_get,
   6514     /* .pd_ability_local_get          = */ phy_hl65_ability_local_get,
   6515     /* .pd_firmware_set               = */ NULL,
   6516     /* .pdpd_timesync_config_set      = */ NULL,
   6517     /* .pdpd_timesync_config_get      = */ NULL,
   6518     /* .pdpd_timesync_control_set     = */ NULL,
   6519     /* .pdpd_timesync_control_set     = */ NULL,
   6520     /* .pd_diag_ctrl                  = */ phy_hl65_diag_ctrl
   6521 };
   6522 
   6523 /***********************************************************************
   6524  *
   6525  * PASS-THROUGH NOTIFY ROUTINES
   6526  */
   6527 
   6528 /*
   6529  * Function:
   6530  *      _phy_hl65_notify_duplex
   6531  * Purpose:
   6532  *      Program duplex if (and only if) serdeshl65 is an intermediate PHY.
   6533  * Parameters:
   6534  *      unit - StrataSwitch unit #.
   6535  *      port - StrataSwitch port #.
   6536  *      duplex - Boolean, TRUE indicates full duplex, FALSE
   6537  *              indicates half.
   6538  * Returns:
   6539  *      SOC_E_XXX
   6540  * Notes:
   6541  *      If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to
   6542  *      talk directly to an external fiber module.
   6543  *
   6544  *      If PHY_FLAGS_FIBER is clear, the PHY is being used in
   6545  *      pass-through mode to talk to an external SGMII PHY.
   6546  *
   6547  *      When used in pass-through mode, autoneg must be turned off and
   6548  *      the speed/duplex forced to match that of the external PHY.
   6549  */
   6550 
   6551 STATIC int
   6552 _phy_hl65_notify_duplex(int unit, soc_port_t port, uint32 duplex)
   6553 {
   6554     int                 fiber;
   6555     uint16              mii_ctrl;
   6556     phy_ctrl_t  *pc;
   6557 
   6558     fiber = PHY_FIBER_MODE(unit, port);
   6559     pc    = INT_PHY_SW_STATE(unit, port);
   6560     LOG_INFO(BSL_LS_SOC_PHY,
   6561              (BSL_META_U(unit,
   6562                          "_phy_hl65_notify_duplex: "
   6563                          "u=%d p=%d duplex=%d fiber=%d\n"),
   6564               unit, port, duplex, fiber));
   6565 
   6566     if (SAL_BOOT_SIMULATION) {
   6567         return SOC_E_NONE;
   6568     }
   6569 
   6570     if (fiber) {
   6571         SOC_IF_ERROR_RETURN
   6572             (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc,
   6573                                           MII_CTRL_FD, MII_CTRL_FD));
   6574         return SOC_E_NONE;
   6575     }
   6576 
   6577     /* Put SERDES PHY in reset */
   6578 
   6579     SOC_IF_ERROR_RETURN
   6580         (_phy_hl65_notify_stop(unit, port, PHY_STOP_DUPLEX_CHG));
   6581 
   6582     /* Update duplexity */
   6583     mii_ctrl = (duplex) ? MII_CTRL_FD : 0;
   6584     SOC_IF_ERROR_RETURN
   6585         (MODIFY_HL65_COMBO_IEEE0_MIICNTLr(unit, pc, mii_ctrl, MII_CTRL_FD));
   6586 
   6587     /* Take SERDES PHY out of reset */
   6588     SOC_IF_ERROR_RETURN
   6589         (_phy_hl65_notify_resume(unit, port, PHY_STOP_DUPLEX_CHG));
   6590 
   6591     /* Autonegotiation must be turned off to talk to external PHY if
   6592      * SGMII autoneg is not enabled.
   6593      */
   6594     if (!PHY_SGMII_AUTONEG_MODE(unit, port)) {
   6595         SOC_IF_ERROR_RETURN
   6596             (phy_hl65_an_set(unit, port, FALSE));
   6597     }
   6598     return SOC_E_NONE;
   6599 }
   6600 
   6601 /*
   6602  * Function:
   6603  *      _phy_hl65_notify_speed
   6604  * Purpose:
   6605  *      Program duplex if (and only if) serdeshl65 is an intermediate PHY.
   6606  * Parameters:
   6607  *      unit - StrataSwitch unit #.
   6608  *      port - StrataSwitch port #.
   6609  *      speed - Speed to program.
   6610  * Returns:
   6611  *      SOC_E_XXX
   6612  * Notes:
   6613  *      If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to
   6614  *      talk directly to an external fiber module.
   6615  *
   6616  *      If PHY_FLAGS_FIBER is clear, the PHY is being used in
   6617  *      pass-through mode to talk to an external SGMII PHY.
   6618  *
   6619  *      When used in pass-through mode, autoneg must be turned off and
   6620  *      the speed/duplex forced to match that of the external PHY.
   6621  */
   6622 
   6623 STATIC int
   6624 _phy_hl65_notify_speed(int unit, soc_port_t port, uint32 speed)
   6625 {
   6626     int          fiber;
   6627     uint16       fiber_status;
   6628     phy_ctrl_t  *pc;
   6629 
   6630     pc    = INT_PHY_SW_STATE(unit, port);
   6631     fiber = PHY_FIBER_MODE(unit, port);
   6632 
   6633     LOG_INFO(BSL_LS_SOC_PHY,
   6634              (BSL_META_U(unit,
   6635                          "_phy_hl65_notify_speed: "
   6636                          "u=%d p=%d speed=%d fiber=%d\n"),
   6637               unit, port, speed, fiber));
   6638 
   6639     if (SAL_BOOT_SIMULATION) {
   6640         return SOC_E_NONE;
   6641     }
   6642 
   6643     SOC_IF_ERROR_RETURN
   6644         (READ_HL65_DIGITAL_STATUS1000X1r(unit, pc, &fiber_status));
   6645 
   6646     /* Put SERDES PHY in reset */
   6647     SOC_IF_ERROR_RETURN
   6648         (_phy_hl65_notify_stop(unit, port, PHY_STOP_SPEED_CHG));
   6649 
   6650     /* Update speed */
   6651     SOC_IF_ERROR_RETURN
   6652         (phy_hl65_speed_set(unit, port, speed));
   6653 
   6654     /* Take SERDES PHY out of reset */
   6655     SOC_IF_ERROR_RETURN
   6656         (_phy_hl65_notify_resume(unit, port, PHY_STOP_SPEED_CHG));
   6657 
   6658     /* Autonegotiation must be turned off to talk to external PHY */
   6659     if (!PHY_SGMII_AUTONEG_MODE(unit, port) && PHY_EXTERNAL_MODE(unit, port)) {
   6660         SOC_IF_ERROR_RETURN
   6661             (phy_hl65_an_set(unit, port, FALSE));
   6662     }
   6663 
   6664     return SOC_E_NONE;
   6665 }
   6666 
   6667 /*
   6668  * Function:
   6669  *      _phy_hl65_stop
   6670  * Purpose:
   6671  *      Put serdeshl65 SERDES in or out of reset depending on conditions
   6672  */
   6673 
   6674 STATIC int
   6675 _phy_hl65_stop(int unit, soc_port_t port)
   6676 {
   6677     int                 stop, copper;
   6678     uint16 mask16,data16;
   6679     phy_ctrl_t  *pc;
   6680     int mdio_addr_share = FALSE;
   6681 
   6682     if (!PHY_INDEPENDENT_LANE_MODE(unit, port)) {
   6683         return SOC_E_NONE;
   6684     }
   6685 
   6686     pc = INT_PHY_SW_STATE(unit, port);
   6687 
   6688     copper = (pc->stop &
   6689               PHY_STOP_COPPER) != 0;
   6690 
   6691     stop = ((pc->stop &
   6692              (PHY_STOP_PHY_DIS |
   6693               PHY_STOP_DRAIN)) != 0 ||
   6694             (copper &&
   6695              (pc->stop &
   6696               (PHY_STOP_MAC_DIS |
   6697                PHY_STOP_DUPLEX_CHG |
   6698                PHY_STOP_SPEED_CHG)) != 0));
   6699 
   6700     LOG_INFO(BSL_LS_SOC_PHY,
   6701              (BSL_META_U(unit,
   6702                          "phy_hl65_stop: u=%d p=%d copper=%d stop=%d flg=0x%x\n"),
   6703               unit, port, copper, stop,
   6704               pc->stop));
   6705 
   6706     /* check for dxgxs ports. Don't disable RX lane, we're using rx_ck clock
   6707      * for MAC Rx block registers in 10G mode
   6708      */
   6709     mask16 = (1 << pc->lane_num);    /* rx lane */
   6710     if (IS_HG_PORT(unit, port) || IS_XE_PORT(unit,port)) {
   6711         mask16 <<= 4; /* assign tx lane */
   6712     } else {
   6713         mask16 |= (mask16 << 4); /* add tx lane */
   6714     }
   6715 
   6716     if (stop) {
   6717         mask16 |= 0x800;
   6718         data16 = mask16;
   6719     } else {
   6720         data16 = 0;
   6721     }
   6722 
   6723     /* point to lane0 mdio addressing. 
   6724      * This register can only be accessed from lane0.
   6725      */
   6726     if (pc->flags & PHYCTRL_MDIO_ADDR_SHARE) {
   6727         mdio_addr_share = TRUE;
   6728         pc->flags &= ~PHYCTRL_MDIO_ADDR_SHARE;
   6729     } else {
   6730         pc->phy_id -= pc->lane_num;
   6731     }
   6732 
   6733     SOC_IF_ERROR_RETURN
   6734         (MODIFY_HL65_XGXSBLK1_LANECTRL3r(unit,pc,data16,mask16));
   6735 
   6736     /* restore the previous MDIO address mode */
   6737     if (mdio_addr_share == TRUE) {
   6738         pc->flags |= PHYCTRL_MDIO_ADDR_SHARE;
   6739     } else {
   6740         pc->phy_id += pc->lane_num;
   6741     }
   6742  
   6743     LOG_INFO(BSL_LS_SOC_PHY,
   6744              (BSL_META_U(unit,
   6745                          "phy_hl65_stop: u=%d p=%d mask=0x%x value=0x%x\n"),
   6746               unit, port, mask16, data16));
   6747  
   6748     return SOC_E_NONE;
   6749 }
   6750 
   6751 /*
   6752  * Function:
   6753  *      _phy_hl65_notify_stop
   6754  * Purpose:
   6755  *      Add a reason to put serdeshl65 PHY in reset.
   6756  * Parameters:
   6757  *      unit - StrataSwitch unit #.
   6758  *      port - StrataSwitch port #.
   6759  *      flags - Reason to stop
   6760  * Returns:     
   6761  *      SOC_E_XXX
   6762  */
   6763 
   6764 STATIC int
   6765 _phy_hl65_notify_stop(int unit, soc_port_t port, uint32 flags)
   6766 {
   6767     INT_PHY_SW_STATE(unit, port)->stop |= flags;
   6768 
   6769     return _phy_hl65_stop(unit, port);
   6770 }
   6771 
   6772 /*  
   6773  * Function:
   6774  *      _phy_hl65_notify_resume
   6775  * Purpose:
   6776  *      Remove a reason to put serdeshl65 PHY in reset.
   6777  * Parameters:
   6778  *      unit - StrataSwitch unit #.
   6779  *      port - StrataSwitch port #.
   6780  *      flags - Reason to stop
   6781  * Returns:     
   6782  *      SOC_E_XXX
   6783  */
   6784 
   6785 STATIC int
   6786 _phy_hl65_notify_resume(int unit, soc_port_t port, uint32 flags)
   6787 {   
   6788     INT_PHY_SW_STATE(unit, port)->stop &= ~flags;
   6789     
   6790     return _phy_hl65_stop(unit, port);
   6791 }
   6792 
   6793 /*
   6794  * Function:
   6795  *      phy_hl65_media_setup
   6796  * Purpose:     
   6797  *      Configure 
   6798  * Parameters:
   6799  *      unit - StrataSwitch unit #.
   6800  *      port - StrataSwitch port #.
   6801  *      fiber_mode - Configure for fiber mode
   6802  *      fiber_pref - Fiber preferrred (if fiber mode)
   6803  * Returns:     
   6804  *      SOC_E_XXX
   6805  */
   6806 STATIC int
   6807 _phy_hl65_notify_interface(int unit, soc_port_t port, uint32 intf)
   6808 {
   6809     phy_ctrl_t  *pc;
   6810     uint16       data16;
   6811     
   6812     pc = INT_PHY_SW_STATE(unit, port);
   6813 
   6814     data16 = 0;
   6815     if (intf != SOC_PORT_IF_SGMII) {
   6816         data16 = DIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK;
   6817     }
   6818  
   6819     SOC_IF_ERROR_RETURN
   6820         (MODIFY_HL65_DIGITAL_CONTROL1000X1r(unit, pc, data16,
   6821                            DIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK));
   6822  
   6823     return SOC_E_NONE;
   6824 }
   6825 
   6826 STATIC
   6827 int _phy_hl65_analog_dsc_init (int unit,int port, int lane)
   6828 {
   6829     uint16      serdes_id0;
   6830     int         reg;
   6831     phy_ctrl_t  *pc;
   6832     
   6833     pc = INT_PHY_SW_STATE(unit, port);
   6834 
   6835     SOC_IF_ERROR_RETURN
   6836         (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
   6837 
   6838     serdes_id0 = serdes_id0 & (TEST_SERDESID0_REV_NUMBER_MASK |
   6839                             TEST_SERDESID0_REV_LETTER_MASK);
   6840 
   6841     /* use default if wrong lane specified */
   6842     if (lane < 0 || lane > 3) {
   6843         lane = HL_ALL_LANES;
   6844     }
   6845 
   6846     if (lane == HL_ALL_LANES) {
   6847         reg = 0x82A0;
   6848     } else {
   6849         reg = 0x8260 + lane * 0x10;
   6850     }
   6851 
   6852     if ((serdes_id0 == HL_SERDES_ID0_REVID_A0) ||
   6853         (serdes_id0 == HL_SERDES_ID0_REVID_A1) || 
   6854         (serdes_id0 == HL_SERDES_ID0_REVID_B0) ) { 
   6855 
   6856         if ((serdes_id0 == HL_SERDES_ID0_REVID_A0) ||
   6857             (serdes_id0 == HL_SERDES_ID0_REVID_A1)) {
   6858 
   6859             /*  Set this bit for the best possible PLL jitter performance */
   6860             SOC_IF_ERROR_RETURN
   6861                 (MODIFY_HL65_TXPLL_ANAPLLACONTROL4r(unit, pc, 
   6862                                PLL_PLLACONTROL4_BIT12_MASK,
   6863                                PLL_PLLACONTROL4_BIT12_MASK));
   6864         }
   6865 
   6866         /* Set lpq = 200uA */
   6867         SOC_IF_ERROR_RETURN
   6868             (MODIFY_HL65_TXPLL_ANAPLLACONTROL2r(unit, pc, (1 << 2),(1 << 2)));
   6869 
   6870         SOC_IF_ERROR_RETURN
   6871             (HL65_REG_WRITE(unit, pc, 0, reg + 0x0, 0x21));
   6872         SOC_IF_ERROR_RETURN
   6873             (HL65_REG_WRITE(unit, pc, 0, reg + 0x2, 0x3800));
   6874         SOC_IF_ERROR_RETURN
   6875             (HL65_REG_WRITE(unit, pc, 0, reg + 0x3,  0x421b));
   6876         SOC_IF_ERROR_RETURN
   6877             (HL65_REG_WRITE(unit, pc, 0, reg + 0x4, 0x53e4));
   6878         SOC_IF_ERROR_RETURN
   6879             (HL65_REG_WRITE(unit, pc, 0, reg + 0x7, 0x14A5));
   6880         SOC_IF_ERROR_RETURN
   6881             (HL65_REG_WRITE(unit, pc, 0, reg + 0x8, 0x03e0));
   6882         SOC_IF_ERROR_RETURN
   6883             (HL65_REG_WRITE(unit, pc, 0, reg + 0x9, 0x0fc0));
   6884         SOC_IF_ERROR_RETURN
   6885             (HL65_REG_WRITE(unit, pc, 0, reg + 0xb, 0x0312));
   6886         SOC_IF_ERROR_RETURN
   6887             (HL65_REG_WRITE(unit, pc, 0, reg + 0xc, 0x046a));
   6888 
   6889     } else if (serdes_id0 == HL_SERDES_ID0_REVID_C0) {
   6890         /* Set lpq = 200uA */
   6891         SOC_IF_ERROR_RETURN
   6892             (MODIFY_HL65_TXPLL_ANAPLLACONTROL2r(unit, pc, (1 << 2),(1 << 2)));
   6893     }
   6894     return SOC_E_NONE;
   6895 }
   6896 
   6897 STATIC
   6898 int _hl65_xgmii_scw_config (int unit, phy_ctrl_t *pc)
   6899 {
   6900     uint16      serdes_id0;
   6901 
   6902     /* only apply to hypercore */
   6903 
   6904     SOC_IF_ERROR_RETURN
   6905         (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
   6906 
   6907     if ((serdes_id0 & TEST_SERDESID0_MODEL_NUMBER_MASK) ==
   6908              SERDES_ID0_MODEL_NUMBER_HYPERLITE) { 
   6909         return(SOC_E_NONE);
   6910     }
   6911 
   6912     SOC_IF_ERROR_RETURN
   6913         (WRITE_HL65_RX66_A_SCW0r(unit,pc,0xE070));
   6914     SOC_IF_ERROR_RETURN
   6915         (WRITE_HL65_RX66_A_SCW1r(unit,pc,0xC0D0));
   6916     SOC_IF_ERROR_RETURN
   6917         (WRITE_HL65_RX66_A_SCW2r(unit,pc,0xA0B0));
   6918     SOC_IF_ERROR_RETURN
   6919         (WRITE_HL65_RX66_A_SCW3r(unit,pc,0x8090));
   6920     SOC_IF_ERROR_RETURN
   6921         (WRITE_HL65_RX66_A_SCW0_MASKr(unit,pc,0xF0F0));
   6922     SOC_IF_ERROR_RETURN
   6923         (WRITE_HL65_RX66_A_SCW1_MASKr(unit,pc,0xF0F0));
   6924     SOC_IF_ERROR_RETURN
   6925         (WRITE_HL65_RX66_A_SCW2_MASKr(unit,pc,0xF0F0));
   6926     SOC_IF_ERROR_RETURN
   6927         (WRITE_HL65_RX66_A_SCW3_MASKr(unit,pc,0xF0F0));
   6928     
   6929     return(SOC_E_NONE);
   6930 }
   6931 
   6932 STATIC 
   6933 int _hl65_rxaui_config(int unit, phy_ctrl_t  *pc,int rxaui)
   6934 {
   6935     uint16 mask16,data16;
   6936     mask16 = XGXSBLK1_LANECTRL3_PWRDWN_FORCE_MASK |
   6937                 0xc |    /* lane 2 and 3 RX */
   6938                 (0xc << XGXSBLK1_LANECTRL3_PWRDN_TX_SHIFT);  /* TX */
   6939 
   6940     /* if in reduced XAUI mode, disable lane 2 and 3 */
   6941     data16 = rxaui? mask16: 0;
   6942 
   6943     SOC_IF_ERROR_RETURN
   6944         (MODIFY_HL65_XGXSBLK1_LANECTRL3r(unit,pc, data16,mask16));
   6945 
   6946     return(SOC_E_NONE);
   6947 }
   6948 
   6949 STATIC
   6950 int _hl65_soft_reset(int unit, phy_ctrl_t  *pc)
   6951 {
   6952     /* Set AER to DTE */    
   6953     SOC_IF_ERROR_RETURN
   6954         (WRITE_HL65_AERBLK_AERr(unit,pc, 0x2800));
   6955 
   6956     /* select multi mmd */
   6957     SOC_IF_ERROR_RETURN
   6958         (WRITE_HL65_XGXSBLK0_MMDSELECTr(unit, pc, 0x400F));
   6959 
   6960     if (soc_property_get(unit, spn_SERDES_LANE0_RESET, 1)) {
   6961         /* soft reset via DTE  */
   6962         SOC_IF_ERROR_RETURN
   6963             (WRITE_HL65_IEEE0BLK_MIICNTLr(unit,pc, 0xA040));
   6964         
   6965         /* wait 2us for reset to complete */
   6966         sal_usleep(2);
   6967     }
   6968     /* restore the AER to default */
   6969     SOC_IF_ERROR_RETURN
   6970         (WRITE_HL65_AERBLK_AERr(unit,pc, 0x0));
   6971 
   6972     return(SOC_E_NONE);
   6973 }
   6974 
   6975 /*
   6976  * This routine initializes some of the device's lane specific registers 
   6977  * applying to all modes. In the combo mode, the AER register should be
   6978  * set to broadcast to all lanes before entering this function.
   6979  */
   6980 STATIC
   6981 int _hl65_lane_reg_init(int unit, phy_ctrl_t  *pc)
   6982 {
   6983     uint16      serdes_id0;
   6984     uint16      data16;
   6985 
   6986     SOC_IF_ERROR_RETURN
   6987         (READ_HL65_TEST_SERDESID0r(unit, pc, &serdes_id0));
   6988 
   6989     serdes_id0 = serdes_id0 & (TEST_SERDESID0_REV_NUMBER_MASK |
   6990                             TEST_SERDESID0_REV_LETTER_MASK);
   6991 
   6992     if ((serdes_id0 == HL_SERDES_ID0_REVID_B0) ||
   6993         (serdes_id0 == HL_SERDES_ID0_REVID_C0)) {
   6994 
   6995         /* Revert Back to original Rx fifo if C0/B0 version */
   6996         SOC_IF_ERROR_RETURN
   6997             (MODIFY_HL65_DIGITAL4_MISC3r(unit, pc,
   6998                    0,
   6999                    DIGITAL4_MISC3_FIFO_IPG_CYA_MASK));
   7000     }
   7001 
   7002     data16 = (1 << 2);   /* Set FIFO Elasticity to 13.5k */
   7003     data16 |= soc_feature(unit, soc_feature_unimac_tx_crs)?
   7004               DIGITAL_CONTROL1000X3_DISABLE_TX_CRS_MASK:
   7005               0;  /* set disable_tx_crs bit accordingly */
   7006  
   7007     SOC_IF_ERROR_RETURN
   7008         (MODIFY_HL65_DIGITAL_CONTROL1000X3r(unit, pc,
   7009              data16,
   7010              DIGITAL_CONTROL1000X3_DISABLE_TX_CRS_MASK |
   7011              DIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK));
   7012 
   7013     return(SOC_E_NONE);
   7014 }
   7015 
   7016 
   7017 #else /* INCLUDE_XGXS_HL65 */
   7018 int _xgxs_hl65_not_empty;
   7019 #endif /* INCLUDE_XGXS_HL65 */