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

phy82328.c (241121B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:       phy82328.c
      8  * Purpose:    Phys Driver support for Broadcom 82328 40G phy
      9  * Note:      
     10  *
     11  * Specifications:
     12 
     13  * Repeater mode only, no retimer operation.
     14 
     15  * Supports the following data speeds:
     16  * 1.25 Gbps line rate (1 GbE data rate, 8x oversampled over 10 Gbps line rate)
     17  * 10.3125 Gbps line rate (10 GbE data rate)
     18  * 11.5 Gpbs line rate (for backplane application, proprietary data rate)
     19  * 410.3125 Gbps line rate (40 GbE data rate)
     20  * 
     21  * Supports the following line-side connections:
     22  * 1 GbE and 10 GbE SFP+ SR and LR optical modules
     23  * 40 GbE QSFP SR4 and LR4 optical modules
     24  * 1 GbE and 10 GbE SFP+ CR (CX1) copper cable
     25  * 40 GbE QSFP CR4 copper cable
     26  * 10 GbE KR, 11.5 Gbps line rate and 40 GbE KR4 backplanes
     27  *
     28  * Operates with the following reference clocks:
     29  * Single 156.25 MHz differential clock for 1.25 Gbps, 10.3125 Gpbs and 11.5 Gbps
     30  * line rates
     31  *
     32  * Supports autonegotiation as follows:
     33  * Clause 73 only for starting Clause 72 and requesting FEC 
     34  * No speed resolution performed
     35  * No Clause 73 in 11.5 Gbps line rate, only Clause 72 supported
     36  * Clause 72 may be enabled standalone for close systems
     37  * Clause 37 is not supported
     38  * No on-chip FEC encoding/decoding, but shall pass-through FEC-encoded data. 
     39  */
     40 
     41 #if defined(INCLUDE_PHY_82328) /* INCLUDE_PHY_82328 */
     42  
     43 #include <sal/types.h>
     44 #include <shared/bsl.h>
     45 #include <soc/drv.h>
     46 #include <soc/debug.h>
     47 #include <soc/error.h>
     48 #include <soc/phyreg.h>
     49  
     50 #include <soc/phy.h>
     51 #include <soc/phy/phyctrl.h>
     52 #include <soc/phy/drv.h>
     53  
     54 #include "phydefs.h"      /* Must include before other phy related includes */
     55 #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
     56 #include "phyident.h"
     57 #include "phyreg.h"
     58 #include "phynull.h"
     59 #include "phyxehg.h"
     60 #include "phy82328.h"
     61 extern unsigned char phy82328_ucode_bin[];
     62 extern unsigned int phy82328_ucode_bin_len;
     63 static char *dev_name_82328_a0 = "BCM82328_A0";
     64 static char *dev_name_82328f_a0 = "BCM82328F_A0";
     65 
     66 extern unsigned char phy82328B0_ucode_bin[];
     67 extern unsigned int phy82328B0_ucode_bin_len;
     68 static char *dev_name_82328_b0 = "BCM82328_B0";
     69 static char *dev_name_82322_b1 = "BCM82322_B1";
     70 static char *dev_name_82328_b1 = "BCM82328_B1";
     71 static char *dev_name_82328f_b0 = "BCM82328F_B0";
     72 static char *dev_name_82328f_b1 = "BCM82328F_B1";
     73 #define PHY82328B1_CHIP_REV    (0x00b1)
     74 #define PHY82328B0_CHIP_REV    (0x00b0)
     75 #define PHY82328A0_CHIP_REV    (0x00a0)
     76 static char *dev_name_82322 = "BCM82322";
     77 #define PHY82328_DEV_PMA_PMD                     1
     78 #define PHY82328_DEV_AN                          2
     79 #define PHY82328_ENABLE                          1
     80 #define PHY82328_DISABLE                         0
     81 #define PHY82328_TOTAL_WR_BYTE                   0x4000 
     82 #define PHY82328_ID_82328                        0x82328 /* Gallardo_28nm_oct_opt */
     83 #define PHY82328_ID_82328F                       0x8232f /* Gallardo_28nm_oct_opt */
     84 #define PHY82328_ID_82322                        0x82322 /* Gallardo_28nm_oct_opt */
     85 #define PHY82328_NUM_LANES                       4
     86 #define PHY82328_20G_NUM_LANES                   2
     87 #define PHY82328_ALL_LANES                       0xf
     88 #define PHY82328_POL_DND                         0xFFFF
     89 #define PHY82328_SPD_1G                          1000
     90 #define PHY82328_SPD_10G                         10000
     91 #define PHY82328_SPD_11G                         11000
     92 #define PHY82328_SPD_40G                         40000
     93 #define PHY82328_SPD_20G                         20000
     94 #define PHY82328_SPD_42G                         42000
     95 #define PHY82328_SPD_100G                        100000
     96 #define PHY82328_GP_REG_1_SPD_100G               (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_100G_SHIFT)
     97 #define PHY82328_GP_REG_1_SPD_42G                ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_SHIFT)| \
     98                                                  (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_SHIFT) | \
     99                                                  (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_SHIFT))
    100 #define PHY82328_GP_REG_1_SPD_40G                (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_SHIFT)
    101 #define PHY82328_GP_REG_1_SPD_11G                ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_SHIFT)| \
    102                                                  (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_SHIFT))
    103 #define PHY82328_GP_REG_1_SPD_10G                (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_SHIFT)
    104 #define PHY82328_GP_REG_1_SPD_1G                 ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_SHIFT) | \
    105                                                  (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_SHIFT))
    106 
    107 #define PHY82328_4BIT_DP_DEPTH1                  (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_ENABLE_ULTRA_LOW_LATENCY_DATAPATH_SHIFT)
    108 #define PHY82328_4BIT_DP_DEPTH2                  ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_ENABLE_ULTRA_LOW_LATENCY_DATAPATH_SHIFT) | \
    109                                                  (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_ULL_DATAPATH_LATENCY_SHIFT))
    110 
    111 #define PHY82328_SINGLE_PORT_MODE(_pc) \
    112     (SOC_INFO((_pc)->unit).port_num_lanes[(_pc)->port] >= 4)
    113 
    114 #define PHY82328_AN_CTRL_REG                     0x0000
    115 #define PHY82328_AN_STS_REG                      0x0001
    116 #define PHY82328_AN_STS_LINK_STS_MSK             0x0004
    117 #define PHY82328_AN_ENABLE_MSK                   (1<<12)
    118 #define PHY82328_AN_COMPLETE_MSK                 (1<<5)
    119 
    120 /* I2C related defines */
    121 #define PHY82328_BSC_XFER_MAX     0x1F9
    122 #define PHY82328_BSC_WR_MAX       16
    123 #define PHY82328_WRITE_START_ADDR 0x8007
    124 #define PHY82328_READ_START_ADDR  0x8007
    125 #define PHY82328_WR_FREQ_400KHZ   0x0100
    126 #define PHY82328_2W_STAT          0x000C
    127 #define PHY82328_2W_STAT_IDLE     0x0000
    128 #define PHY82328_2W_STAT_COMPLETE 0x0004
    129 #define PHY82328_2W_STAT_IN_PRG   0x0008
    130 #define PHY82328_2W_STAT_FAIL     0x000C
    131 #define PHY82328_BSC_WRITE_OP     0x22
    132 #define PHY82328_BSC_READ_OP      0x2
    133 #define PHY82328_I2CDEV_WRITE     0x1
    134 #define PHY82328_I2CDEV_READ      0x0
    135 #define PHY82328_I2C_8BIT         0
    136 #define PHY82328_I2C_16BIT        1
    137 #define PHY82328_I2C_TEMP_RAM     0xE
    138 #define PHY82328_I2C_OP_TYPE(access_type,data_type) \
    139         ((access_type) | ((data_type) << 8))
    140 #define PHY82328_I2C_ACCESS_TYPE(op_type) ((op_type) & 0xff)
    141 #define PHY82328_I2C_DATA_TYPE(op_type)   (((op_type) >> 8) & 0xff)
    142 #define PHY82328_I2CM_IDLE_WAIT_MSEC                        350
    143 #define PHY82328_I2CM_IDLE_WAIT_CHUNK                       10
    144 #define PHY82328_I2CM_IDLE_WAIT_COUNT     (PHY82328_I2CM_IDLE_WAIT_MSEC / PHY82328_I2CM_IDLE_WAIT_CHUNK)
    145 
    146 #define PHY82328_PREEMPHASIS_LANE_GET(_T, _L)           \
    147     if (_T == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) {      \
    148         _L = 0; }                                       \
    149     else if (_T == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) { \
    150         _L = 1; }                                       \
    151     else if (_T == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) { \
    152         _L = 2; }                                       \
    153     else if (_T == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) { \
    154         _L = 3; }                                       \
    155     else {                                              \
    156         _L = PHY82328_ALL_LANES; }
    157 
    158 
    159 static const char *phy82328_intf_names[] = SOC_PORT_IF_NAMES_INITIALIZER;
    160 int eye_consol_val[64][64];
    161 
    162 /* interface params */
    163 typedef struct phy82328_intf_cfg {
    164     int32          speed;
    165     soc_port_if_t  type;
    166 } phy82328_intf_cfg_t;
    167 
    168 typedef	enum {
    169     PHY82328_DATAPATH_20,
    170     PHY82328_DATAPATH_4_DEPTH_1,
    171     PHY82328_DATAPATH_4_DEPTH_2
    172 }phy82328_datapath_t;
    173 
    174 typedef enum {
    175     PHY82328_INTF_SIDE_LINE,
    176     PHY82328_INTF_SIDE_SYS
    177 } phy82328_intf_side_t;
    178 
    179 typedef struct {
    180     int32 enable;
    181     int32	count;					/* resume only if count==0 */
    182 } phy82328_micro_ctrl_t;
    183 
    184 typedef struct {
    185     uint32              devid;
    186     uint32              devrev;
    187     int32               p2l_map[PHY82328_NUM_LANES];  /* index: physical lane, array element: */
    188     phy82328_intf_cfg_t line_intf;
    189     phy82328_intf_cfg_t sys_intf;
    190     uint16              pol_tx_cfg;
    191     uint16              pol_rx_cfg;
    192     int32               mod_auto_detect;			  /* module auto detect enabled */
    193     phy82328_datapath_t cfg_datapath;
    194     phy82328_datapath_t cur_datapath;
    195     int32               an_en;
    196     uint16              logical_lane0;
    197     int32               sys_forced_cl72;
    198     int32               sync_init;
    199     phy82328_micro_ctrl_t  micro_ctrl;
    200     int32               fw_rx_los;
    201     int32               int_phy_re_en;
    202     soc_timeout_t       sync_to;
    203     int                 cfg_sys_intf;
    204     uint16              port_disabled;
    205 } phy82328_dev_desc_t;
    206 
    207 #define DEVID(_pc)              (((phy82328_dev_desc_t *)((_pc) + 1))->devid)
    208 #define DEVREV(_pc)             (((phy82328_dev_desc_t *)((_pc) + 1))->devrev)
    209 #define P2L_MAP(_pc,_ix)        (((phy82328_dev_desc_t *)((_pc) + 1))->p2l_map[(_ix)])
    210 #define LINE_INTF(_pc)          (((phy82328_dev_desc_t *)((_pc) + 1))->line_intf)
    211 #define SYS_INTF(_pc)           (((phy82328_dev_desc_t *)((_pc) + 1))->sys_intf)
    212 #define POL_TX_CFG(_pc)	        (((phy82328_dev_desc_t *)((_pc) + 1))->pol_tx_cfg)
    213 #define POL_RX_CFG(_pc)	        (((phy82328_dev_desc_t *)((_pc) + 1))->pol_rx_cfg)
    214 #define MOD_AUTO_DETECT(_pc)    (((phy82328_dev_desc_t *)((_pc) + 1))->mod_auto_detect)
    215 #define CFG_DATAPATH(_pc)       (((phy82328_dev_desc_t *)((_pc) + 1))->cfg_datapath)
    216 #define CUR_DATAPATH(_pc)       (((phy82328_dev_desc_t *)((_pc) + 1))->cur_datapath)
    217 #define AN_EN(_pc)              (((phy82328_dev_desc_t *)((_pc) + 1))->an_en)
    218 #define SYS_FORCED_CL72(_pc)    (((phy82328_dev_desc_t *)((_pc) + 1))->sys_forced_cl72)
    219 #define SYNC_INIT(_pc)	        (((phy82328_dev_desc_t *)((_pc) + 1))->sync_init)
    220 #define MICRO_CTRL(_pc)	        (((phy82328_dev_desc_t *)((_pc) + 1))->micro_ctrl)
    221 #define FW_RX_LOS(_pc)	        (((phy82328_dev_desc_t *)((_pc) + 1))->fw_rx_los)
    222 #define LOGICAL_LANE0(_pc)		(((phy82328_dev_desc_t *)((_pc) + 1))->logical_lane0)
    223 #define SYNC_TO(_pc)			(((phy82328_dev_desc_t *)((_pc) + 1))->sync_to)
    224 #define INT_PHY_RE_EN(_pc)		(((phy82328_dev_desc_t *)((_pc) + 1))->int_phy_re_en)
    225 #define CFG_SYS_INTF(_pc)		(((phy82328_dev_desc_t *)((_pc) + 1))->cfg_sys_intf)
    226 #define PORT_DISABLED(_pc)		(((phy82328_dev_desc_t *)((_pc) + 1))->port_disabled)
    227 
    228 
    229 #define PHY_82328_MICRO_PAUSE(_u, _p, _s) \
    230     do { \
    231         phy_ctrl_t *_pc; \
    232         _pc = EXT_PHY_SW_STATE((_u), (_p)); \
    233         if (DEVREV(_pc) == PHY82328A0_CHIP_REV || DEVREV(_pc) == PHY82328B0_CHIP_REV || DEVREV(_pc) == PHY82328B1_CHIP_REV) { \
    234             _phy_82328_micro_pause((_u), (_p), (_s)); \
    235         } \
    236     } while (0) 
    237 
    238 #define PHY_82328_MICRO_RESUME(_u, _p)\
    239     do { \
    240         phy_ctrl_t *_pc; \
    241         _pc = EXT_PHY_SW_STATE((_u), (_p)); \
    242         if (DEVREV(_pc) == PHY82328A0_CHIP_REV || DEVREV(_pc) == PHY82328B0_CHIP_REV || DEVREV(_pc) == PHY82328B1_CHIP_REV) { \
    243             _phy_82328_micro_resume((_u), (_p)); \
    244         } \
    245     } while (0) 
    246 
    247 #define POL_CONFIG_LANE_MASK(_l)           (1 << _l)
    248 
    249 /* QSFI_RX :: anaRxStatus :: status_sel [02:00] */
    250 #define QSFI_RX_ANARXSTATUS_SM_SEL_MASK            0x0007
    251 
    252 /* QSFI_RX :: anaRxStatus :: status_sel [02:00] */
    253 #define QSFI_RX_ANARXSTATUS_PMD_RX_PMD_LOCK_MASK   0x1000
    254 
    255 /* REMOTE PHY ABLITY REG*/
    256 #define PHY82328_RMT_PHY_ABLITY_REG                0xc450
    257 
    258 /* REMOTE PHY VALID FLAG*/
    259 #define PHY82328_RMT_PHY_ABLITY_VALID_MASK         0x8
    260 #define PHY82328_RMT_PHY_ABLITY_KR_MASK            0x10
    261 #define PHY82328_RMT_PHY_ABLITY_KR2_MASK           0x20
    262 #define PHY82328_RMT_PHY_ABLITY_KR4_MASK           0x40
    263 #define PHY82328_RMT_PHY_ABLITY_PAUSE_MASK         0x3800
    264 #define PHY82328_RMT_PHY_ABLITY_FEC_MASK           0xC000
    265 
    266 /* EYE SCAN RELATED MACROS & ENUMS*/
    267 #define PHY82328_STS_IS_MICRO_STOPPED(u, p,  pc, sts)                         phy82328_serdes_rdbl_uc_var(u, p, pc, 0x11, &sts)
    268 #define PHY82328_TRNSUM_TAP_5_TO_N2            0
    269 #define PHY82328_TRNSUM_TAP_0                  4
    270 #define PHY82328_DSC_STATE_UC_TUNE             7
    271 #define PHY82328_RD_UC_DSC_RDY_FOR_CMD(u, pc, rdy)                         \
    272     SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(u, pc, DSC_A_DSC_UC_CTRL, &rdy));      \
    273     rdy = (rdy & 0x0080) >> 7;
    274 
    275 /** SERDES_PMD_UC_COMMANDS Enum */
    276 typedef enum PHY82328_SERDES_PMD_UC_CMD {
    277   PHY82328_CMD_NULL                =  0,
    278   PHY82328_CMD_UC_CTRL             =  1,
    279   PHY82328_CMD_HEYE_OFFSET         =  2,
    280   PHY82328_CMD_VEYE_OFFSET         =  3,
    281   PHY82328_CMD_FREEZE_STEADY_STATE =  4,
    282   PHY82328_CMD_DIAG_EN             =  5,
    283   PHY82328_CMD_READ_UC_LANE_BYTE   =  6,
    284   PHY82328_CMD_WRITE_UC_LANE_BYTE  =  7,
    285   PHY82328_CMD_READ_UC_CORE_BYTE   =  8,
    286   PHY82328_CMD_WRITE_UC_CORE_BYTE  =  9,
    287   PHY82328_CMD_READ_UC_LANE_WORD   = 10,
    288   PHY82328_CMD_WRITE_UC_LANE_WORD  = 11,
    289   PHY82328_CMD_READ_UC_CORE_WORD   = 12,
    290   PHY82328_CMD_WRITE_UC_CORE_WORD  = 13,
    291   PHY82328_CMD_EVENT_LOG_CTRL      = 14,
    292   PHY82328_CMD_EVENT_LOG_READ      = 15
    293 }PHY82328_SERDES_PMD_UC_CMD;
    294 
    295 /** SERDES_UC_CTRL_COMMANDS Enum */
    296 typedef enum PHY82328_SERDES_PMD_UC_CTRL_CMD {
    297   PHY82328_CMD_UC_CTRL_STOP_GRACEFULLY   = 0,
    298   PHY82328_CMD_UC_CTRL_STOP_IMMEDIATE    = 1,
    299   PHY82328_CMD_UC_CTRL_RESUME            = 2,
    300   PHY82328_CMD_UC_CTRL_STOP_HOLD         = 3,
    301   PHY82328_CMD_UC_CTRL_RELEASE_HOLD_ONCE = 4
    302 }PHY82328_SERDES_PMD_UC_CTRL_CMD;
    303 
    304 typedef enum PHY82328_TRNSUM_ERR_SEL {
    305   PHY82328_TRNSUM_ERR_SEL_EMUX = 0,
    306   PHY82328_TRNSUM_ERR_SEL_1    = 1,
    307   PHY82328_TRNSUM_ERR_SEL_M1   = 2,
    308   PHY82328_TRNSUM_ERR_SEL_P1   = 3
    309 }PHY82328_TRNSUM_ERR_SEL;
    310 
    311 soc_port_if_t phy82328_sys_to_port_if[] = {
    312     0,                                  /* PHY_SYSTEM_INTERFACE_DFLT    */
    313     SOC_PORT_IF_KX,                     /* PHY_SYSTEM_INTERFACE_KX      */
    314     SOC_PORT_IF_KR,                     /* PHY_SYSTEM_INTERFACE_KR      */
    315     SOC_PORT_IF_SR,                     /* PHY_SYSTEM_INTERFACE_SR      */
    316     SOC_PORT_IF_LR,                     /* PHY_SYSTEM_INTERFACE_LR      */
    317     SOC_PORT_IF_CR,                     /* PHY_SYSTEM_INTERFACE_CR      */
    318     SOC_PORT_IF_KR4,                    /* PHY_SYSTEM_INTERFACE_KR4     */
    319     SOC_PORT_IF_SR4,                    /* PHY_SYSTEM_INTERFACE_SR4     */
    320     SOC_PORT_IF_LR4,                    /* PHY_SYSTEM_INTERFACE_LR4     */
    321     SOC_PORT_IF_CR4,                    /* PHY_SYSTEM_INTERFACE_CR4     */
    322     SOC_PORT_IF_XFI,                    /* PHY_SYSTEM_INTERFACE_XFI     */
    323     SOC_PORT_IF_XLAUI,                  /* PHY_SYSTEM_INTERFACE_XLAUI   */
    324         
    325 };
    326 
    327 #ifdef PHY82328_MDIO_DEBUGGING
    328 #undef  READ_PHY_REG
    329 #define READ_PHY_REG(_unit, _pc,  _addr, _value) \
    330             ((_phy_82328_dbg_read)((_pc->unit), _pc, (_addr), (_value)))
    331 #undef  WRITE_PHY_REG
    332 #define WRITE_PHY_REG(_unit, _pc, _addr, _value) \
    333             ((_phy_82328_dbg_write)((_pc->unit), _pc, (_addr), (_value)))
    334 #undef  MODIFY_PHY_REG
    335 #define MODIFY_PHY_REG(_unit, _pc, _addr, _data, _mask) \
    336 			(_phy_82328_dbg_modify((_unit), (_pc), (_addr), (_data), (_mask)))
    337 #endif
    338 
    339 /* dsc values */
    340 typedef struct {       
    341     uint8 osr_mode;
    342     uint16 ucv_config;
    343     uint8 sig_det;
    344     uint8 rx_lock;
    345     int16 rx_ppm;
    346     int8 clk90;
    347     int8 clkp1;
    348     uint8 pf_main;
    349     uint8 pf_hiz;
    350     uint8 pf_bst;
    351     uint8 pf_low;
    352     uint8 vga;
    353     int8 dc_offset;
    354     uint8 p1_lvl_ctrl;
    355     uint8 dfe1;
    356     int8 dfe2;
    357     int8 dfe3;
    358     int8 dfe4;
    359     int8 dfe5;
    360     int8 dfe1_dcd;
    361     int8 dfe2_dcd;
    362     int8 pe;
    363     int8 ze;
    364     int8 me;
    365     int8 po;
    366     int8 zo;
    367     int8 mo;
    368     uint8 tx_ppm;
    369     uint8 txfir_pre; 
    370     uint8 txfir_main;
    371     uint8 txfir_post1; 
    372     uint8 txfir_post2;
    373     uint8 heye_left;
    374     uint8 heye_right;
    375     uint8 veye_upper;
    376     uint8 veye_lower;
    377     uint8 br_pd_en;
    378 } phy82328_serdes_lane_state;
    379 
    380 #define PHY82328_CONV_SIGNED_BYTE(_D, _M, _L)                \
    381         _D <<= (15 - (_M));                                  \
    382         _D >>= (15 - (_M) + (_L));                           \
    383         _D &= (0xFF);
    384 
    385 
    386 STATIC int32
    387 _phy_82328_channel_select(int32 unit, soc_port_t port, phy82328_intf_side_t side, int32 lane);
    388 STATIC int32
    389 _phy_82328_polarity_flip(int32 unit, soc_port_t port, uint16 cfg_tx_pol, uint16 cfg_rx_pol);
    390 STATIC int32
    391 phy_82328_control_get(int32 unit, soc_port_t port,
    392                      soc_phy_control_t type, uint32 *value);
    393 STATIC int32
    394 phy_82328_control_set(int32 unit, soc_port_t port,
    395                      soc_phy_control_t type, uint32 value);
    396 STATIC void
    397 _phy_82328_micro_pause(int32 unit, soc_port_t port, const char *loc);
    398 STATIC void
    399 _phy_82328_micro_resume(int32 unit, soc_port_t port);
    400 STATIC int32
    401 _phy_82328_debug_info(int32 unit, soc_port_t port);
    402 STATIC int32
    403 _phy_82328_intf_line_sys_init(int32 unit, soc_port_t port);
    404 STATIC int32
    405 _phy_82328_intf_type_set(int32 unit, soc_port_t port, soc_port_if_t pif, int32 must_update);
    406 STATIC int32
    407 phy_82328_an_get(int32 unit, soc_port_t port, int32 *an, int32 *an_done);
    408 STATIC int32
    409 _phy_82328_intf_line_sys_update(int32 unit, soc_port_t port);
    410 
    411 STATIC int32
    412 _phy_82328_speed_set(int32 unit, soc_port_t port, int32 speed);
    413 
    414 STATIC int32 
    415 phy_82328_regbit_set_wait_check(int32 unit ,int32 port,
    416                                 int32 reg, int32 bit_num,
    417                                 int32 bitset, int32 timeout);
    418 STATIC int32
    419 _phy_82328_rx_los_control_set(int32 unit, soc_port_t port, uint32 value);
    420 
    421 
    422 #ifdef PHY82328_MDIO_DEBUGGING
    423 STATIC int32
    424 _phy_82328_dbg_read(int32 unit, phy_ctrl_t *pc, uint32 addr, uint16 *data)
    425 {
    426 	int32 rv;
    427 	rv = (pc->read)(unit, pc->phy_id, addr, data);
    428 
    429     LOG_INFO(BSL_LS_SOC_PHY,
    430              (BSL_META_U(unit,
    431                          "Read Addr=0x%04x Val=0x%04x\n"), addr, *data));
    432 	return rv;
    433 		
    434 }
    435 
    436 STATIC int32
    437 _phy_82328_dbg_write(int32 unit, phy_ctrl_t *pc, uint32 addr, uint16 data)
    438 {
    439 	int32 rv;
    440     LOG_INFO(BSL_LS_SOC_PHY,
    441              (BSL_META_U(unit,
    442                          "Write Addr=0x%04x Val=0x%04x\n"), addr, data));
    443 	rv = (pc->write)(unit, pc->phy_id, addr, data);
    444 	return rv;
    445 }
    446 
    447 STATIC int32
    448 _phy_82328_dbg_modify(int32 unit, phy_ctrl_t *pc, uint32 addr, uint16 data, uint16 mask)
    449 {
    450 	int32 rv;
    451 	rv = phy_reg_modify(unit, pc, addr, data, mask);
    452 	rv = (pc->read)(unit, pc->phy_id, addr, &data);
    453     LOG_INFO(BSL_LS_SOC_PHY,
    454              (BSL_META_U(unit,
    455                          "Write Addr=0x%04x Val=0x%04x\n"), addr, data));
    456 	return rv;
    457 }
    458 #endif
    459 
    460 STATIC 
    461 int32 phy82328_intf_side_reg_select(int unit, soc_port_t port, uint16 intf)
    462 {
    463     phy_ctrl_t *pc;
    464     pc = EXT_PHY_SW_STATE(unit, port);
    465 
    466         SOC_IF_ERROR_RETURN
    467             (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, intf));
    468     return SOC_E_NONE;
    469 }
    470 
    471 STATIC
    472 int32 _phy_82328_modify_pma_pmd_reg (int32 unit, int32 port, phy_ctrl_t *pc, 
    473                                uint16 dev, uint16 address, uint8 msb_pos, 
    474                                uint8 lsb_pos, uint16 data)
    475 {
    476     uint16 mask = 0, i =0;
    477 
    478     for (i = lsb_pos; i<=msb_pos; i++) {
    479         mask |= (1 << i);
    480     }
    481    
    482     data = data << lsb_pos; 
    483     if (dev == PHY82328_DEV_PMA_PMD) {
    484         SOC_IF_ERROR_RETURN
    485             (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, address,
    486                                         data, mask));
    487     } else { 
    488         SOC_IF_ERROR_RETURN
    489             (MODIFY_PHY82328_MMF_AN_REG(unit, pc, address,
    490                                         data, mask));
    491     }
    492     return SOC_E_NONE;
    493 }
    494 
    495 STATIC
    496 int32 _phy_82328_set_bcast_mode(int32 unit, int32 port,
    497                                int16 ena_dis)
    498 {
    499     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
    500 
    501     SOC_IF_ERROR_RETURN
    502         (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 
    503          PHY82328_DEV_PMA_PMD, MGT_TOP_BROADCAST_CTRL,
    504          MGT_TOP_PMD_USR_BROADCAST_CTRL_BROADCAST_MODE_ENABLE_SHIFT, 
    505          MGT_TOP_PMD_USR_BROADCAST_CTRL_BROADCAST_MODE_ENABLE_SHIFT, ena_dis));
    506 
    507     return SOC_E_NONE;
    508 }
    509 
    510 STATIC
    511 int32 _phy_82328_soft_reset(int32 unit, int32 port)
    512 {
    513     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
    514 
    515     SOC_IF_ERROR_RETURN
    516         (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 
    517          PHY82328_DEV_PMA_PMD, IEEE0_BLK_PMA_PMD_PMD_CONTROL_REGISTER,
    518          QSFI_IEEE0_PMD_CONTROL_REGISTER_RESET_SHIFT, 
    519          QSFI_IEEE0_PMD_CONTROL_REGISTER_RESET_SHIFT, 1));
    520 
    521     return SOC_E_NONE;
    522 }
    523 
    524 STATIC 
    525 int32 _phy_82328_rom_fw_dload (int32 unit, int32 port, int32 offset, 
    526                                 uint8 *new_fw, uint32 datalen)
    527 {
    528     uint32 wr_data = 0, j = 0;
    529     uint16 data16 = 0, temp = 0;
    530     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 
    531     if (offset == PHYCTRL_UCODE_BCST_SETUP) {
    532         /* Enable Bcast */
    533         LOG_INFO(BSL_LS_SOC_PHY,
    534                  (BSL_META_U(unit,
    535                              "PHY82328 Enable Bcast u:%d p:%d\n"),
    536                              unit, port));
    537         SOC_IF_ERROR_RETURN (_phy_82328_set_bcast_mode(unit, port,
    538                           PHY82328_ENABLE));
    539         return SOC_E_NONE;
    540     } else if (offset == PHYCTRL_UCODE_BCST_uC_SETUP) {
    541         LOG_INFO(BSL_LS_SOC_PHY,
    542                  (BSL_META_U(unit,
    543                              "PHY82328 uC setup u:%d p:%d\n"),
    544                              unit, port));
    545 
    546         /* uController reset */
    547         SOC_IF_ERROR_RETURN
    548             (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 
    549              PHY82328_DEV_PMA_PMD, MGT_TOP_GEN_CTRL,
    550              MGT_TOP_CMN_CTLR_GEN_CTRL_UCRST_SHIFT, 
    551              MGT_TOP_CMN_CTLR_GEN_CTRL_UCRST_SHIFT, PHY82328_ENABLE));
    552 
    553         SOC_IF_ERROR_RETURN(_phy_82328_soft_reset(unit, port));
    554         sal_udelay(3000);
    555         return SOC_E_NONE;
    556     } else if (offset == PHYCTRL_UCODE_BCST_ENABLE) {
    557         /* Re Enable Bcast */
    558         SOC_IF_ERROR_RETURN (_phy_82328_set_bcast_mode(unit, port,
    559                           PHY82328_ENABLE));
    560         return SOC_E_NONE;
    561     } else if (offset == PHYCTRL_UCODE_BCST_LOAD) {
    562         LOG_INFO(BSL_LS_SOC_PHY,
    563                  (BSL_META_U(unit,
    564                              "PHY82328 uCode load u:%d p:%d\n"),
    565                              unit, port));
    566 
    567         /*Select MDIO FOR ucontroller download */
    568         SOC_IF_ERROR_RETURN
    569          (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 
    570           PHY82328_DEV_PMA_PMD, MGT_TOP_SPA_CONTROL_STATUS_REGISTER,
    571           MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_PORT_USED_SHIFT, 
    572           MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_PORT_USED_SHIFT, 
    573           PHY82328_DISABLE));
    574         
    575         /* Clear Download Done */
    576         SOC_IF_ERROR_RETURN
    577          (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 
    578           PHY82328_DEV_PMA_PMD, MGT_TOP_SPA_CONTROL_STATUS_REGISTER,
    579           MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_DWLD_DONE_SHIFT, 
    580           MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_DWLD_DONE_SHIFT, 
    581           PHY82328_DISABLE));
    582 
    583         SOC_IF_ERROR_RETURN
    584          (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 
    585          PHY82328_DEV_PMA_PMD, MGT_TOP_SPA_CONTROL_STATUS_REGISTER,
    586          MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_BOOT_SHIFT, 
    587          MGT_TOP_PMD_USR_SPA_CONTROL_STATUS_REGISTER_SPI_BOOT_SHIFT, 
    588          PHY82328_ENABLE));
    589 
    590    
    591         /* Set Dload size to 32K */
    592         SOC_IF_ERROR_RETURN
    593          (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 
    594           PHY82328_DEV_PMA_PMD, MGT_TOP_MISC_CTRL,
    595           MGT_TOP_CMN_CTLR_MISC_CTRL_SPI_DOWNLOAD_SIZE_SHIFT,
    596           MGT_TOP_CMN_CTLR_MISC_CTRL_SPI_DOWNLOAD_SIZE_SHIFT, 
    597           PHY82328_ENABLE));
    598 
    599         /* uController reset */
    600         SOC_IF_ERROR_RETURN
    601          (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 
    602           PHY82328_DEV_PMA_PMD, MGT_TOP_GEN_CTRL,
    603           MGT_TOP_CMN_CTLR_GEN_CTRL_UCRST_SHIFT, 
    604           MGT_TOP_CMN_CTLR_GEN_CTRL_UCRST_SHIFT, PHY82328_DISABLE));
    605 
    606         sal_udelay(3000);    /*wait for 3ms to initialize the RAM*/
    607 
    608         /*Write Address*/
    609         SOC_IF_ERROR_RETURN
    610           (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MSG_IN, 0x8000));
    611 
    612         /* Make sure Address word is read by the Micro*/
    613         sal_udelay(10);
    614 
    615         wr_data = (datalen/2);            /*16k ROM*/
    616         SOC_IF_ERROR_RETURN
    617             (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MSG_IN, wr_data));
    618         sal_udelay(10);
    619    
    620         /* Fill in the SRAM */
    621         wr_data = (datalen - 1);
    622         for (j = 0; j < wr_data; j+=2) {
    623             /*Make sure the word is read by the Micro */
    624             sal_udelay(10);        
    625             data16 = (new_fw[j] << 8) | new_fw[j+1];
    626             SOC_IF_ERROR_RETURN
    627             (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MSG_IN, data16));
    628         }
    629         return SOC_E_NONE;
    630     } else if(offset== PHYCTRL_UCODE_BCST_END) {
    631         int i = 0;
    632         sal_udelay(20);
    633         if ((pc->phy_id & 3) != 0) {
    634             return SOC_E_NONE;
    635         }
    636         temp = pc->phy_id;
    637         for (i = 0; i <= 3; i++) {
    638             pc->phy_id &= ~3;
    639             pc->phy_id |= i;
    640             SOC_IF_ERROR_RETURN
    641                 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MSG_OUT, &data16));
    642     
    643             LOG_INFO(BSL_LS_SOC_PHY,
    644                      (BSL_META_U(unit,
    645                                  "PHY82328 FW load done u:%d p:%d Read Done:0x%x\n"),
    646                                  unit, port, data16));
    647 
    648             sal_udelay(4000);
    649             SOC_IF_ERROR_RETURN
    650                 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_4, &data16));
    651 
    652             LOG_INFO(BSL_LS_SOC_PHY,
    653                      (BSL_META_U(unit,
    654                                  "PHY82328 FW load done u:%d p:%d chksum:0x%x\n"),
    655                                  unit, port, data16));
    656 
    657             if (data16 != 0x600D) {
    658                 LOG_ERROR(BSL_LS_SOC_PHY,
    659                           (BSL_META_U(unit,
    660                                       "Invalid Checksum:0x%x\n"), data16));
    661                 pc->phy_id = temp;
    662                 /* Disable Bcast */
    663                 SOC_IF_ERROR_RETURN (_phy_82328_set_bcast_mode(unit, port,
    664                                       PHY82328_DISABLE));
    665                 return SOC_E_INTERNAL;
    666             }
    667             /*Check the register to read*/
    668             SOC_IF_ERROR_RETURN
    669              (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0xc161, &data16)); 
    670 
    671             LOG_CLI((BSL_META_U(unit,
    672                                 "PHY82328 u:%d p:%d Rom Version(Reg:0xc161):0x%x\n"), 
    673                      unit, port, (data16 & 0xFF)));
    674 
    675             /* Disable Bcast */
    676             SOC_IF_ERROR_RETURN (_phy_82328_set_bcast_mode(unit, port,
    677                               PHY82328_DISABLE));
    678 
    679             data16 = (PHY82328_SINGLE_PORT_MODE(pc)) ?
    680                      MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK : 0;
    681             SOC_IF_ERROR_RETURN
    682                (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
    683                MGT_TOP_SINGLE_PMD_CTRL, data16,
    684                MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK));
    685             pc->phy_id = temp;
    686             if (PHY82328_SINGLE_PORT_MODE(pc)) {
    687                 break;
    688             }
    689             /* Make sure micro completes its initialization */
    690             sal_udelay(5000);
    691         }
    692         pc->phy_id = temp;
    693     } else {
    694         LOG_ERROR(BSL_LS_SOC_PHY,
    695                   (BSL_META_U(unit,
    696                               "u=%d p=%d PHY82328 firmware_bcst: invalid cmd 0x%x\n"),
    697                    unit, port, offset));
    698     }
    699     return SOC_E_NONE;
    700 }
    701 
    702 STATIC int32
    703 _phy_82328_intf_is_single_port(soc_port_if_t intf_type)
    704 {
    705 	int32 rv;
    706 
    707     switch (intf_type) {
    708         case SOC_PORT_IF_CR4:
    709         case SOC_PORT_IF_KR4:
    710         case SOC_PORT_IF_XLAUI:
    711         case SOC_PORT_IF_LR4:
    712         case SOC_PORT_IF_SR4:
    713 	        rv = TRUE;
    714 		break;
    715         default:
    716 		    rv = FALSE;
    717     }
    718     return rv;
    719 }
    720 
    721 STATIC int32
    722 _phy_82328_intf_is_quad_port(soc_port_if_t intf_type)
    723 {
    724 	int32 rv;
    725 
    726     switch (intf_type) {
    727         case SOC_PORT_IF_SR:
    728         case SOC_PORT_IF_CR:
    729         case SOC_PORT_IF_KR:
    730         case SOC_PORT_IF_XFI:
    731         case SOC_PORT_IF_SFI:
    732         case SOC_PORT_IF_LR:
    733         case SOC_PORT_IF_ZR:
    734         case SOC_PORT_IF_KX:
    735         case SOC_PORT_IF_GMII:
    736         case SOC_PORT_IF_SGMII:
    737             rv = TRUE;
    738 		break;
    739         default:
    740 		    rv = FALSE;
    741     }
    742     return rv;
    743 }
    744 
    745 STATIC int32
    746 _phy_82328_intf_line_sys_params_get(int32 unit, soc_port_t port)
    747 {
    748     phy82328_intf_cfg_t *line_intf;
    749     phy82328_intf_cfg_t *sys_intf;
    750     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
    751 
    752     line_intf = &(LINE_INTF(pc));
    753     sys_intf = &(SYS_INTF(pc));
    754 
    755 	/*
    756 	 * system side interface was specified so make sure it's compatible with
    757 	 * line side speed. If not, overwrite with default compatible interface
    758 	 */
    759     if (line_intf->speed == PHY82328_SPD_40G) {
    760         sys_intf->speed = PHY82328_SPD_40G;
    761         line_intf->type = SOC_PORT_IF_SR4;
    762         if (!(_phy_82328_intf_is_single_port(sys_intf->type))) {
    763             /* system side interface is not compatible so overwrite with default */
    764             LOG_ERROR(BSL_LS_SOC_PHY,
    765                       (BSL_META_U(unit,
    766                                   "PHY82328 incompatible 40G system side interface, "
    767                                   "using default: u=%d p=%d\n"), unit, port));
    768             sys_intf->type = SOC_PORT_IF_XLAUI;
    769         }
    770     }
    771     else { /* 10G/1G */
    772         if (_phy_82328_intf_is_quad_port(sys_intf->type)) {
    773             if (sys_intf->type == SOC_PORT_IF_KX) {
    774                 line_intf->speed = PHY82328_SPD_1G;
    775                 line_intf->type = SOC_PORT_IF_GMII;
    776                 sys_intf->speed = PHY82328_SPD_1G;
    777 			} else {
    778                 /* 10G system side so fix line side to be 10G compatible */
    779                 line_intf->speed = PHY82328_SPD_10G;
    780                 line_intf->type = SOC_PORT_IF_SR;
    781                 sys_intf->speed = PHY82328_SPD_10G;
    782             }
    783         } else {
    784             /* system side interface is not compatible so overwrite with default */
    785             LOG_ERROR(BSL_LS_SOC_PHY,
    786                       (BSL_META_U(unit,
    787                                   "PHY82328 incompatible 10G/1G system side interface, "
    788                                   "using default: u=%d p=%d\n"), unit, port));
    789             /* default to 10G interface/speed on both sides */
    790             line_intf->speed = PHY82328_SPD_10G;
    791             line_intf->type = SOC_PORT_IF_SR;
    792             sys_intf->speed = PHY82328_SPD_10G;
    793             sys_intf->type =  SOC_PORT_IF_XFI;
    794         }
    795     }
    796     return SOC_E_NONE;
    797 }
    798 
    799 STATIC int32
    800 _phy_82328_config_update(int32 unit, soc_port_t port)
    801 {
    802     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
    803     
    804     /* Change polarity got from config */
    805     return _phy_82328_polarity_flip(unit, port, POL_TX_CFG(pc), POL_RX_CFG(pc));
    806 }
    807 
    808 #ifdef BCM_WARM_BOOT_SUPPORT
    809 
    810 STATIC int32
    811 _phy_82328_intf_speed_from_reg(uint16 mode, int32 *speed)
    812 {
    813     uint16 speed_reg = mode & (MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_MASK |
    814                                MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_MASK |
    815                                MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_MASK |
    816                                MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_100G_MASK );
    817     *speed = 0;
    818     switch (speed_reg) {
    819 
    820     case PHY82328_GP_REG_1_SPD_42G:
    821         *speed = PHY82328_SPD_42G;
    822         break;
    823 
    824     case PHY82328_GP_REG_1_SPD_40G:
    825         *speed = PHY82328_SPD_40G;
    826         break;
    827 
    828     case PHY82328_GP_REG_1_SPD_10G:
    829         *speed = PHY82328_SPD_10G;
    830         break;
    831     case PHY82328_GP_REG_1_SPD_1G: 
    832         /********* 100, 10 not recoverable from PHY ********/
    833         *speed = PHY82328_SPD_1G;
    834         break;
    835 
    836     default:
    837         /* hardware has unexpected value */
    838         return SOC_E_FAIL;
    839     }
    840 
    841     return SOC_E_NONE;
    842 }
    843 
    844 STATIC int32
    845 _phy_82328_intf_type_from_reg(uint16 mode, phy82328_intf_side_t side, int32 speed, int32 an,
    846                               soc_port_if_t *intf_type) 
    847 {
    848     uint16 intf_reg = mode & ((side == PHY82328_INTF_SIDE_LINE) ? 0x5300 : 0xac00);
    849 
    850     if (side == PHY82328_INTF_SIDE_LINE) {
    851         if (intf_reg == 0) {
    852             if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) {
    853                 *intf_type = SOC_PORT_IF_SR4;
    854             } else if (speed == PHY82328_SPD_10G) {
    855                 *intf_type = SOC_PORT_IF_SR;
    856             } else if (speed == PHY82328_SPD_1G) {
    857                 if (an) {
    858                     *intf_type = SOC_PORT_IF_GMII;
    859                 } else {
    860                     *intf_type = SOC_PORT_IF_SGMII;
    861                 }
    862             } else if (speed == 100 || speed == 10) {
    863                 *intf_type = SOC_PORT_IF_SGMII;
    864             } 
    865             else {
    866                 return SOC_E_FAIL;
    867             }
    868         } else if (intf_reg == 0x4200) {
    869             if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) {
    870                 *intf_type = SOC_PORT_IF_XLAUI;
    871             } else if (speed == PHY82328_SPD_10G) {
    872                 *intf_type = SOC_PORT_IF_SFI;
    873             } else {
    874                 return SOC_E_FAIL;
    875             }
    876         } else if (intf_reg == 0x4000) {
    877             if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) {
    878                 *intf_type = SOC_PORT_IF_LR4;
    879             } else if (speed == PHY82328_SPD_10G) {
    880                 *intf_type = SOC_PORT_IF_LR;
    881             } else {
    882                 return SOC_E_FAIL;
    883             }
    884         } else if (intf_reg == 0x200 || intf_reg == 0x1200) {
    885             if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) {
    886                 *intf_type = SOC_PORT_IF_CR4;
    887             } else if (speed == PHY82328_SPD_10G) {
    888                 *intf_type = SOC_PORT_IF_CR;
    889             }
    890             else {
    891                 return SOC_E_FAIL;
    892             }
    893         } else if (intf_reg == 0x100) {
    894             if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) {
    895                 *intf_type = SOC_PORT_IF_KR4;
    896             } else if (speed == PHY82328_SPD_10G) {
    897                 *intf_type = SOC_PORT_IF_KR;
    898             } else if (speed == PHY82328_SPD_1G || speed == 100 || speed == 10) {
    899                 *intf_type = SOC_PORT_IF_KX;
    900             }
    901             else {
    902                 return SOC_E_FAIL;
    903             }
    904         } else if (intf_reg == 0x5000) {
    905             if (speed == PHY82328_SPD_10G) {
    906                 *intf_type = SOC_PORT_IF_ZR;
    907             } else {
    908                 return SOC_E_FAIL;
    909             }
    910         } else {
    911             return SOC_E_FAIL;
    912         } /*  if (intf_reg) */
    913     } else {
    914         if (intf_reg == 0) {
    915             if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) {
    916                 *intf_type = SOC_PORT_IF_SR4;
    917             } else if (speed == PHY82328_SPD_10G) {
    918                 *intf_type = SOC_PORT_IF_SR;
    919             } else if (speed == PHY82328_SPD_1G) {
    920                 if (an) {
    921                     *intf_type = SOC_PORT_IF_GMII;
    922                 } else {
    923                     *intf_type = SOC_PORT_IF_SGMII;
    924                 }
    925             } else if (speed == 100 || speed == 10) {
    926                 *intf_type = SOC_PORT_IF_SGMII;
    927             }
    928             else {
    929                 return SOC_E_FAIL;
    930             }
    931         } else if (intf_reg == 0x8800) {
    932             if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) {
    933                 *intf_type = SOC_PORT_IF_XLAUI;
    934             } else if (speed == PHY82328_SPD_10G) {
    935                 *intf_type = SOC_PORT_IF_XFI;
    936             } 
    937             else {
    938                 return SOC_E_FAIL;
    939             }
    940         } else if (intf_reg == 0x800 || intf_reg == 0x2800) {
    941             if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) {
    942                 *intf_type = SOC_PORT_IF_CR4;
    943             } else if (speed == PHY82328_SPD_10G) {
    944                 *intf_type = SOC_PORT_IF_CR;
    945             }
    946             else {
    947                 return SOC_E_FAIL;
    948             }
    949         } else if (intf_reg == 0x400) {
    950             if (speed == PHY82328_SPD_40G || speed == PHY82328_SPD_42G) {
    951                 *intf_type = SOC_PORT_IF_KR4;
    952             } else if (speed == PHY82328_SPD_10G) {
    953                 *intf_type = SOC_PORT_IF_KR;
    954             } else if (speed == PHY82328_SPD_1G || speed == 10 || speed == 100) {
    955                 *intf_type = SOC_PORT_IF_KX;
    956             } 
    957             else {
    958                 return SOC_E_FAIL;
    959             }
    960         } else {
    961            return SOC_E_FAIL;
    962         }
    963     } 
    964     return SOC_E_NONE;
    965 }
    966 
    967 STATIC int32
    968 _phy_82328_reinit_line_intf(int32 unit, soc_port_t port, int32 speed, int32 an, uint16 mode)
    969 {
    970     phy_ctrl_t  *pc;
    971     phy82328_intf_cfg_t *line_intf;
    972     
    973     pc = EXT_PHY_SW_STATE(unit, port);
    974     line_intf = &(LINE_INTF(pc));
    975 
    976     line_intf->speed = speed;
    977     SOC_IF_ERROR_RETURN(_phy_82328_intf_type_from_reg(mode, PHY82328_INTF_SIDE_LINE, speed, an, &(line_intf->type)));
    978 
    979     return SOC_E_NONE;
    980 }
    981 
    982 STATIC int32
    983 _phy_82328_reinit_system_intf(int32 unit, soc_port_t port, int32 speed, int32 an, uint16 mode)
    984 {
    985     phy_ctrl_t  *pc;
    986     phy82328_intf_cfg_t *system_intf;
    987     
    988     pc = EXT_PHY_SW_STATE(unit, port);
    989     system_intf = &(SYS_INTF(pc));
    990 
    991     system_intf->speed = speed;
    992     SOC_IF_ERROR_RETURN(_phy_82328_intf_type_from_reg(mode, PHY82328_INTF_SIDE_SYS, speed, an, &(system_intf->type)));
    993 
    994     return SOC_E_NONE;
    995 }
    996 
    997 STATIC int32
    998 _phy_82328_reinit_cur_datapath(int32 unit, soc_port_t port, uint16 mode)
    999 {
   1000     uint16 datapath_reg;
   1001     phy_ctrl_t  *pc;
   1002 
   1003     pc = EXT_PHY_SW_STATE(unit, port);
   1004     
   1005     datapath_reg = mode & (MGT_TOP_PMD_USR_GP_REGISTER_1_ENABLE_ULTRA_LOW_LATENCY_DATAPATH_MASK |
   1006                            MGT_TOP_PMD_USR_GP_REGISTER_1_ULL_DATAPATH_LATENCY_MASK);
   1007 
   1008     if (datapath_reg == 0) {
   1009         CUR_DATAPATH(pc) = PHY82328_DATAPATH_20;
   1010     } else if (datapath_reg == PHY82328_4BIT_DP_DEPTH1) {
   1011         CUR_DATAPATH(pc) = PHY82328_DATAPATH_4_DEPTH_1;
   1012     } else if ( datapath_reg == PHY82328_4BIT_DP_DEPTH2) {
   1013         CUR_DATAPATH(pc) = PHY82328_DATAPATH_4_DEPTH_2;
   1014     } else {
   1015         return SOC_E_FAIL;
   1016     }
   1017     return SOC_E_NONE;
   1018 }
   1019 
   1020 STATIC int32
   1021 _phy_82328_reinit_from_mode(int32 unit, soc_port_t port)
   1022 {
   1023     uint16 mode_reg = 0, side_reg, an_reg;
   1024     int32 speed = 0, an =0, an_done = 0;
   1025     phy_ctrl_t  *pc, *int_pc;
   1026 
   1027     pc = EXT_PHY_SW_STATE(unit, port);
   1028     int_pc = INT_PHY_SW_STATE(unit, port);
   1029 
   1030     if (int_pc == NULL) {
   1031         return SOC_E_UNAVAIL;
   1032     }
   1033     /* 
   1034      * Make sure line side registers are selected
   1035      * if not, have to bail out since the system is in a bad state
   1036      */
   1037     SOC_IF_ERROR_RETURN(
   1038         READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, &side_reg));
   1039     if (side_reg != 0) {
   1040         return SOC_E_UNAVAIL;
   1041     }
   1042 
   1043     /* Read the current mode */
   1044     SOC_IF_ERROR_RETURN(
   1045         READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_3, &mode_reg));
   1046 
   1047     /* Get speed */
   1048     SOC_IF_ERROR_RETURN(_phy_82328_intf_speed_from_reg(mode_reg, &speed));
   1049 
   1050     /* Get an setting */
   1051     if (speed < PHY82328_SPD_10G ) {
   1052         SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &an, &an_done));
   1053         SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &speed));
   1054     } else {
   1055         SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_AN_REG(unit, pc,
   1056                                                      PHY82328_AN_CTRL_REG, &an_reg));
   1057         an = ((an_reg & PHY82328_AN_ENABLE_MSK) == PHY82328_AN_ENABLE_MSK);
   1058     }
   1059     
   1060     AN_EN(pc) = an;
   1061 #if 1
   1062     SOC_IF_ERROR_RETURN(
   1063         _phy_82328_reinit_line_intf(unit, port, speed, an, mode_reg));
   1064     SOC_IF_ERROR_RETURN(
   1065         _phy_82328_reinit_system_intf(unit, port, speed, an, mode_reg));
   1066 #endif
   1067     SOC_IF_ERROR_RETURN(
   1068         _phy_82328_reinit_cur_datapath(unit, port, mode_reg));
   1069 
   1070     return SOC_E_NONE;
   1071 }
   1072 
   1073 STATIC int32
   1074 _phy_82328_reinit_fw_rx_los(int32 unit, soc_port_t port)
   1075 {
   1076     uint16 data16 = 0;
   1077     phy_ctrl_t  *pc;
   1078 
   1079     pc = EXT_PHY_SW_STATE(unit, port);
   1080 
   1081     SOC_IF_ERROR_RETURN(
   1082         READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, SIGDET_SIGDET_CTRL_1, &data16));
   1083 
   1084     FW_RX_LOS(pc) = (data16 & SIGDET_SIGDET_CTRL_1_SIGNAL_DETECT_FRC_MASK) >>
   1085                       SIGDET_SIGDET_CTRL_1_SIGNAL_DETECT_FRC_SHIFT;
   1086 
   1087     return SOC_E_NONE;
   1088 }
   1089 
   1090 STATIC int32
   1091 _phy_82328_reinit(int32 unit, soc_port_t port)
   1092 {
   1093 	SOC_IF_ERROR_RETURN(
   1094             _phy_82328_reinit_from_mode(unit , port));
   1095 
   1096     /* Reinit fw_rx_los */
   1097     SOC_IF_ERROR_RETURN(
   1098         _phy_82328_reinit_fw_rx_los(unit, port));
   1099 
   1100     return SOC_E_NONE;
   1101 }
   1102 
   1103 #endif /*  BCM_WARM_BOOT_SUPPORT */
   1104 
   1105 STATIC int32
   1106 _phy_82328_init_pass2(int32 unit, soc_port_t port)
   1107 {
   1108     phy_ctrl_t *pc;
   1109     phy82328_intf_cfg_t *line_intf, *sys_intf;
   1110     phy82328_micro_ctrl_t *micro_ctrl;
   1111     uint16 if_sys_idx = 0;
   1112     uint16 chan_data = 0, chan_mask = 0;
   1113 
   1114     LOG_INFO(BSL_LS_SOC_PHY,
   1115              (BSL_META_U(unit,
   1116                          "PHY82328 init pass2: u=%d p=%d\n"), unit, port));
   1117     pc = EXT_PHY_SW_STATE(unit, port);
   1118 	/*
   1119 	 * - interfaces are KR4/KR/KX/XAUI/XFI/SR/LR/CR/SR4/LR4/CR4
   1120 	 * - Gallardo is capable of being configured symmetrically and can support all 
   1121 	 *   interfaces on both sides
   1122 	 * - system side interfaces cannot be changed dynamically
   1123 	 *   - configured in Gallardo via config variables
   1124 	 * - line side mode can be changed dynamically
   1125 	 *   - configured specifically with interface set and/or by matching speed
   1126 	 *   - automatically when module autodetect is enabled
   1127 	 *
   1128 	 *    port mode            system side                   line side
   1129 	 * ----------------  ------------------------  --------------------------------
   1130 	 * 40G(singleport)   dflt:XLAUI or configvar   dflt:XLAUI  or user set if/speed
   1131 	 * 1G/10G(quadport)  dflt:XFI or configvar     dflt:SFI    or user set if/speed
   1132 	 */
   1133 	
   1134     line_intf = &(LINE_INTF(pc));
   1135     sys_intf  = &(SYS_INTF(pc));
   1136     micro_ctrl = &(MICRO_CTRL(pc));
   1137 
   1138     sal_memset(line_intf, 0, sizeof(phy82328_intf_cfg_t));
   1139     sal_memset(sys_intf,  0, sizeof(phy82328_intf_cfg_t));
   1140     sal_memset(micro_ctrl,  0, sizeof(phy82328_micro_ctrl_t));
   1141 
   1142     AN_EN(pc) = 0;
   1143     SYNC_INIT(pc) = 1;
   1144     FW_RX_LOS(pc) = 0;
   1145     LOGICAL_LANE0(pc) = 0;
   1146     micro_ctrl->enable = 1;
   1147     micro_ctrl->count = 0;
   1148 
   1149     SYS_FORCED_CL72(pc) = soc_property_port_get(unit, port, spn_PORT_INIT_CL72, 0);
   1150     pc->flags |= PHYCTRL_INIT_DONE;
   1151 	/* Get configured system interface */
   1152     if_sys_idx = soc_property_port_get(unit, port, spn_PHY_SYS_INTERFACE, 0);
   1153     if (if_sys_idx >= (sizeof(phy82328_sys_to_port_if) / sizeof(soc_port_if_t))) {
   1154         LOG_ERROR(BSL_LS_SOC_PHY,
   1155                   (BSL_META_U(unit,
   1156                               "PHY82328 invalid system side interface: u=%d p=%d intf=%d\n"
   1157                               "Using default interface\n"),
   1158                    unit, port, if_sys_idx));
   1159         if_sys_idx = 0;
   1160 	}
   1161     sys_intf->type = phy82328_sys_to_port_if[if_sys_idx];
   1162     if (PHY82328_SINGLE_PORT_MODE(pc)) {
   1163         line_intf->speed = PHY82328_SPD_40G;
   1164     }
   1165     else {
   1166         line_intf->speed = PHY82328_SPD_10G;
   1167     }
   1168     if (sys_intf->type == 0) {
   1169 		/* use defaults based on current line side */
   1170         sys_intf->speed = line_intf->speed;
   1171         if ( line_intf->speed == PHY82328_SPD_40G) {
   1172             line_intf->type = SOC_PORT_IF_SR4;
   1173             sys_intf->type = SOC_PORT_IF_XLAUI;
   1174         }
   1175         else {
   1176             line_intf->type = SOC_PORT_IF_SR;
   1177             sys_intf->type = SOC_PORT_IF_XFI;
   1178         }
   1179         LOG_INFO(BSL_LS_SOC_PHY,
   1180                  (BSL_META_U(unit,
   1181                              "default sys and line intf are used\n")));
   1182     } else {
   1183         SOC_IF_ERROR_RETURN(_phy_82328_intf_line_sys_params_get(unit, port));
   1184         LOG_CLI((BSL_META_U(unit,
   1185                             "After updating intf based on sys config\n")));
   1186         LOG_CLI((BSL_META_U(unit,
   1187                             "SYS Intf:%s speed:%d\n"),
   1188                  phy82328_intf_names[sys_intf->type],sys_intf->speed));
   1189         LOG_CLI((BSL_META_U(unit,
   1190                             "Line intf:%s speed:%d\n"),
   1191                  phy82328_intf_names[line_intf->type],line_intf->speed));
   1192     }
   1193     CFG_SYS_INTF(pc) = sys_intf->type;
   1194     CFG_DATAPATH(pc) = soc_property_port_get(unit, port, "82328_DATAPATH", PHY82328_DATAPATH_20);
   1195     CUR_DATAPATH(pc) = CFG_DATAPATH(pc);
   1196 	
   1197     /* Polarity configuration is applied every time interface is configured */
   1198     POL_TX_CFG(pc) = soc_property_port_get(unit, port, spn_PHY_TX_POLARITY_FLIP, PHY82328_POL_DND);
   1199     POL_RX_CFG(pc) = soc_property_port_get(unit, port, spn_PHY_RX_POLARITY_FLIP, PHY82328_POL_DND);
   1200 
   1201     PHY_82328_MICRO_PAUSE(unit, port, "polarity config in Init");
   1202 
   1203     /* Push configuration to the device */
   1204     SOC_IF_ERROR_RETURN(_phy_82328_config_update(unit, port));
   1205     
   1206     PHY_82328_MICRO_RESUME(unit, port);
   1207     /* Manually power down channel*/
   1208     chan_data = (1 << MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_MAN_TXON_EN_SHIFT) |
   1209         (1 << MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_TXOFFT_SHIFT);
   1210     chan_mask = MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_MAN_TXON_EN_MASK |
   1211         MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_TXOFFT_MASK;
   1212 
   1213     SOC_IF_ERROR_RETURN(
   1214         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_OPTICAL_CONFIGURATION,
   1215                                        chan_data, chan_mask));
   1216 #ifdef BCM_WARM_BOOT_SUPPORT
   1217     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){
   1218         /* Do nothing */
   1219     } else 
   1220 #endif
   1221     {
   1222         /* Initialize system and line side interfaces */
   1223         SOC_IF_ERROR_RETURN(_phy_82328_intf_line_sys_init(unit, port));
   1224     }
   1225 
   1226 #ifdef BCM_WARM_BOOT_SUPPORT
   1227     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){
   1228         return _phy_82328_reinit(unit, port);
   1229     }
   1230 #endif
   1231     if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) {
   1232         /* indicate third  pass of init is needed */
   1233         PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS3);
   1234     }
   1235     return SOC_E_NONE;
   1236 }
   1237 
   1238 STATIC int
   1239 _phy_82328_init_pass3(int unit, soc_port_t port)
   1240 {
   1241     int rv;
   1242     phy_ctrl_t  *pc, *int_pc;
   1243 
   1244     LOG_INFO(BSL_LS_SOC_PHY,
   1245              (BSL_META_U(unit,
   1246                          "PHY82328 init pass3: u=%d p=%d\n"), unit, port));
   1247     pc = EXT_PHY_SW_STATE(unit, port);
   1248     int_pc = INT_PHY_SW_STATE(unit, port);
   1249 
   1250     /* Complete  what we started from PASS2 in PASS3 */
   1251     if (INT_PHY_RE_EN(pc)) {
   1252         /* wait for timer to expire */
   1253         while (!soc_timeout_check(&SYNC_TO(pc))) {
   1254             sal_usleep(100);
   1255         }
   1256 
   1257         /* Turn internal PHY back on now that the mode has been configured */
   1258         SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 1));
   1259         INT_PHY_RE_EN(pc) = 0;
   1260     }
   1261 	/* Logical lane0 used for auto-negotiation in 40G CR4 */
   1262 	if (PHY82328_SINGLE_PORT_MODE(pc)) {
   1263 		uint16 logical_lane0;
   1264 		
   1265 		logical_lane0 = soc_property_port_get(unit, port, spn_PHY_LANE0_L2P_MAP, 0);
   1266 		if (logical_lane0 > PHY82328_NUM_LANES) {
   1267             LOG_ERROR(BSL_LS_SOC_PHY,
   1268                       (BSL_META_U(unit,
   1269                                   "PHY82328 bad auto-negotiation lane %d: u=%d p=%d"
   1270                                   " lane must be 0..3\n"), (int)logical_lane0, unit, port));
   1271 		} else {
   1272 			SOC_IF_ERROR_RETURN(
   1273 				MODIFY_PHY82328_MMF_PMA_PMD_REG(
   1274 					unit, pc, MGT_TOP_SINGLE_PMD_CTRL, 
   1275 					logical_lane0 << MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT, 
   1276 					MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_MASK));
   1277 			LOGICAL_LANE0(pc) = logical_lane0;
   1278 		}
   1279 	}
   1280 	
   1281 	/* If configured, enable module auto detection */
   1282 	MOD_AUTO_DETECT(pc) = soc_property_port_get(unit, port, spn_PHY_MOD_AUTO_DETECT, 0);
   1283 	if (MOD_AUTO_DETECT(pc)) {
   1284 		uint16 data, mask;
   1285 		
   1286         LOG_INFO(BSL_LS_SOC_PHY,
   1287                  (BSL_META_U(unit,
   1288                              "PHY82328 module auto detect enabled: u=%d p=%d\n"),
   1289                   unit, port));
   1290 
   1291         /* Enables both SFP and QSFP module detect */
   1292  		data = (MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_QSFP_MOD_DETECT_MASK |
   1293                 MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK);
   1294 		mask = (MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_QSFP_MOD_DETECT_MASK |
   1295                 MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK);
   1296 		
   1297 		rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, data, mask);
   1298 		if (SOC_FAILURE(rv)) {
   1299 			MOD_AUTO_DETECT(pc) = 0;
   1300 			LOG_ERROR(BSL_LS_SOC_PHY,
   1301                                   (BSL_META_U(unit,
   1302                                               "PHY82328 setting module auto detect failed: u=%d p%d\n"),
   1303                                    unit, port));
   1304 		} 
   1305 	}
   1306 #ifdef BCM_WARM_BOOT_SUPPORT
   1307     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){
   1308         return _phy_82328_reinit(unit, port);
   1309     }
   1310 #endif
   1311 
   1312     /* Cold boot code only below this  */
   1313 	return SOC_E_NONE;
   1314 }
   1315 
   1316 /*
   1317  * Check if the core has been initialized. This is done by
   1318  * looking at all ports which belong to the same core and see
   1319  * if any one of them have completed initialization.
   1320  * The primary port is used to determine whether the port is
   1321  * on the same core as all ports in a core share the primary port.
   1322  */
   1323 STATIC int32
   1324 _phy_82328_core_init_done(int32 unit, struct phy_driver_s *pd, int32 primary_port)
   1325 {
   1326     int32 rv;
   1327     soc_port_t port;
   1328     phy_ctrl_t *pc;
   1329     uint32 core_primary_port;
   1330 
   1331     PBMP_ALL_ITER(unit, port) {
   1332         pc = EXT_PHY_SW_STATE(unit, port);
   1333         if (pc == NULL) {
   1334             continue;
   1335         }
   1336         /* Make sure this port has a 82328 driver */
   1337         if (pc->pd != pd) {
   1338             continue;
   1339         }
   1340         rv = phy_82328_control_get(unit, port, SOC_PHY_CONTROL_PORT_PRIMARY,
   1341                                    &core_primary_port);
   1342         if (rv != SOC_E_NONE) {
   1343             continue;
   1344         }
   1345         if ((primary_port == core_primary_port) && (pc->flags & PHYCTRL_INIT_DONE)) {
   1346             return TRUE;
   1347 		}
   1348 	}
   1349     return FALSE;
   1350 }
   1351 
   1352 
   1353 STATIC int32
   1354 _phy_82328_init_pass1(int32 unit, soc_port_t port)
   1355 {
   1356     phy_ctrl_t			*pc;
   1357     int32               offset;
   1358     soc_port_t			primary_port;
   1359     uint16              chip_rev;
   1360 		
   1361     pc = EXT_PHY_SW_STATE(unit, port);
   1362 	
   1363     LOG_INFO(BSL_LS_SOC_PHY,
   1364              (BSL_META_U(unit,
   1365                          "PHY82328 init pass1: u=%d p=%d\n"), unit, port));
   1366 
   1367     SOC_IF_ERROR_RETURN(
   1368         READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   1369                                       MGT_TOP_CHIP_REV_REGISTER,
   1370 				      &chip_rev));
   1371     DEVREV(pc) = chip_rev;
   1372     /* Set the primary port & offset */
   1373     if (soc_phy_primary_and_offset_get(unit, port, &primary_port, &offset) != SOC_E_NONE) {
   1374 		/* 
   1375 		 * Derive primary and offset 
   1376 		 * There is an assumption lane 0 on first core on the the MDIO
   1377 		 * bus is a primary port
   1378 		 */
   1379         if (PHY82328_SINGLE_PORT_MODE(pc)) {
   1380             primary_port = port;
   1381             offset = 0;
   1382         } else {
   1383             /*primary_port = port - (pc->phy_id & 0x3);*/
   1384             if ((port-1) == 0) {
   1385                 primary_port = (((port)/4) * 4) + 1;
   1386             } else {
   1387                 primary_port = (((port -1)/4) * 4) + 1;
   1388             }
   1389             offset = pc->phy_id & 0x3;
   1390         }
   1391     }
   1392     /* set the default values that are valid for many boards */
   1393     SOC_IF_ERROR_RETURN(phy_82328_control_set(unit, port, SOC_PHY_CONTROL_PORT_PRIMARY,
   1394                                               primary_port));
   1395 	
   1396     SOC_IF_ERROR_RETURN(phy_82328_control_set(unit, port,SOC_PHY_CONTROL_PORT_OFFSET,
   1397                                               offset));
   1398 
   1399     /*
   1400      * Since there is a single micro and therefore a single copy of the firmware
   1401      * shared among the 4 channels in a core, do not download firmware if in quad
   1402      * channel and the other channels are active.
   1403      */
   1404      if (PHY82328_SINGLE_PORT_MODE(pc) ||
   1405         (!PHY82328_SINGLE_PORT_MODE(pc) && 
   1406         (!_phy_82328_core_init_done(unit, pc->pd, primary_port)))) {
   1407          uint16 sts_reg = 0;
   1408          SOC_IF_ERROR_RETURN
   1409             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 
   1410                      MGT_TOP_SPA_CONTROL_STATUS_REGISTER, &sts_reg));
   1411 
   1412          if ((sts_reg & (1 << 13)) && 
   1413              !(soc_property_port_get(unit, port,
   1414                      spn_PHY_FORCE_FIRMWARE_LOAD, FALSE))) {
   1415              pc->flags &= (~PHYCTRL_MDIO_BCST);
   1416          } else {
   1417              LOG_INFO(BSL_LS_SOC_PHY,
   1418                       (BSL_META_U(unit,
   1419                                   "PHY82328 Bcast Enabled for Port:%d"), port));
   1420              pc->flags |= PHYCTRL_MDIO_BCST;
   1421 	     }
   1422     }
   1423 	
   1424 	/* indicate second pass of init is needed */
   1425     PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2);
   1426 
   1427     return SOC_E_NONE;
   1428 }
   1429 
   1430 STATIC int32
   1431 _phy_82328_chip_id_get(int32 unit, soc_port_t port, phy_ctrl_t *pc, uint32 *chip_id)
   1432 {
   1433 	int32 rv = SOC_E_NONE;
   1434 
   1435     uint16 chip_id_lsb = 0, chip_id_msb = 0, chip_id_misc = 0;
   1436 
   1437     *chip_id = 0;
   1438 
   1439     SOC_IF_ERROR_RETURN(
   1440             READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_CHIP_ID0_REGISTER, &chip_id_lsb));
   1441     SOC_IF_ERROR_RETURN(
   1442             READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_CHIP_ID1_REGISTER, &chip_id_msb));
   1443     SOC_IF_ERROR_RETURN(
   1444             READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_OTP_MISC_SIG4_REGISTER, &chip_id_misc));
   1445 
   1446     if (chip_id_msb == 0x8) {
   1447         if (chip_id_lsb == 0x2328) {
   1448             if (chip_id_misc & (1U << 12)) {
   1449                 *chip_id = PHY82328_ID_82328F;
   1450             } else {
   1451                 *chip_id = PHY82328_ID_82328;
   1452             }
   1453         } else if (chip_id_lsb == 0x2322) {
   1454             *chip_id = PHY82328_ID_82322;
   1455         } else if (chip_id_lsb == 0x232F) {
   1456             *chip_id = PHY82328_ID_82328F;
   1457         } else {
   1458             LOG_ERROR(BSL_LS_SOC_PHY,
   1459                       (BSL_META_U(unit,
   1460                                   "PHY82328  bad chip id: u=%d p=%d chipid %x%x\n"),
   1461                                   unit, port, chip_id_msb, chip_id_lsb));
   1462             rv = SOC_E_BADID;
   1463         }
   1464     }
   1465     return rv;
   1466 }
   1467 
   1468 STATIC int32
   1469 _phy_82328_config_devid(int32 unit,soc_port_t port, phy_ctrl_t *pc, uint32 *devid)
   1470 {
   1471     if (soc_property_port_get(unit, port, "phy_82328", FALSE)) {
   1472         return *devid = PHY82328_ID_82328;
   1473     } else if(soc_property_port_get(unit, port, "phy_82328f", FALSE)) {
   1474         return *devid = PHY82328_ID_82328F;
   1475     } else if(soc_property_port_get(unit, port, "phy_82322", FALSE)) {
   1476         return *devid = PHY82328_ID_82322;
   1477     }
   1478 
   1479     return _phy_82328_chip_id_get(unit, port, pc, devid);
   1480 }
   1481 
   1482 /* Function:
   1483  *    phy_82328_init
   1484  * Purpose:
   1485  *    Initialize 82328 phys
   1486  * Parameters:
   1487  *    unit - StrataSwitch unit #.
   1488  *    port - StrataSwitch port #.
   1489  * Returns:
   1490  *    SOC_E_NONE
   1491  */
   1492 
   1493 STATIC
   1494 int32 phy_82328_init(int32 unit, soc_port_t port)
   1495 {
   1496     int32					ix;
   1497     uint32				devid;
   1498     phy_ctrl_t			*pc;
   1499 
   1500     pc = EXT_PHY_SW_STATE(unit, port);
   1501 
   1502     LOG_INFO(BSL_LS_SOC_PHY,
   1503              (BSL_META_U(unit,
   1504                          "PHY82328 init: u=%d p=%d state=%d\n"), 
   1505                          unit, port,PHYCTRL_INIT_STATE(pc)));
   1506     SOC_IF_ERROR_RETURN(
   1507       phy82328_intf_side_reg_select (unit, port, PHY82328_INTF_SIDE_LINE));
   1508 
   1509     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) ||
   1510         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   1511 
   1512         /* Read the chip id to identify the device */
   1513         SOC_IF_ERROR_RETURN(_phy_82328_config_devid(unit, port, pc, &devid));
   1514 
   1515         /* Save it in the device description structure for future use */  
   1516         DEVID(pc) = devid;
   1517 
   1518         /* initialize default p2l map */
   1519         for (ix = 0; ix < PHY82328_NUM_LANES; ix++) {
   1520             P2L_MAP(pc,ix) = ix;
   1521         }
   1522         PHY_FLAGS_SET(unit, port,  PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER);
   1523         SOC_IF_ERROR_RETURN(_phy_82328_init_pass1(unit, port));
   1524 
   1525         if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) {
   1526             return SOC_E_NONE;
   1527         }
   1528     }
   1529 
   1530     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) ||
   1531         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   1532         SOC_IF_ERROR_RETURN (_phy_82328_init_pass2(unit, port));
   1533         if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) {
   1534             return SOC_E_NONE;
   1535         }
   1536     }
   1537 
   1538     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS3) ||
   1539         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   1540 
   1541         SOC_IF_ERROR_RETURN( _phy_82328_init_pass3(unit, port));
   1542 
   1543         LOG_INFO(BSL_LS_SOC_PHY,
   1544                  (BSL_META_U(unit,
   1545                              "PHY82328 init pass3 completed: u=%d p=%d\n"), unit, port));
   1546         PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_DEFAULT);
   1547         return SOC_E_NONE;
   1548     }
   1549 
   1550     return SOC_E_NONE;
   1551 }
   1552 
   1553 /* Return contents of ANARXSTATUS */
   1554 STATIC int32
   1555 _phy_82328_intf_link_get(int32 unit, soc_port_t port, int32 *link)
   1556 {
   1557     int32 lane=0, max_lane=0;
   1558     uint16 data16=0;
   1559     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   1560 
   1561         if (PHY82328_SINGLE_PORT_MODE(pc)) {
   1562             max_lane = PHY82328_NUM_LANES;
   1563         } 
   1564         else {
   1565            max_lane = 1;
   1566         }
   1567     for (lane = 0; lane < max_lane; lane++) {
   1568         if (PHY82328_SINGLE_PORT_MODE(pc)) {
   1569             /* Select the lane on the line side */
   1570             SOC_IF_ERROR_RETURN(
   1571                _phy_82328_channel_select(unit, port, PHY82328_INTF_SIDE_LINE, lane));
   1572         }
   1573         if (AN_EN(pc) == 1) { 
   1574             /*anaRxStatusSel 1.C0B1.[2:0] 0*/
   1575             SOC_IF_ERROR_RETURN(
   1576                 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, PHY82328_AN_STS_REG,
   1577                          &data16));
   1578             if (data16 & PHY82328_AN_STS_LINK_STS_MSK) {
   1579                 *link &=1;
   1580             } else {
   1581                 *link &=0;
   1582             }
   1583         } else {
   1584             /*anaRxStatusSel 1.C0B1.[2:0] 0*/
   1585             SOC_IF_ERROR_RETURN(
   1586                 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, RX_ANARXCONTROL,
   1587                          0x0, QSFI_RX_ANARXSTATUS_SM_SEL_MASK));
   1588             /*anaRxStatusSel 1.C0B0.12 1*/
   1589             SOC_IF_ERROR_RETURN(
   1590                 READ_PHY82328_MMF_PMA_PMD_REG (unit, pc, RX_ANARXSTATUS, &data16));
   1591         
   1592             /* Check if rxSeq Done in any lane */
   1593             if ((data16 & QSFI_RX_ANARXSTATUS_PMD_RX_PMD_LOCK_MASK) ==
   1594                  QSFI_RX_ANARXSTATUS_PMD_RX_PMD_LOCK_MASK) {
   1595                 *link &= 1;
   1596             } else {
   1597                 *link = 0;
   1598             }
   1599             LOG_VERBOSE(BSL_LS_SOC_PHY,
   1600                         (BSL_META_U(unit,
   1601                                     "PhyID:%x link:%d"),
   1602                          pc->phy_id,*link));
   1603         }
   1604 #if 0
   1605         if (LINE_INTF(pc).speed == 10000) {
   1606             LOG_CLI((BSL_META_U(unit,
   1607                                 "Speed 10G: link:%d\n"), *link));
   1608             break;
   1609         }
   1610 #endif
   1611     }
   1612         LOG_VERBOSE(BSL_LS_SOC_PHY,
   1613                     (BSL_META_U(unit,
   1614                                 "-->After MOD PhyID:%x\n"),
   1615                      pc->phy_id));
   1616  
   1617     /* Restore to default single port register access */
   1618     if (PHY82328_SINGLE_PORT_MODE(pc)) {
   1619         SOC_IF_ERROR_RETURN
   1620             (_phy_82328_channel_select(unit, port, PHY82328_INTF_SIDE_LINE,
   1621 											  PHY82328_ALL_LANES));
   1622     }
   1623     return SOC_E_NONE;
   1624 }
   1625 
   1626 STATIC int
   1627 _phy_82328_mod_auto_detect_speed_check(int unit, soc_port_t port, uint16 csr)
   1628 {
   1629 	uint16 csr_speed;
   1630 	phy_ctrl_t *pc;
   1631 	phy82328_intf_cfg_t *line_intf;
   1632 	static int speed_tbl[] = {	0, 1000, 10000, 0, 40000, 0, 0 ,0, 10000 };
   1633 
   1634 	pc = EXT_PHY_SW_STATE(unit, port);
   1635 	line_intf = &(LINE_INTF(pc));
   1636 
   1637 	csr_speed = csr & (MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_100G_MASK | 
   1638 					   MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_MASK |
   1639 					   MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_MASK |
   1640 					   MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_MASK);
   1641 	if (line_intf->speed != speed_tbl[csr_speed]) {
   1642 		LOG_ERROR(BSL_LS_SOC_PHY,
   1643                           (BSL_META_U(unit,
   1644                                       "82328 module auto detection unexpected: u=%d p=%d speed=0x%x\n"),
   1645                            unit, port, speed_tbl[csr_speed]));
   1646 	}
   1647 	return (line_intf->speed == speed_tbl[csr_speed]);
   1648 }
   1649 
   1650 STATIC int
   1651 _phy_82328_mod_auto_detect_intf_process(int unit, soc_port_t port, uint16 csr)
   1652 {
   1653 	int copper_mod = 0;
   1654 	int lr_mod = 0;
   1655 	phy_ctrl_t *pc;
   1656 	phy82328_intf_cfg_t *line_intf;
   1657 	int intf_update = 1;
   1658 
   1659 	pc = EXT_PHY_SW_STATE(unit, port);
   1660 	line_intf = &(LINE_INTF(pc));
   1661 
   1662 	copper_mod = (csr & MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_MASK) ==
   1663 		MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_MASK;
   1664 
   1665 	lr_mod = (csr & MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_LR_MODE_MASK) ==
   1666 		MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_LR_MODE_MASK;
   1667 
   1668 	/* Change interface if going from optical to copper */ 
   1669 	if (copper_mod) {
   1670 		switch (line_intf->type) {
   1671 		case SOC_PORT_IF_SR:
   1672 		case SOC_PORT_IF_SFI:
   1673 		case SOC_PORT_IF_XFI:
   1674 			line_intf->type = SOC_PORT_IF_CR;
   1675 			break;
   1676 		case SOC_PORT_IF_SR4:
   1677 		case SOC_PORT_IF_XLAUI:
   1678 			line_intf->type = SOC_PORT_IF_CR4;
   1679 			break;
   1680 		default:
   1681 			/* No interface change if not currently an optical interface */
   1682 			intf_update = 0;
   1683 			break;
   1684 		}
   1685 	} else {
   1686 		/* Change interface if going from optical SR to LR */
   1687 		if (lr_mod) {
   1688 			switch (line_intf->type) {
   1689 			case SOC_PORT_IF_SR:
   1690 			case SOC_PORT_IF_SFI:
   1691 			case SOC_PORT_IF_XFI:
   1692 				line_intf->type = SOC_PORT_IF_LR;
   1693 				break;
   1694 			case SOC_PORT_IF_SR4:
   1695 			case SOC_PORT_IF_XLAUI:
   1696 				line_intf->type = SOC_PORT_IF_LR4;
   1697 				break;
   1698 			default:
   1699 				/* No interface change */
   1700 				intf_update = 0;
   1701 				break;
   1702 			}
   1703 		}
   1704 		/* Change interface if going from copper to optical */
   1705 		switch (line_intf->type) {
   1706 		case SOC_PORT_IF_CR:
   1707 			line_intf->type = lr_mod ? SOC_PORT_IF_LR : SOC_PORT_IF_SR;
   1708 			break;
   1709 		case SOC_PORT_IF_CR4:
   1710 			line_intf->type = lr_mod ? SOC_PORT_IF_LR4 : SOC_PORT_IF_SR4;
   1711 			break;
   1712 		default:
   1713 			intf_update = 0;
   1714 			break;
   1715 		}
   1716 	}
   1717 	if (intf_update) {
   1718 		SOC_IF_ERROR_RETURN(_phy_82328_intf_line_sys_update(unit, port));
   1719 	}
   1720 	return SOC_E_NONE;
   1721 }
   1722 
   1723 STATIC int
   1724 _phy_82328_mod_auto_detect_process(int unit, soc_port_t port, uint16 csr) 
   1725 {
   1726 
   1727 	LOG_ERROR(BSL_LS_SOC_PHY,
   1728                   (BSL_META_U(unit,
   1729                               "PHY82328 module detected: u=%d p=%d csr=%x\n"), 
   1730                    unit, port, csr));
   1731 
   1732 	/*
   1733 	 *  Speed cannot change with module detection so it must match the
   1734 	 *  currently configured speed
   1735 	 */
   1736 	if (!_phy_82328_mod_auto_detect_speed_check(unit, port, csr)) {
   1737 		return SOC_E_FAIL;
   1738 	}
   1739 		
   1740 	/*
   1741 	 * Get the line side interface based on the current interface and the 
   1742 	 * detected module
   1743 	 */
   1744 	SOC_IF_ERROR_RETURN(_phy_82328_mod_auto_detect_intf_process(unit, port, csr));
   1745 
   1746 	return SOC_E_NONE;
   1747 }
   1748 
   1749 STATIC int 
   1750 _phy_82328_mod_auto_detect_update(int unit, soc_port_t port) 
   1751 {
   1752 	phy_ctrl_t *pc;
   1753 	uint16 ucode_csr;
   1754 	uint16 drv_csr;
   1755 
   1756     pc = EXT_PHY_SW_STATE(unit, port);
   1757 
   1758 	/* 
   1759 	 * New module insertion when 1.c843[4] == 1 and 1.c841[4] == 0
   1760 	 */ 
   1761     SOC_IF_ERROR_RETURN
   1762         (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_3, &ucode_csr));
   1763     if (ucode_csr & MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK) {
   1764         SOC_IF_ERROR_RETURN
   1765             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, &drv_csr));
   1766         if (!(drv_csr & MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK)) {
   1767             SOC_IF_ERROR_RETURN(_phy_82328_mod_auto_detect_process(unit, port, ucode_csr));
   1768 			
   1769             /* 
   1770              * Ack firmware that the module insertion has been updated 
   1771              * 1.c841[4] = 1, 1.c841[7] = 0
   1772              */
   1773 			SOC_IF_ERROR_RETURN
   1774 				(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, 
   1775 												 MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK,
   1776 												 MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK |
   1777 												 MGT_TOP_PMD_USR_GP_REGISTER_3_FINISH_CHANGE_MASK));
   1778         }
   1779     } else {
   1780 		/* 
   1781 		 * New module removal when 1.c843[4] == 0 and 1.c841[4] == 1
   1782 		 */
   1783         SOC_IF_ERROR_RETURN
   1784 			(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, &drv_csr));
   1785 		if (drv_csr & MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK) {
   1786             /* 
   1787              * Ack firmware new module removal 1.c841[4] = 0 
   1788              */
   1789             SOC_IF_ERROR_RETURN
   1790                  (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1, 
   1791                        0, MGT_TOP_PMD_USR_GP_REGISTER_3_SPEED_OR_TYPE_CHANGE_MASK));
   1792 			
   1793             LOG_ERROR(BSL_LS_SOC_PHY,
   1794                       (BSL_META_U(unit,
   1795                                   "PHY82328 module removed u=%d p=%d\n"), unit, port));
   1796         }
   1797     }
   1798 
   1799 	return SOC_E_NONE;
   1800 }
   1801 
   1802 /*
   1803  *    phy_82328_link_get
   1804  * Purpose:
   1805  *    Get layer2 connection status.
   1806  * Parameters:
   1807  *    unit - StrataSwitch unit #.
   1808  *    port - StrataSwitch port #.
   1809  *      link - address of memory to store link up/down state.
   1810  * Returns:
   1811  *    SOC_E_NONE
   1812  */
   1813  
   1814 STATIC int32
   1815 phy_82328_link_get(int32 unit, soc_port_t port, int32 *link)
   1816 {
   1817     phy_ctrl_t  *int_pc, *pc;
   1818     int32 int_phy_link = 0;
   1819 	
   1820     if (link == NULL) {
   1821         return SOC_E_PARAM;
   1822     }
   1823     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1824         *link = FALSE;
   1825         return SOC_E_NONE;
   1826     }
   1827     int_pc = INT_PHY_SW_STATE(unit, port);   
   1828     pc = EXT_PHY_SW_STATE(unit, port);   
   1829     
   1830     if (int_pc != NULL) {
   1831         SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &int_phy_link));
   1832         *link = int_phy_link;
   1833     } else {
   1834        *link = 1;
   1835     }
   1836 
   1837     SOC_IF_ERROR_RETURN(
   1838             _phy_82328_intf_link_get( unit, port, link));
   1839 
   1840     if (MOD_AUTO_DETECT(pc)) {
   1841 		SOC_IF_ERROR_RETURN(
   1842                 _phy_82328_mod_auto_detect_update(unit, port));
   1843 	}
   1844 
   1845     LOG_VERBOSE(BSL_LS_SOC_PHY,
   1846                 (BSL_META_U(unit,
   1847                             "phy_82328_link_get: u=%d port%d: link:%s\n"),
   1848                  unit, port, *link ? "Up": "Down"));
   1849     return SOC_E_NONE;
   1850 }
   1851 
   1852 /*
   1853  * Function:
   1854  *    phy_82328_enable_set
   1855  * Purpose:
   1856  *    Enable/Disable phy
   1857  * Parameters:
   1858  *    unit - StrataSwitch unit #.
   1859  *    port - StrataSwitch port #.
   1860  *      enable - on/off state to set
   1861  * Returns:
   1862  *    SOC_E_NONE
   1863  */
   1864  
   1865 STATIC int32
   1866 phy_82328_enable_set(int32 unit, soc_port_t port, int32 enable)
   1867 {
   1868     uint16 chan_data, chan_mask;
   1869     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   1870     phy_ctrl_t  *int_pc = INT_PHY_SW_STATE(unit, port);
   1871 
   1872 	/* Manually power channel up/down */
   1873     chan_data = enable ? 0 :
   1874         (1 << MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_MAN_TXON_EN_SHIFT) |
   1875         (1 << MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_TXOFFT_SHIFT);
   1876     chan_mask = MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_MAN_TXON_EN_MASK |
   1877         MGT_TOP_PMD_USR_OPTICAL_CONFIGURATION_TXOFFT_MASK;
   1878         SOC_IF_ERROR_RETURN(
   1879             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_OPTICAL_CONFIGURATION,
   1880                                        chan_data, chan_mask));
   1881     if (enable) {
   1882         SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 1));
   1883         /* Let the micro settle down after powering back up */
   1884         sal_udelay(100);
   1885         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
   1886         PORT_DISABLED(pc) = 0;
   1887     } else {
   1888         SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 0));
   1889         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
   1890         PORT_DISABLED(pc) = 1;
   1891     }
   1892     return SOC_E_NONE;
   1893 }
   1894 
   1895 /*
   1896  * Function:
   1897  *    phy_82328_regbit_set_wait_check
   1898  * Purpose:
   1899  *   Waits for a reg. bit to be set. 
   1900  *	 Spins until bit is set or time out. 
   1901  *   The time out is programmable.
   1902  * Parameters:
   1903  *    unit - StrataSwitch unit #.
   1904  *    port - StrataSwitch port #.
   1905  *    reg  - register to test
   1906  *	  bit_num - register bit to be tested
   1907  *    bitset - to test set/clear
   1908  *    timeout - spin time out
   1909  * Returns:
   1910  *    SOC_E_NONE if no errors, SOC_E_ERROR else.
   1911  */
   1912 STATIC
   1913 int32 phy_82328_regbit_set_wait_check(int32 unit ,int32 port,
   1914                   int32 reg,              /* register to check */
   1915                   int32 bit_num,          /* bit number to check */
   1916                   int32 bitset,           /* check bit set or bit clear */
   1917                   int32 timeout)          /* max wait time to check */
   1918 {                      
   1919     uint16         data16 = 0;
   1920     soc_timeout_t  to;
   1921     int32            rv;
   1922     int32            cond;
   1923     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1924 
   1925     /* override min_polls with iteration count for DV. */
   1926     soc_timeout_init(&to, timeout, 0);
   1927     do {     
   1928         rv = READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, reg, &data16);
   1929         cond = (bitset  && (data16 & bit_num)) ||
   1930                (!bitset && !(data16 & bit_num));
   1931         if (cond || (rv < 0)) {
   1932             break;
   1933         }
   1934     } while (!soc_timeout_check(&to));
   1935 
   1936     /* Do one final check potentially after timeout as required by soc_timeout */
   1937     if (rv >= 0) {
   1938         rv = READ_PHY82328_MMF_PMA_PMD_REG(unit,pc,reg,&data16);
   1939         cond = (bitset  && (data16 & bit_num)) ||
   1940                (!bitset && !(data16 & bit_num));
   1941     }
   1942     return (cond? SOC_E_NONE: SOC_E_TIMEOUT);
   1943 }
   1944 
   1945 STATIC phy82328_intf_side_t
   1946 _phy_82328_intf_side_regs_get(int32 unit, soc_port_t port)
   1947 {
   1948     int32 rv=0;
   1949     uint16 data=0;
   1950     phy82328_intf_side_t side = PHY82328_INTF_SIDE_LINE;
   1951     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);                
   1952  
   1953     rv = READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, &data);
   1954     if (rv == SOC_E_NONE) {
   1955         side = (data & MGT_TOP_PMD_USR_XPMD_REGS_SEL_SELECT_SYS_REGISTERS_MASK) ? 
   1956                 PHY82328_INTF_SIDE_SYS : PHY82328_INTF_SIDE_LINE;
   1957     }
   1958     return side;
   1959 }
   1960 
   1961 STATIC int32
   1962 _phy_82328_intf_update(int32 unit, soc_port_t port, uint16 reg_data, uint16 reg_mask)
   1963 {
   1964     uint16 ucode_csr_bef;
   1965     phy82328_intf_side_t saved_side;
   1966     int32 rv = SOC_E_NONE;
   1967     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   1968  
   1969     /* Access line side registers */
   1970     saved_side = _phy_82328_intf_side_regs_get(unit, port);
   1971     if (saved_side == PHY82328_INTF_SIDE_SYS) {                
   1972         SOC_IF_ERROR_RETURN(
   1973          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   1974     }
   1975     /* Make sure ucode has acked */
   1976     rv = READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_3, &ucode_csr_bef);
   1977     if (SOC_FAILURE(rv)) {
   1978         LOG_ERROR(BSL_LS_SOC_PHY,
   1979                   (BSL_META_U(unit,
   1980                               "82328 failed reading ucode csr: u=%d p=%d err=%d\n"),
   1981                               unit, port, rv));
   1982         goto fail;
   1983     }
   1984     if ((ucode_csr_bef & MGT_TOP_PMD_USR_GP_REGISTER_3_FINISH_CHANGE_MASK) ==
   1985                 MGT_TOP_PMD_USR_GP_REGISTER_3_FINISH_CHANGE_MASK) {
   1986 
   1987         /* Cmd active and ucode acked, so let ucode know drv saw ack */
   1988         rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1,
   1989                        0x0,  MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_MASK);
   1990         if (SOC_FAILURE(rv)) {
   1991             LOG_ERROR(BSL_LS_SOC_PHY,
   1992                       (BSL_META_U(unit,
   1993                                   "82328 failed clearing ack: u=%d p=%d err=%d\n"),
   1994                                   unit, port, rv));
   1995             goto fail;
   1996         }
   1997 
   1998         /*Spin for finish Flag to Clear*/
   1999         rv = phy_82328_regbit_set_wait_check (unit,port,MGT_TOP_GP_REGISTER_3,
   2000                MGT_TOP_PMD_USR_GP_REGISTER_3_FINISH_CHANGE_MASK,0,1000000);
   2001         if (rv != SOC_E_NONE) {
   2002             goto fail;
   2003         }
   2004     }
   2005     LOG_INFO(BSL_LS_SOC_PHY,
   2006              (BSL_META_U(unit,
   2007                          "82328 intf update register: u=%d, p=%d, 1.%04x=%04x/%04x ucode_csr=%04x\n"),
   2008                          unit, port, MGT_TOP_GP_REGISTER_1, reg_data, reg_mask, ucode_csr_bef));
   2009  
   2010     /* Send command */
   2011     rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1,
   2012                                       reg_data, reg_mask);
   2013     if (SOC_FAILURE(rv)) {
   2014         LOG_ERROR(BSL_LS_SOC_PHY,
   2015                   (BSL_META_U(unit,
   2016                               "82328 failed sending command to ucode: u=%d p=%d err=%d\n"),
   2017                    unit, port, rv));
   2018         goto fail;
   2019     }
   2020     /* Handshake with microcode by waiting for ack before moving on */
   2021     rv = phy_82328_regbit_set_wait_check (unit, port, MGT_TOP_GP_REGISTER_3,
   2022                  MGT_TOP_PMD_USR_GP_REGISTER_3_FINISH_CHANGE_MASK, 1, 1000000);
   2023 				
   2024     if (rv !=SOC_E_NONE) {
   2025         goto fail;
   2026     }
   2027     /* Cmd active and ucode acked - let ucode know we saw ack */
   2028     rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REGISTER_1,
   2029             0,  MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_MASK);
   2030     if (rv != SOC_E_NONE) {
   2031         goto fail;
   2032     }
   2033  
   2034 fail:
   2035     if (saved_side == PHY82328_INTF_SIDE_SYS) {                
   2036         SOC_IF_ERROR_RETURN(
   2037          phy82328_intf_side_reg_select (unit, port, PHY82328_INTF_SIDE_SYS));
   2038     }
   2039     return rv;
   2040 }
   2041 						
   2042 STATIC int32
   2043 _phy_82328_intf_datapath_reg_get(int32 unit, soc_port_t port, phy82328_datapath_t datapath,
   2044                                                                  uint16 *reg_data, uint16 *reg_mask)
   2045 {
   2046     *reg_data = 0;
   2047     *reg_mask = 0;
   2048  
   2049     switch (datapath) {
   2050         case PHY82328_DATAPATH_20:
   2051             *reg_data = 0;
   2052         break;
   2053         case PHY82328_DATAPATH_4_DEPTH_1:
   2054             *reg_data = PHY82328_4BIT_DP_DEPTH1;
   2055         break;
   2056         case PHY82328_DATAPATH_4_DEPTH_2:
   2057             *reg_data =	PHY82328_4BIT_DP_DEPTH2;
   2058         break;
   2059         default :
   2060             LOG_ERROR(BSL_LS_SOC_PHY,
   2061                       (BSL_META_U(unit,
   2062                                   "82328 invalid datapath: u=%d p=%d datapath=%d\n"),
   2063                                   unit, port, datapath));
   2064             return SOC_E_CONFIG;
   2065     }
   2066     *reg_data |= (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_SHIFT);
   2067     *reg_mask = (MGT_TOP_PMD_USR_GP_REGISTER_1_ENABLE_ULTRA_LOW_LATENCY_DATAPATH_MASK |
   2068 	             MGT_TOP_PMD_USR_GP_REGISTER_1_ULL_DATAPATH_LATENCY_MASK |
   2069                  MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_MASK);
   2070 				 
   2071     LOG_INFO(BSL_LS_SOC_PHY,
   2072              (BSL_META_U(unit,
   2073                          "82328 datapath set register: u=%d, p=%d, reg=%04x/%04x, datapath=%d\n"),
   2074                          unit, port, *reg_data, *reg_mask, datapath));
   2075     return SOC_E_NONE;
   2076 }
   2077 
   2078 /*
   2079  * Return the settings in gp_reg_1/gp_register_1 for the inteface speed
   2080  * Register data and mask are returned to modify the register.
   2081  */ 
   2082 STATIC int32
   2083 _phy_82328_intf_speed_reg_get(int32 unit, soc_port_t port, int32 speed, uint16 *reg_data, uint16 *reg_mask)
   2084 {
   2085     *reg_data = 0;
   2086     *reg_mask = 0;		
   2087     switch (speed) {
   2088         case PHY82328_SPD_100G: /*1.C841.3 Not yet implemented */
   2089 	       *reg_data = PHY82328_GP_REG_1_SPD_100G; 
   2090            break;
   2091         case PHY82328_SPD_42G:/*1.C841.[2-0]*/
   2092            *reg_data = PHY82328_GP_REG_1_SPD_42G; 
   2093         break;
   2094         case PHY82328_SPD_40G:/*1.C841.2*/
   2095             *reg_data = PHY82328_GP_REG_1_SPD_40G;
   2096         break;
   2097 		case PHY82328_SPD_11G: /*1.C841.0 & 1.C841.2*/
   2098             *reg_data = PHY82328_GP_REG_1_SPD_11G;
   2099         break;
   2100         case PHY82328_SPD_10G: /*1.C841.1*/
   2101             *reg_data = PHY82328_GP_REG_1_SPD_10G;
   2102         break;
   2103         case PHY82328_SPD_1G:/*1.C841.0*/
   2104 		case 100:
   2105 		case 10:
   2106             *reg_data = PHY82328_GP_REG_1_SPD_1G;
   2107         break;
   2108         default :
   2109             LOG_ERROR(BSL_LS_SOC_PHY,
   2110                       (BSL_META_U(unit,
   2111                                   "82328 invalid line speed %d: u=%d p=%d\n"),
   2112                                   speed, unit, port));
   2113             return SOC_E_CONFIG;
   2114     }
   2115     *reg_data |= (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_SHIFT);
   2116     *reg_mask |= MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_MASK;
   2117     *reg_mask |= (MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_1G_MASK |
   2118                   MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_10G_MASK|
   2119                   MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_40G_MASK |
   2120                   MGT_TOP_PMD_USR_GP_REGISTER_1_SPEED_100G_MASK);
   2121  
   2122     LOG_INFO(BSL_LS_SOC_PHY,
   2123              (BSL_META_U(unit,
   2124                          "82328 speed set register: u=%d, p=%d, reg=%04x/%04x), speed=%d\n"),
   2125                          unit, port, *reg_data, *reg_mask, speed));
   2126     return SOC_E_NONE;
   2127 }
   2128 
   2129 STATIC int32
   2130 _phy_82328_intf_type_reg_get(int32 unit, soc_port_t port, soc_port_if_t intf_type,
   2131                             phy82328_intf_side_t side, uint16 *reg_data, uint16 *reg_mask)
   2132 {
   2133     uint16 data = 0;
   2134     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   2135  
   2136     assert((side == PHY82328_INTF_SIDE_LINE) || (side == PHY82328_INTF_SIDE_SYS));
   2137     *reg_data = 0;
   2138     *reg_mask = 0;
   2139  
   2140     switch (intf_type) {			
   2141         case SOC_PORT_IF_KX:
   2142         case SOC_PORT_IF_KR:
   2143         case SOC_PORT_IF_KR4:
   2144             data = (side == PHY82328_INTF_SIDE_SYS) ?
   2145                    (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_TYPE_SHIFT):
   2146                    (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_TYPE_SHIFT);
   2147             *reg_mask |= (side == PHY82328_INTF_SIDE_SYS) ?
   2148                 (MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_TYPE_MASK):
   2149                 (MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_TYPE_MASK);
   2150         break;
   2151         case SOC_PORT_IF_SR:
   2152         case SOC_PORT_IF_SFI:/*Nothing but 10G, but not in list*/
   2153         case SOC_PORT_IF_GMII:
   2154         case SOC_PORT_IF_SGMII:
   2155         case SOC_PORT_IF_SR4: 
   2156             data = 0;
   2157         break;
   2158         case SOC_PORT_IF_CR4: 
   2159             /* If CR4 line side and autoneg enabled, then CR4, otherwise, XFI/XLAUI_DFE*/
   2160             if (side == PHY82328_INTF_SIDE_LINE) {
   2161                 data = (AN_EN(pc)) ? (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_SHIFT) :
   2162                           ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_FORCED_CL72_MODE_SHIFT) |
   2163                            (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_SHIFT));
   2164             } else {
   2165                 /*System side set to XLAUI_DFE */
   2166                 /*CR4 System side is unusual taken  
   2167                   CL72 not supported for Sys Side only DFE*/
   2168                 data = (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_SHIFT) |
   2169                        (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_CU_TYPE_SHIFT);
   2170             }
   2171         break;			
   2172        case SOC_PORT_IF_CR:
   2173             data = (side == PHY82328_INTF_SIDE_SYS) ?
   2174                    ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_SHIFT) |
   2175                    (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_CU_TYPE_SHIFT)) :
   2176                    (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_SHIFT);
   2177         break;
   2178         case SOC_PORT_IF_XFI:
   2179         case SOC_PORT_IF_XLAUI:
   2180             data = (side == PHY82328_INTF_SIDE_SYS) ?
   2181                    ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_LR_MODE_SHIFT) |
   2182                    (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_CU_TYPE_SHIFT)) :
   2183                    ((1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_LR_MODE_SHIFT) |
   2184                    (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_SHIFT));
   2185         break;
   2186 			
   2187         case SOC_PORT_IF_LR:
   2188         case SOC_PORT_IF_LR4:
   2189             data = (side == PHY82328_INTF_SIDE_SYS) ?
   2190                    (1<< MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_LR_MODE_SHIFT) :
   2191                    (1<< MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_LR_MODE_SHIFT);
   2192         break;
   2193         default:
   2194             LOG_ERROR(BSL_LS_SOC_PHY,
   2195                       (BSL_META_U(unit,
   2196                                   "82328 Unsupported interface: u=%d p=%d\n"), unit, port));			
   2197             return SOC_E_UNAVAIL;
   2198     }
   2199     *reg_data |= (data | (1 << MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_SHIFT));
   2200     *reg_mask |=  MGT_TOP_PMD_USR_GP_REGISTER_1_FINISH_CHANGE_MASK;
   2201     if (side == PHY82328_INTF_SIDE_LINE) {
   2202         *reg_mask |= (MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_LR_MODE_MASK |
   2203                       MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_FORCED_CL72_MODE_MASK |
   2204                       MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_CU_TYPE_MASK |
   2205                       MGT_TOP_PMD_USR_GP_REGISTER_1_LINE_TYPE_MASK);
   2206     } else {
   2207         /* System side mask */
   2208         *reg_mask |=  (MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_LR_MODE_MASK |
   2209                        MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_MASK |
   2210                        MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_CU_TYPE_MASK | 
   2211                        MGT_TOP_PMD_USR_GP_REGISTER_1_SYSTEM_TYPE_MASK);
   2212     }
   2213     LOG_INFO(BSL_LS_SOC_PHY,
   2214              (BSL_META_U(unit,
   2215                          "82328 intf type register: u=%d, p=%d, reg=%04x/%04x, intf=%d\n"),
   2216                          unit, port, *reg_data, *reg_mask, intf_type));
   2217  
   2218     return SOC_E_NONE;	
   2219 }
   2220 
   2221 STATIC int32
   2222 _phy_82328_intf_debug_print(int32 unit, soc_port_t port, const char *msg)
   2223 {
   2224 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   2225     phy_ctrl_t  *pc;
   2226     phy82328_intf_cfg_t *line_intf, *sys_intf;
   2227  
   2228     pc = EXT_PHY_SW_STATE(unit, port);
   2229     line_intf = &(LINE_INTF(pc));
   2230     sys_intf = &(SYS_INTF(pc));
   2231  
   2232     LOG_INFO(BSL_LS_SOC_PHY,
   2233              (BSL_META_U(unit,
   2234                          "%s: "), msg));
   2235     LOG_INFO(BSL_LS_SOC_PHY,
   2236              (BSL_META_U(unit,
   2237                          "[LINE:intf=%s,speed=%d], "),
   2238                          phy82328_intf_names[line_intf->type], line_intf->speed));
   2239     LOG_INFO(BSL_LS_SOC_PHY,
   2240              (BSL_META_U(unit,
   2241                          "[SYS :intf=%s,speed=%d]\n"),
   2242                          phy82328_intf_names[sys_intf->type], sys_intf->speed));
   2243 #endif /* BROADCOM_DEBUG || DEBUG_PRINT */
   2244     return SOC_E_NONE;
   2245 }
   2246 
   2247 
   2248 STATIC int32
   2249 _phy_82328_intf_line_sys_update(int32 unit, soc_port_t port)
   2250 {
   2251     phy_ctrl_t  *pc;
   2252     phy_ctrl_t *int_pc; 
   2253     uint16      data = 0, mask = 0;
   2254     uint16      reg_data = 0, reg_mask = 0;
   2255     int32 int_phy_en = 0;
   2256     phy82328_intf_cfg_t *line_intf, *sys_intf;
   2257  
   2258     pc = EXT_PHY_SW_STATE(unit, port);    
   2259     int_pc = INT_PHY_SW_STATE(unit, port);    
   2260     line_intf = &(LINE_INTF(pc));
   2261     sys_intf = &(SYS_INTF(pc));
   2262  
   2263     _phy_82328_intf_debug_print(unit, port, "interface/Speed update");
   2264 
   2265     reg_data = 0;
   2266     reg_mask = 0;
   2267     SOC_IF_ERROR_RETURN(
   2268         _phy_82328_intf_type_reg_get(unit, port, line_intf->type,
   2269                                      PHY82328_INTF_SIDE_LINE, &data, &mask));
   2270     reg_data |= data;
   2271     reg_mask |= mask;
   2272 
   2273     SOC_IF_ERROR_RETURN(
   2274         _phy_82328_intf_type_reg_get(unit, port, sys_intf->type,
   2275                                      PHY82328_INTF_SIDE_SYS, &data, &mask));
   2276     reg_data |= data;
   2277     reg_mask |= mask;
   2278 	
   2279     LOG_INFO(BSL_LS_SOC_PHY,
   2280              (BSL_META_U(unit,
   2281                          "82328  intf update: line=%s sys=%s speed=%d (1.%x = %04x/%04x): u=%d p=%d\n"),
   2282               phy82328_intf_names[line_intf->type], phy82328_intf_names[sys_intf->type],
   2283               line_intf->speed, MGT_TOP_GP_REGISTER_1, reg_data, reg_mask,
   2284               unit, port));	
   2285 	
   2286     SOC_IF_ERROR_RETURN(
   2287         _phy_82328_intf_speed_reg_get(unit, port, line_intf->speed, &data, &mask));
   2288     reg_data |= data;
   2289     reg_mask |= mask;
   2290 
   2291     SOC_IF_ERROR_RETURN(
   2292         _phy_82328_intf_datapath_reg_get(unit, port, CUR_DATAPATH(pc), &data, &mask));
   2293     reg_data |= data;
   2294     reg_mask |= mask;
   2295 
   2296     LOG_INFO(BSL_LS_SOC_PHY,
   2297              (BSL_META_U(unit,
   2298                          "82328  intf update: line=%s sys=%s speed=%d (1.%x = %04x/%04x): u=%d p=%d\n"),
   2299               phy82328_intf_names[line_intf->type], phy82328_intf_names[sys_intf->type],
   2300               line_intf->speed, MGT_TOP_GP_REGISTER_1, reg_data, reg_mask,
   2301               unit, port));
   2302 
   2303     if (SYNC_INIT(pc) == 1) {
   2304         SOC_IF_ERROR_RETURN(PHY_ENABLE_GET(int_pc->pd, unit, port, &int_phy_en));
   2305         if (int_phy_en) {
   2306             /* Turn off internal PHY while the mode changes */
   2307             SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 0));
   2308         }
   2309     }
   2310     /* GP registers are only on the line side */
   2311     SOC_IF_ERROR_RETURN(_phy_82328_intf_update(unit, port, reg_data, reg_mask));
   2312 
   2313     if (SYNC_INIT(pc) == 1) {
   2314         if (int_phy_en) {
   2315             /* If called from PASS2 we skip this and complete in PASS3 */
   2316             if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2)) {
   2317                 INT_PHY_RE_EN(pc) = 1;
   2318                 /* start timer */
   2319                 soc_timeout_init(&SYNC_TO(pc), 10000, 0);
   2320             } else {
   2321                 sal_udelay(10000);
   2322                 /* Turn internal PHY back on now that the mode has been configured */
   2323                 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 1));
   2324             }
   2325         }
   2326     }
   2327     return SOC_E_NONE;
   2328 }
   2329 
   2330 
   2331 /*
   2332  * Return whether AN is enabled or forced with internal SerDes on the system side
   2333  */
   2334 STATIC int32
   2335 _phy_82328_intf_sys_forced(int32 unit, soc_port_t port, soc_port_if_t intf_type)
   2336 {
   2337     int32 rv;
   2338     phy_ctrl_t *pc;
   2339 
   2340     pc = EXT_PHY_SW_STATE(unit, port);
   2341 
   2342     switch (intf_type) {
   2343         case SOC_PORT_IF_SR:
   2344         case SOC_PORT_IF_SR4:
   2345         case SOC_PORT_IF_LR:
   2346         case SOC_PORT_IF_LR4:
   2347         case SOC_PORT_IF_XLAUI:
   2348         case SOC_PORT_IF_XFI:
   2349         case SOC_PORT_IF_SFI:
   2350         case SOC_PORT_IF_CR:
   2351         case SOC_PORT_IF_CR4:
   2352         case SOC_PORT_IF_ZR:
   2353             rv = TRUE;
   2354         break;
   2355         case SOC_PORT_IF_GMII:
   2356             rv = FALSE;
   2357         break;
   2358         case SOC_PORT_IF_KR:
   2359         case SOC_PORT_IF_KR4:
   2360             rv = SYS_FORCED_CL72(pc) ? TRUE : FALSE;
   2361         break;
   2362         default:
   2363             rv = FALSE;
   2364     }
   2365     return rv;
   2366 }
   2367 
   2368 STATIC int32
   2369 _phy_82328_speed_set(int32 unit, soc_port_t port, int32 speed)
   2370 {
   2371     int rv = SOC_E_NONE;
   2372     int cur_speed = 0;
   2373     uint32  cur_fw_mode = 0;
   2374     int32 cur_an, cur_an_done;
   2375     soc_port_if_t cur_type, new_type;
   2376     phy_ctrl_t  *pc, *int_pc;
   2377     phy82328_intf_cfg_t  *line_intf;
   2378     phy82328_intf_cfg_t  *sys_intf;
   2379  
   2380     pc = EXT_PHY_SW_STATE(unit, port);
   2381     int_pc = INT_PHY_SW_STATE(unit, port);
   2382     line_intf = &(LINE_INTF(pc));
   2383     sys_intf = &(SYS_INTF(pc));
   2384  
   2385     line_intf->speed = speed;
   2386     sys_intf->speed = speed;	
   2387     
   2388     if (int_pc != NULL) {
   2389         if ((sys_intf->type == SOC_PORT_IF_GMII) || (sys_intf->type == SOC_PORT_IF_SGMII)) {
   2390             SOC_IF_ERROR_RETURN(PHY_SPEED_SET(int_pc->pd, unit, port, sys_intf->speed));
   2391         } else if (_phy_82328_intf_sys_forced(unit, port, sys_intf->type) ) {
   2392             /*
   2393              * When setting system side 40G DAC/XLAUI-DFE, tell internal SerDes to match
   2394              * with XLAUI.
   2395              *
   2396              * If flexports, the internal SerDes may be out of sync until it gets a chance 
   2397              *  to convert the port, so these operations may be best effort.
   2398              */
   2399             /* When the speed is 20G forcing interface to MLD irrespective of
   2400              * remote PHY capability. When remote PHY capablity is enabled 
   2401              * forcing interface and speed */
   2402                 new_type = (sys_intf->type == SOC_PORT_IF_CR4) ? SOC_PORT_IF_XLAUI : sys_intf->type;
   2403                 SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET(int_pc->pd, unit, port, &cur_type));
   2404                 if (cur_type != new_type) {
   2405                     (void) PHY_INTERFACE_SET(int_pc->pd, unit, port, new_type);
   2406                 }
   2407 
   2408             /* Check if it must change to forced */
   2409             SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &cur_an, &cur_an_done));
   2410             if (cur_an == TRUE) {
   2411                 (void) PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit,port, FALSE);
   2412             }
   2413             if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2)) {
   2414                 /* Skip int_pc speed set during phy init */
   2415             } else if ((rv = PHY_SPEED_GET(int_pc->pd, unit, port, &cur_speed))
   2416                         != SOC_E_NONE) {
   2417 #if 0
   2418                 LOG_CLI((BSL_META_U(unit,
   2419                                     "82328 u=%d p=%d speed get error\n"), unit, port));
   2420 #endif
   2421                 return rv;
   2422             } else if (cur_speed  != sys_intf->speed) {
   2423                 (void) PHY_SPEED_SET(int_pc->pd, unit, port, sys_intf->speed);
   2424             }
   2425 
   2426             /* For system intf=cr4 use XLAUI_DFE on Serdes (in forced mode)*/
   2427             if (sys_intf->type != SOC_PORT_IF_CR4) {
   2428                 /* Skip int_pc fw mode set */
   2429             } else if ((rv = PHY_CONTROL_GET(int_pc->pd, unit, port,
   2430                              SOC_PHY_CONTROL_FIRMWARE_MODE, &cur_fw_mode))
   2431                         != SOC_E_NONE) {                
   2432                 return rv;
   2433             } else if (cur_fw_mode != SOC_PHY_FIRMWARE_FORCE_OSDFE) {
   2434                 (void) PHY_CONTROL_SET(int_pc->pd, unit, port,
   2435                                         SOC_PHY_CONTROL_FIRMWARE_MODE,
   2436                                         SOC_PHY_FIRMWARE_FORCE_OSDFE);
   2437             }
   2438 
   2439         } else {
   2440             SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit,port, TRUE));
   2441         }
   2442     }
   2443     /* Update interface type/speed */        
   2444     return (_phy_82328_intf_line_sys_update(unit, port));
   2445 }
   2446 /*
   2447  * Function:
   2448  *    _phy_82328_intf_type_1G
   2449  * Purpose:
   2450  *   Check the interface for 1G
   2451  * Parameters:
   2452  *    unit - StrataSwitch unit #.
   2453  *    port - StrataSwitch port #.
   2454  *    intf_type - Interface type to test
   2455  * Returns:
   2456  *    TRUE/FALSE
   2457  */
   2458 STATIC int32
   2459 _phy_82328_intf_type_1G(soc_port_if_t intf_type)
   2460 {
   2461     int32 rv;
   2462  
   2463     switch (intf_type) {
   2464         case SOC_PORT_IF_KX:
   2465         case SOC_PORT_IF_GMII:
   2466         case SOC_PORT_IF_SGMII:
   2467             rv = TRUE;
   2468         break;
   2469         default:
   2470             rv = FALSE;
   2471     }
   2472     return rv;
   2473 }
   2474 
   2475 /*
   2476  * Function:
   2477  *    _phy_82328_intf_type_10G
   2478  * Purpose:
   2479  *   Check the interface for 10G
   2480  * Parameters:
   2481  *    unit - StrataSwitch unit #.
   2482  *    port - StrataSwitch port #.
   2483  *    intf_type - Interface type to test
   2484  * Returns:
   2485  *    TRUE/FALSE
   2486  */
   2487 STATIC int32
   2488 _phy_82328_intf_type_10G(soc_port_if_t intf_type)
   2489 {
   2490     int32 rv;
   2491     
   2492     switch (intf_type) {
   2493         case SOC_PORT_IF_SR:
   2494         case SOC_PORT_IF_CR:
   2495 		case SOC_PORT_IF_LR:
   2496         case SOC_PORT_IF_KR:
   2497         case SOC_PORT_IF_ZR:
   2498         case SOC_PORT_IF_XFI:
   2499         case SOC_PORT_IF_SFI:
   2500             rv = TRUE;
   2501         break;
   2502         default:
   2503             rv = FALSE;
   2504     }
   2505     return rv;
   2506 }
   2507 
   2508 
   2509 STATIC int32
   2510 _phy_82328_intf_line_sys_init(int32 unit, soc_port_t port)
   2511 {
   2512     phy_ctrl_t  *pc;
   2513 	phy82328_intf_cfg_t  *line_intf;
   2514 
   2515     pc = EXT_PHY_SW_STATE(unit, port);
   2516 	line_intf = &(LINE_INTF(pc));
   2517 
   2518 	return _phy_82328_speed_set(unit, port, line_intf->speed);
   2519 }
   2520 
   2521 /*
   2522  * Function:
   2523  *      phy_82328_speed_set
   2524  * Purpose:
   2525  *      Set PHY speed
   2526  *      For 20G speed make sure serdes configured as 20G MLD
   2527  * Parameters:
   2528  *      unit - StrataSwitch unit #.
   2529  *      port - StrataSwitch port #.
   2530  *      speed - link speed in Mbps
   2531  * Returns:
   2532  *      SOC_E_NONE
   2533  */
   2534  
   2535 STATIC int32
   2536 phy_82328_speed_set(int32 unit, soc_port_t port, int32 speed)
   2537 {
   2538     int32 rv;
   2539     phy_ctrl_t  *pc;
   2540     phy82328_intf_cfg_t  *line_intf;
   2541     phy82328_intf_cfg_t  *sys_intf;
   2542  
   2543     COMPILER_REFERENCE(unit);
   2544     COMPILER_REFERENCE(port);
   2545  
   2546     pc = EXT_PHY_SW_STATE(unit, port);
   2547     line_intf = &(LINE_INTF(pc));
   2548     sys_intf = &(SYS_INTF(pc));
   2549 
   2550     LOG_INFO(BSL_LS_SOC_PHY,
   2551              (BSL_META_U(unit,
   2552                          "phy_82328_speed_set: u=%d p=%d speed=%d\n"),
   2553                          unit, port,speed));
   2554     if (PHY82328_SINGLE_PORT_MODE(pc)) {
   2555         if (!_phy_82328_intf_is_single_port(line_intf->type)) {
   2556              LOG_INFO(BSL_LS_SOC_PHY,
   2557                       (BSL_META_U(unit,
   2558                                   "82328 speed set does not match interface: "
   2559                                   "u=%d p=%d speed=%d intf=%d\n"),
   2560                        unit, port, speed, sys_intf->type));
   2561              return SOC_E_PARAM;
   2562         }
   2563         /*Single port mode can supported 40/40HG/42HG/100G*/
   2564         switch (speed) {
   2565             case PHY82328_SPD_40G: 
   2566                 /* Both 40G And 40HG share same
   2567                  * register config */
   2568             break;
   2569             case PHY82328_SPD_42G:
   2570                 if (! IS_HG_PORT(unit, port)) {
   2571                     speed = PHY82328_SPD_40G;
   2572                 }
   2573             break;
   2574             case PHY82328_SPD_100G:  
   2575             break;
   2576             default:
   2577                 LOG_ERROR(BSL_LS_SOC_PHY,
   2578                           (BSL_META_U(unit,
   2579                                       "82328  invalid speed Single Port: u=%d p=%d speed=%d\n"),
   2580                            unit, port, speed));
   2581             return SOC_E_PARAM;
   2582         }
   2583     } else {
   2584         /*Check for the valid interface*/
   2585         if(_phy_82328_intf_is_single_port(line_intf->type)){
   2586             LOG_ERROR(BSL_LS_SOC_PHY,
   2587                       (BSL_META_U(unit,
   2588                                   "82328  invalid intf in quad port: u=%d p=%d intf=%d\n"),
   2589                        unit, port, line_intf->type));
   2590             return SOC_E_PARAM;
   2591 		}
   2592         switch (speed) {
   2593             case PHY82328_SPD_1G:            
   2594                 if(!_phy_82328_intf_type_1G(line_intf->type)){
   2595                     line_intf->type = SOC_PORT_IF_GMII;
   2596                 }
   2597                 /*
   2598                  * Changing speed to 1000
   2599                  * - if backplane interface(KR) then change to KX
   2600                  * - if not KX, then set to GMII
   2601                  */
   2602                 if (sys_intf->type == SOC_PORT_IF_KR) {
   2603                     sys_intf->type = SOC_PORT_IF_KX;
   2604                 } else if (sys_intf->type != SOC_PORT_IF_KX) {
   2605                     sys_intf->type = line_intf->type;
   2606                 }
   2607             break;
   2608             case 100:  
   2609             case 10:
   2610                 if (line_intf->type != SOC_PORT_IF_SGMII) {
   2611                     line_intf->type = SOC_PORT_IF_SGMII;
   2612                 }
   2613                 sys_intf->type = line_intf->type;
   2614             break;
   2615 				
   2616             /*10G/11G LR/SR/CR XFI/XFI DFE/Forced CL72*/
   2617             case PHY82328_SPD_11G:
   2618                 /* 11G only valid for HG[11] */
   2619                 if (!IS_HG_PORT(unit, port)) {
   2620                     speed = PHY82328_SPD_10G;
   2621                 }
   2622             break;
   2623             case PHY82328_SPD_10G:
   2624                 /* If changing from 1000 to 10000/11000, then adjust interface*/
   2625                 if (line_intf->speed <= PHY82328_SPD_1G) {
   2626                     /* If changing speed from 1000 to 10000, set line interface to SR*/
   2627                     if (!_phy_82328_intf_type_10G(line_intf->type)) {
   2628                         line_intf->type = SOC_PORT_IF_SR;
   2629                     }
   2630                     if (!_phy_82328_intf_type_10G(sys_intf->type)) {
   2631                         sys_intf->type = SOC_PORT_IF_XFI;
   2632                     }
   2633                 }
   2634             break;
   2635             case PHY82328_SPD_40G:
   2636             case PHY82328_SPD_42G:/*42G*/
   2637             case PHY82328_SPD_100G: 
   2638             default:
   2639                 LOG_ERROR(BSL_LS_SOC_PHY,
   2640                           (BSL_META_U(unit,
   2641                                       "82328  invalid speed Quad Port: u=%d p=%d speed=%d\n"),
   2642                            unit, port, speed));
   2643             return SOC_E_PARAM;
   2644         }
   2645     }
   2646 	
   2647     rv =  _phy_82328_speed_set(unit, port, speed);
   2648     if (SOC_FAILURE(rv)) {
   2649         LOG_ERROR(BSL_LS_SOC_PHY,
   2650                   (BSL_META_U(unit,
   2651                               "82328  %s failed: u=%d p=%d\n"), FUNCTION_NAME(), unit, port));
   2652     }
   2653     return rv;
   2654 }
   2655 
   2656 /*
   2657  * Function:
   2658  *      phy_82328_speed_get
   2659  * Purpose:
   2660  *      Get PHY speed
   2661  * Parameters:
   2662  *      unit - StrataSwitch unit #.
   2663  *      port - StrataSwitch port #.
   2664  *      speed - current link speed in Mbps
   2665  * Returns:
   2666  *      SOC_E_NONE
   2667  */
   2668  
   2669 STATIC int32
   2670 phy_82328_speed_get(int32 unit, soc_port_t port, int32 *speed)
   2671 {
   2672     phy82328_intf_cfg_t *line_intf;
   2673     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   2674 	
   2675     if ((pc !=NULL )&& (speed !=NULL)) {
   2676         line_intf = &(LINE_INTF(pc));
   2677         *speed = line_intf->speed;
   2678     } else {
   2679         return SOC_E_PARAM;
   2680     }
   2681     return SOC_E_NONE;
   2682 }
   2683 
   2684 /*
   2685  * Directly select channel to access based on interface side and lane number.
   2686  */
   2687 STATIC int32
   2688 _phy_82328_channel_direct_select(int32 unit, soc_port_t port, phy82328_intf_side_t side, int32 lane)
   2689 {
   2690     uint16      lane_sel;
   2691     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   2692 
   2693     /*
   2694      * If all lanes, restore single PMD access with lane 0 broadcast to all lanes
   2695      * For single lane, select lane in Single PMD 1.ca86[5:4] and [3..0] that corresponds
   2696      * to the lane with direct lane selection in 1.ca86[8]
   2697      */
   2698     if (lane == PHY82328_ALL_LANES) {
   2699         lane_sel = 
   2700             (LOGICAL_LANE0(pc) << MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT) |
   2701             MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK |
   2702             MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_MASK;
   2703     } else {
   2704         lane_sel = (lane << MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT) |
   2705             ((1 << lane) & MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_MASK);
   2706     }
   2707     SOC_IF_ERROR_RETURN(
   2708         _phy_82328_modify_pma_pmd_reg (unit, port, pc, 
   2709         PHY82328_DEV_PMA_PMD,  MGT_TOP_SINGLE_PMD_CTRL, 
   2710         MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_SHIFT +3/*+ 5*/, 
   2711         MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_SHIFT, lane_sel));
   2712     READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0xca86, &lane_sel);
   2713     return SOC_E_NONE;
   2714 }
   2715 
   2716 /*
   2717  * Select channel to access based on interface side and lane number.
   2718  * The side is selected before returning.
   2719  */
   2720 STATIC int32
   2721 _phy_82328_channel_select(int32 unit, soc_port_t port, phy82328_intf_side_t side, int32 lane)
   2722 {
   2723     int32 rv;
   2724     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   2725 
   2726     if (!(PHY82328_SINGLE_PORT_MODE(pc))) {
   2727         return SOC_E_PARAM;
   2728     }
   2729 
   2730     if (!((lane == PHY82328_ALL_LANES) || ((lane >= 0) && (lane <= 3)))) {
   2731         return SOC_E_PARAM;
   2732     }
   2733     SOC_IF_ERROR_RETURN(
   2734      phy82328_intf_side_reg_select(unit, port, side));
   2735 
   2736     rv  = _phy_82328_channel_direct_select(unit, port, side, lane);
   2737 
   2738     return rv;
   2739 }
   2740 
   2741 /*
   2742  *   20-bit: set txpol in line side 1.DOE3[0]
   2743  *   4-bit:  set txpol in line side 1.D0A0[9]
   2744  */
   2745 STATIC int32
   2746 _phy_82328_polarity_flip_tx_set(int32 unit, soc_port_t port, int32 flip)
   2747 {	
   2748     uint16		data = 0;
   2749     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   2750 
   2751 	/* Clear to flip, set to unflip */
   2752     if (CUR_DATAPATH(pc) == PHY82328_DATAPATH_20) {
   2753         data = flip ? TLB_RX_TLB_RX_MISC_CONFIG_RX_PMD_DP_INVERT_MASK : 0;
   2754         SOC_IF_ERROR_RETURN(
   2755           _phy_82328_modify_pma_pmd_reg (unit, port, pc, 
   2756           PHY82328_DEV_PMA_PMD,  TLB_TX_TLB_TX_MISC_CONFIG, 
   2757           TLB_TX_TLB_TX_MISC_CONFIG_TX_PMD_DP_INVERT_SHIFT, 
   2758           TLB_TX_TLB_TX_MISC_CONFIG_TX_PMD_DP_INVERT_SHIFT, data));
   2759     } else {
   2760         data = flip ? 1 : 0;
   2761         SOC_IF_ERROR_RETURN(
   2762           _phy_82328_modify_pma_pmd_reg (unit, port, pc, 
   2763           PHY82328_DEV_PMA_PMD,  AMS_TX_TX_CTRL_0,
   2764           AMS_TX_TX_CTRL_0_LL_POLARITY_FLIP_SHIFT, 
   2765           AMS_TX_TX_CTRL_0_LL_POLARITY_FLIP_SHIFT, data));
   2766     }
   2767     return SOC_E_NONE;
   2768 }
   2769 
   2770 STATIC int32
   2771 _phy_82328_polarity_flip_tx(int32 unit, soc_port_t port, phy82328_intf_side_t side, uint16 cfg_pol)
   2772 {
   2773     int32			flip;
   2774     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   2775     int32	lane = 0;
   2776     
   2777     if (side != PHY82328_INTF_SIDE_LINE) {
   2778         SOC_IF_ERROR_RETURN(
   2779          phy82328_intf_side_reg_select(unit, port, side));
   2780     }
   2781     if ((PHY82328_SINGLE_PORT_MODE(pc))) {
   2782         if (cfg_pol != PHY82328_POL_DND) {
   2783             for (lane = 0; lane < PHY82328_NUM_LANES; lane++) {
   2784 	            /* Check for all lanes or whether this lane has polarity flipped */
   2785                 if ((cfg_pol & POL_CONFIG_LANE_MASK(lane)) == POL_CONFIG_LANE_MASK(lane)) {
   2786 				    flip = 1;
   2787                 } else {
   2788                     flip = 0;
   2789                 }
   2790                 LOG_INFO(BSL_LS_SOC_PHY,
   2791                          (BSL_META_U(unit,
   2792                                      "82328 tx polarity flip=%d: u=%d p=%d" 
   2793                                      "lane=%d\n"), flip, unit, port, lane));
   2794 
   2795 			    /* Select the lane on the line side */
   2796                 SOC_IF_ERROR_RETURN
   2797                     (_phy_82328_channel_select(unit, port, side, lane));
   2798                 SOC_IF_ERROR_RETURN
   2799                     (_phy_82328_polarity_flip_tx_set(unit, port, flip));
   2800             }
   2801             /* Restore to default single port register access */
   2802             SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, PHY82328_INTF_SIDE_LINE, 
   2803                                 PHY82328_ALL_LANES));
   2804         }
   2805     } 
   2806     else {  /* quad mode */
   2807         if (cfg_pol != PHY82328_POL_DND) {
   2808             flip = (cfg_pol) ? 1 : 0;
   2809             SOC_IF_ERROR_RETURN
   2810                 (_phy_82328_polarity_flip_tx_set(unit, port, flip));
   2811             LOG_INFO(BSL_LS_SOC_PHY,
   2812                      (BSL_META_U(unit,
   2813                                  "82328  polarity flip: u=%d p=%d\n"), unit, port));
   2814         }
   2815 	}
   2816     if (side != PHY82328_INTF_SIDE_LINE) {
   2817         SOC_IF_ERROR_RETURN(
   2818          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   2819     }
   2820 
   2821     return SOC_E_NONE;
   2822 }
   2823 
   2824 STATIC int32
   2825 _phy_82328_polarity_flip_rx_20bit(int32 unit, soc_port_t port, int32 flip)
   2826 {
   2827     uint16		data = 0;
   2828     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   2829 
   2830     data = flip ? 1 : 0;
   2831     SOC_IF_ERROR_RETURN(
   2832           _phy_82328_modify_pma_pmd_reg (unit, port, pc, 
   2833           PHY82328_DEV_PMA_PMD,  TLB_RX_TLB_RX_MISC_CONFIG, 
   2834           TLB_RX_TLB_RX_MISC_CONFIG_RX_PMD_DP_INVERT_SHIFT, 
   2835           TLB_RX_TLB_RX_MISC_CONFIG_RX_PMD_DP_INVERT_SHIFT, data));
   2836 
   2837     return SOC_E_NONE;
   2838 }
   2839 			
   2840 STATIC int32
   2841 _phy_82328_polarity_flip_rx(int32 unit, soc_port_t port, phy82328_intf_side_t side, uint16 cfg_pol)
   2842 {
   2843     int32  flip;
   2844     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   2845     int32  lane;
   2846 
   2847     if (side != PHY82328_INTF_SIDE_LINE) {
   2848         SOC_IF_ERROR_RETURN(
   2849          phy82328_intf_side_reg_select(unit, port, side));
   2850     }
   2851     if ((PHY82328_SINGLE_PORT_MODE(pc))) {
   2852         if (cfg_pol != PHY82328_POL_DND) {	
   2853             /* 4-bit polarity handled on system side */
   2854      		if (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20) {
   2855                 PHY_82328_MICRO_PAUSE(unit, port, "polarity rx");
   2856             }
   2857             for (lane = 0; lane < PHY82328_NUM_LANES; lane++) {
   2858                 flip = 0;
   2859                 if ((cfg_pol & POL_CONFIG_LANE_MASK(lane)) == POL_CONFIG_LANE_MASK(lane)) {
   2860                     flip = 1;
   2861                 }
   2862                 if (CUR_DATAPATH(pc) == PHY82328_DATAPATH_20) {
   2863                     SOC_IF_ERROR_RETURN
   2864                         (_phy_82328_channel_select(unit, port, side, lane));
   2865                     SOC_IF_ERROR_RETURN
   2866                         (_phy_82328_polarity_flip_rx_20bit(unit, port, flip));
   2867                 }
   2868                 LOG_INFO(BSL_LS_SOC_PHY,
   2869                          (BSL_META_U(unit,
   2870                                      "82328 rx polarity flip: u=%d p=%d lane=%d\n"), unit, port, lane));
   2871             }
   2872             /* Restore to default single port register access */
   2873             SOC_IF_ERROR_RETURN
   2874                 (_phy_82328_channel_select(unit, port, PHY82328_INTF_SIDE_LINE, PHY82328_ALL_LANES));
   2875             if (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20) {
   2876                 PHY_82328_MICRO_RESUME(unit, port);
   2877             }
   2878         }
   2879     }
   2880 
   2881     else {  /* quad mode */
   2882         if (cfg_pol != PHY82328_POL_DND) {
   2883             flip = (cfg_pol)? 1:0;
   2884             SOC_IF_ERROR_RETURN(_phy_82328_polarity_flip_rx_20bit(unit, port, flip));
   2885         }
   2886     }
   2887     
   2888     if (side != PHY82328_INTF_SIDE_LINE) {
   2889         SOC_IF_ERROR_RETURN(
   2890          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   2891     }
   2892 
   2893     LOG_INFO(BSL_LS_SOC_PHY,
   2894              (BSL_META_U(unit,
   2895                          "82328 rx polarity flip: u=%d p=%d\n"), unit, port));
   2896     return SOC_E_NONE;
   2897 }
   2898 
   2899 /*                                                                                              
   2900  * Flip configured tx/rx polarities
   2901  *
   2902  * Property values are either 1 for all lanes or
   2903  * lane 0: 0001
   2904  * lane 1: 0002
   2905  * lane 2: 0004
   2906  * lane 3: 0008
   2907  */
   2908 STATIC int32
   2909 _phy_82328_polarity_flip(int32 unit, soc_port_t port, uint16 cfg_tx_pol, uint16 cfg_rx_pol)
   2910 {
   2911     LOG_INFO(BSL_LS_SOC_PHY,
   2912              (BSL_META_U(unit,
   2913                          "82328 polarity flip: u=%d p%d TX=%x RX=%x\n"), unit, port, 
   2914                          cfg_tx_pol, cfg_rx_pol));
   2915     if (cfg_tx_pol != PHY82328_POL_DND) {
   2916         SOC_IF_ERROR_RETURN(
   2917             _phy_82328_polarity_flip_tx(unit, port, PHY82328_INTF_SIDE_LINE, cfg_tx_pol));
   2918     }
   2919     if (cfg_rx_pol != PHY82328_POL_DND) {
   2920         SOC_IF_ERROR_RETURN(
   2921             _phy_82328_polarity_flip_rx(unit, port, PHY82328_INTF_SIDE_LINE, cfg_rx_pol));
   2922     }
   2923 
   2924     return SOC_E_NONE;
   2925 }
   2926 
   2927 STATIC void
   2928 _phy_82328_micro_pause(int32 unit, soc_port_t port, const char *loc)
   2929 {
   2930     int32 rv = SOC_E_NONE;
   2931     uint16 data, mask;
   2932     int32 checks;
   2933     uint16 csr;
   2934     uint16 saved_side;
   2935     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   2936     phy82328_micro_ctrl_t *micro_ctrl = &(MICRO_CTRL(pc));
   2937 
   2938     if (!micro_ctrl->enable) {
   2939         return;
   2940     }
   2941 
   2942     /* Access line side registers */
   2943     saved_side = _phy_82328_intf_side_regs_get(unit, port);
   2944     if (saved_side == PHY82328_INTF_SIDE_SYS) {
   2945         WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL,PHY82328_INTF_SIDE_LINE);
   2946     }
   2947 
   2948     micro_ctrl->count++;
   2949     
   2950     /* Quiet micro */
   2951     data = 0;
   2952     mask = 0xff00;
   2953     rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, data, mask);
   2954     if (rv != SOC_E_NONE) {
   2955         goto fail;
   2956     }
   2957     sal_udelay(500);
   2958     checks = 0;
   2959     while (checks < 1000) {
   2960         /* Make sure micro really paused */
   2961         rv = READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_2, &data);
   2962         if (rv != SOC_E_NONE) {
   2963             goto fail;
   2964         }
   2965         if ((data & mask) == 0) {
   2966             break;
   2967         }
   2968         sal_udelay(100);
   2969         checks++;
   2970     }
   2971     if (data & mask) {
   2972         rv = READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, &csr);
   2973         if (rv != SOC_E_NONE) {
   2974             goto fail;
   2975         }
   2976         LOG_INFO(BSL_LS_SOC_PHY,
   2977                  (BSL_META_U(unit,
   2978                              "82328 microcode did not pause in %s: "
   2979                              "u=%d p%d 1.ca18/1.ca19=%04x/%04x checks=%d\n"), 
   2980                   loc, unit, port, csr, data, checks));
   2981     }
   2982 
   2983 fail:
   2984     if (saved_side != PHY82328_INTF_SIDE_LINE) {
   2985         WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, saved_side);
   2986     }
   2987     return;
   2988 }
   2989 
   2990 STATIC void
   2991 _phy_82328_micro_resume(int32 unit, soc_port_t port)
   2992 {
   2993     phy82328_intf_side_t saved_side;
   2994     int32 rv = SOC_E_NONE;
   2995     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   2996     phy82328_micro_ctrl_t *micro_ctrl = &(MICRO_CTRL(pc));
   2997 
   2998     if (!micro_ctrl->enable) {
   2999         return;
   3000     }
   3001 
   3002     /* Access line side registers */
   3003     saved_side = _phy_82328_intf_side_regs_get(unit, port);
   3004     if (saved_side == PHY82328_INTF_SIDE_SYS) {
   3005         WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, PHY82328_INTF_SIDE_LINE);
   3006 	}
   3007 
   3008     micro_ctrl->count--;
   3009     if (micro_ctrl->count <= 0) {
   3010         rv = MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, 
   3011                                              0xff00, 0xff00);
   3012         if (rv != SOC_E_NONE) {
   3013             goto fail;
   3014         }
   3015         if (micro_ctrl->count < 0) {
   3016             LOG_VERBOSE(BSL_LS_SOC_PHY,
   3017                         (BSL_META_U(unit,
   3018                                     "82328 unmatched micro resume\n")));
   3019             micro_ctrl->count = 0;;
   3020         }
   3021     }
   3022 
   3023 fail:
   3024     if (saved_side != PHY82328_INTF_SIDE_LINE) {
   3025         WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, saved_side);
   3026     }
   3027     return;
   3028 }
   3029 
   3030 /*
   3031  * Function:
   3032  *      phy_82328_an_set
   3033  * Purpose:
   3034  *      Configures auto-negotiation 
   3035  *      Parameters:
   3036  *      unit - StrataSwitch unit #.
   3037  *      port - StrataSwitch port #.
   3038  *      enable   - if true, auto-negotiation is enabled.
   3039  * Returns:
   3040  *      SOC_E_XXX
   3041  */
   3042 
   3043 STATIC int32
   3044 phy_82328_an_set(int32 unit, soc_port_t port, int32 an)
   3045 {
   3046 	int32 dev_an, dev_an_done;
   3047 	phy_ctrl_t  *pc, *int_pc;
   3048 	phy82328_intf_cfg_t  *line_intf;
   3049 
   3050 	pc = EXT_PHY_SW_STATE(unit, port);
   3051     int_pc = INT_PHY_SW_STATE(unit, port);
   3052 	line_intf = &(LINE_INTF(pc));
   3053 
   3054     LOG_INFO(BSL_LS_SOC_PHY,
   3055              (BSL_META_U(unit,
   3056                          "phy_82328_an_set: u=%d p=%d an=%s\n"),
   3057               unit, port, an ? "enable" : "disable"));
   3058 
   3059 	/*
   3060 	 * Determining line side AN status 
   3061 	 *  SR/LR/SR4/LR4/SR2: no AN 
   3062 	 *  KR/KR4/KR2: line side: cl73/cl72, system side as forced cl72
   3063 	 *  CR4/CR: AN enabled in FW, to disable set interface to 40G CR4 DAC(aka XLAUI_DFE), otherwise, CR4
   3064 	 *  GMII: AN handled by internal SerDes
   3065 	 */
   3066 	switch (line_intf->type) {
   3067 	    case SOC_PORT_IF_GMII:
   3068         case SOC_PORT_IF_SGMII:
   3069 	        AN_EN(pc) = an;
   3070             SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an));
   3071 		break;
   3072 	    case SOC_PORT_IF_KX:
   3073         case SOC_PORT_IF_KR:
   3074         case SOC_PORT_IF_KR4:
   3075            AN_EN(pc) = 1;
   3076 		break;
   3077         case SOC_PORT_IF_CR4:
   3078            AN_EN(pc) = an;
   3079 		break;
   3080         default:
   3081 		    /* Interface does not support AN in the firmware so it's always forced */
   3082             AN_EN(pc) = FALSE;
   3083 	}
   3084 	SOC_IF_ERROR_RETURN(_phy_82328_intf_type_set(unit, port, line_intf->type, TRUE));
   3085 
   3086     /* If not passtrhu an, make sure firmware has enabled an */
   3087     if (line_intf->speed > 1000) {
   3088         SOC_IF_ERROR_RETURN(phy_82328_an_get(unit, port, &dev_an, &dev_an_done));
   3089         if (dev_an != AN_EN(pc)) {
   3090             LOG_ERROR(BSL_LS_SOC_PHY,
   3091                       (BSL_META_U(unit,
   3092                                   "82328 device autonegotiation mismatch: u=%d p=%d an=%s\n"),
   3093                        unit, port, AN_EN(pc) ? "en" : "dis"));
   3094         }
   3095     }
   3096     return SOC_E_NONE;
   3097 }
   3098 
   3099 /*
   3100  * Function:
   3101  *      phy_82328_an_get
   3102  * Purpose:
   3103  *      Get the current auto-negotiation status (enabled/busy)
   3104  * Parameters:
   3105  *      unit - StrataSwitch unit #.
   3106  *      port - StrataSwitch port #.
   3107  *      an   - (OUT) if true, auto-negotiation is enabled.
   3108  *      an_done - (OUT) if true, auto-negotiation is complete. This
   3109  *              value is undefined if an == false.
   3110  * Returns:
   3111  *      SOC_E_XXX
   3112  */
   3113  
   3114 STATIC int32
   3115 phy_82328_an_get(int32 unit, soc_port_t port, int32 *an, int32 *an_done)
   3116 {
   3117     uint16 data16 = 0;
   3118     phy_ctrl_t  *pc, *int_pc;
   3119     phy82328_intf_cfg_t  *line_intf;
   3120 
   3121 	pc = EXT_PHY_SW_STATE(unit, port);
   3122     int_pc = INT_PHY_SW_STATE(unit, port);
   3123 	line_intf = &(LINE_INTF(pc));
   3124 
   3125 	if ((line_intf->type == SOC_PORT_IF_GMII) || (line_intf->type == SOC_PORT_IF_SGMII)) {
   3126 		SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, an, an_done));
   3127 	} else {   
   3128         SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_AN_REG(unit, pc,
   3129                                      PHY82328_AN_CTRL_REG, &data16));
   3130         *an = ((data16 & PHY82328_AN_ENABLE_MSK) == PHY82328_AN_ENABLE_MSK);
   3131         LOG_INFO(BSL_LS_SOC_PHY,
   3132                  (BSL_META_U(unit,
   3133                              "PHY82328: AN Enable: 0x%x\n"),data16));
   3134         if (*an) {
   3135             SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_AN_REG(unit, pc,
   3136                                PHY82328_AN_STS_REG, &data16));
   3137 
   3138             LOG_INFO(BSL_LS_SOC_PHY,
   3139                      (BSL_META_U(unit,
   3140                                  "PHY82328 AN Done: 0x%x\n"),data16));
   3141            *an_done = ((data16 & PHY82328_AN_COMPLETE_MSK) == PHY82328_AN_COMPLETE_MSK);
   3142         }
   3143     }
   3144 
   3145     return SOC_E_NONE;
   3146 }
   3147 
   3148 /*
   3149  * Squelch/unsquelch tx in 1.reg.bit
   3150  */
   3151 STATIC int32
   3152 _phy_82328_tx_squelch_enable(int32 unit, soc_port_t port, phy82328_intf_side_t side, uint8 squelch)
   3153 {
   3154     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   3155 
   3156     SOC_IF_ERROR_RETURN( 
   3157           _phy_82328_modify_pma_pmd_reg (unit, port, pc, 
   3158            PHY82328_DEV_PMA_PMD,  TX_ANATXACONTROL7, 
   3159            QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_EN_SM_SHIFT,
   3160            QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_EN_SM_SHIFT, 1));
   3161  
   3162     SOC_IF_ERROR_RETURN( 
   3163           _phy_82328_modify_pma_pmd_reg (unit, port, pc, 
   3164            PHY82328_DEV_PMA_PMD,  TX_ANATXACONTROL7, 
   3165            QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_VAL_SM_SHIFT, 
   3166            QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_VAL_SM_SHIFT, squelch? 1:0));
   3167 
   3168     return SOC_E_NONE;
   3169 }
   3170 
   3171 STATIC int32
   3172 _phy_82328_tx_squelch(int32 unit, soc_port_t port, phy82328_intf_side_t side, int32 cfg_sql)
   3173 {
   3174     uint8  squelch = 0;
   3175     int32	lane = 0;
   3176     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3177 	
   3178     SOC_IF_ERROR_RETURN(
   3179      phy82328_intf_side_reg_select(unit, port, side));
   3180     if (PHY82328_SINGLE_PORT_MODE(pc)) {
   3181         for (lane = 0; lane < PHY82328_NUM_LANES; lane++) {
   3182             /* Check for all lanes or whether this lane has to be squelched */
   3183             if(cfg_sql & (1<<lane)){
   3184                 squelch = 1;
   3185             } else {
   3186                 squelch = 0;
   3187             }
   3188             LOG_INFO(BSL_LS_SOC_PHY,
   3189                      (BSL_META_U(unit,
   3190                                  "82328 tx squelch=%d: u=%d p=%d lane=%d\n"), squelch, unit, port, lane));
   3191 
   3192             /* Select the lane on the line side */
   3193             SOC_IF_ERROR_RETURN(_phy_82328_channel_select (unit, port, side, lane));
   3194             SOC_IF_ERROR_RETURN(_phy_82328_tx_squelch_enable (unit, port, side, squelch));
   3195         }
   3196         /* Restore to default single port register access */
   3197         SOC_IF_ERROR_RETURN(_phy_82328_channel_select (unit, port, PHY82328_INTF_SIDE_LINE, PHY82328_ALL_LANES));
   3198     } 
   3199     else {  
   3200         squelch = (cfg_sql) ? 1 : 0;
   3201         SOC_IF_ERROR_RETURN(_phy_82328_tx_squelch_enable (unit, port, side, squelch));
   3202         LOG_INFO(BSL_LS_SOC_PHY,
   3203                  (BSL_META_U(unit,
   3204                              "82328 squelch %s side: u=%d p=%d \n"),
   3205                   side ? "SYSTEM" : "LINE", unit, port));
   3206     }
   3207 
   3208     if (side != PHY82328_INTF_SIDE_LINE) {
   3209         SOC_IF_ERROR_RETURN(
   3210          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   3211     }
   3212     return SOC_E_NONE;
   3213 }
   3214 
   3215 /*
   3216  * Function:
   3217  *    _phy_82328_remote_loopback_get
   3218  * Purpose:
   3219  *    Get 82328 PHY loopback state
   3220  * Parameters:
   3221  *    unit - StrataSwitch unit #.
   3222  *    port - StrataSwitch port #.
   3223  *    enable - (OUT) address of location to store binary value for on/off (1/0)
   3224  * Returns:
   3225  *    SOC_E_NONE
   3226  */ 
   3227  STATIC int32
   3228 _phy_82328_remote_loopback_get(int32 unit, soc_port_t port, uint32 *enable)
   3229 {
   3230     uint16 read_data=0,ret_val = 1;
   3231     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3232 		
   3233     /* Remote Loop Back Set <Line Side>*/
   3234     SOC_IF_ERROR_RETURN(
   3235      phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   3236 
   3237     /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/
   3238     SOC_IF_ERROR_RETURN
   3239         (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3240                   TLB_TX_RMT_LPBK_CONFIG, &read_data));	
   3241 
   3242     read_data &=TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK;
   3243     read_data = read_data >> TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_SHIFT;
   3244     ret_val &=read_data;		
   3245     
   3246     /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/		
   3247     SOC_IF_ERROR_RETURN
   3248         (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3249                 TX_PI_TX_PI_CONTROL_5, &read_data));
   3250 
   3251     read_data &=TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK;
   3252     read_data = read_data >> TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_SHIFT;
   3253     ret_val &=(!read_data);													 
   3254     
   3255     /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/
   3256     SOC_IF_ERROR_RETURN
   3257         (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3258                  TX_PI_TX_PI_CONTROL_0, &read_data));
   3259     read_data &=TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK;
   3260     read_data = read_data >> TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_SHIFT;
   3261     ret_val &=read_data;
   3262 		
   3263     *enable = ret_val;		
   3264     return SOC_E_NONE;
   3265 }
   3266 
   3267 /*
   3268  * Function:
   3269  *    _phy_82328_remote_loopback_set
   3270  * Purpose:
   3271  *    Get 82328 PHY loopback state
   3272  * Parameters:
   3273  *    unit - StrataSwitch unit #.
   3274  *    port - StrataSwitch port #.
   3275  *    enable - address of location to store binary value for on/off (1/0)
   3276  * Returns:
   3277  *    SOC_E_NONE
   3278  */
   3279  STATIC int32
   3280 _phy_82328_remote_loopback_set(int32 unit,soc_port_t port,int32 enable)
   3281 {
   3282     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3283 
   3284     /* Loopback requires 20-bit datapath */	
   3285     if (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20) {
   3286         return SOC_E_RESOURCE;
   3287     }
   3288 
   3289     /* Remote LoopBk Set <Line Side>*/
   3290     SOC_IF_ERROR_RETURN(
   3291      phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   3292         SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3293                  MGT_TOP_GP_REG_0,
   3294                  (enable << MGT_TOP_CMN_CTLR_GP_REG_0_DISABLE_TX_SQUELCHING_SHIFT),
   3295                  MGT_TOP_CMN_CTLR_GP_REG_0_DISABLE_TX_SQUELCHING_MASK));
   3296  
   3297         if (enable) {
   3298             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3299                                                       TX_ANATXACONTROL7, 0,
   3300                                                       QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_VAL_SM_MASK));
   3301 
   3302             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3303                                                       TX_ANATXACONTROL7, 0,
   3304                                                       QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_EN_SM_MASK));
   3305 
   3306             /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/
   3307             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3308                                                                 TLB_TX_RMT_LPBK_CONFIG,
   3309                                                                 (1<<TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_SHIFT), 
   3310                                                                 TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK));
   3311             /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/		
   3312             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3313                                                                 TX_PI_TX_PI_CONTROL_5,
   3314                                                                 0, 
   3315                                                                 TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK));
   3316             sal_udelay(100);
   3317             /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/
   3318             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3319                                                                 TX_PI_TX_PI_CONTROL_0,
   3320                                                                 (1<<TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_SHIFT), 
   3321                                                                 TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK));				
   3322             SOC_IF_ERROR_RETURN
   3323                  (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 
   3324                                                  PHY82328_DEV_PMA_PMD, TX_PI_TX_PI_CONTROL_0,
   3325                                                  TX_PI_TX_PI_CONTROL_0_TX_PI_LOOP_TIMING_EN_SHIFT,
   3326                                                  TX_PI_TX_PI_CONTROL_0_TX_PI_EN_SHIFT, 0x3));
   3327         } else {
   3328             /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/
   3329             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3330                                                                 TLB_TX_RMT_LPBK_CONFIG,
   3331                                                                 0, 
   3332                                                                 TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK));
   3333             /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/		
   3334             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3335                                                                 TX_PI_TX_PI_CONTROL_5,
   3336                                                                 (1<<TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_SHIFT), 
   3337                                                                 TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK));
   3338             sal_udelay(100);
   3339             /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/
   3340             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3341                                                                 TX_PI_TX_PI_CONTROL_0,
   3342                                                                 0, 
   3343                                                                 TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK));	
   3344         }
   3345     return SOC_E_NONE;
   3346 }
   3347 
   3348 /*
   3349  * Function:
   3350  *    phy_82328_lb_get
   3351  * Purpose:
   3352  *    Get 82328 PHY loopback state
   3353  * Parameters:
   3354  *    unit - StrataSwitch unit #.
   3355  *    port - StrataSwitch port #.
   3356  *    enable - (OUT) address of location to store binary value for on/off (1/0)
   3357  * Returns:
   3358  *    SOC_E_NONE
   3359  */ 
   3360 STATIC int32
   3361 phy_82328_lb_get(int32 unit, soc_port_t port, int32 *enable)
   3362 {
   3363     uint16 read_data=0,ret_val=1;		
   3364     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3365 
   3366     *enable = 0xFFFF;	
   3367     /* LB Set API Supports System Side*/
   3368     SOC_IF_ERROR_RETURN(
   3369      phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS));
   3370 
   3371         /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/
   3372         SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG (unit, pc,
   3373                          TLB_TX_RMT_LPBK_CONFIG, &read_data));
   3374     
   3375         read_data &=TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK;
   3376         read_data = read_data >> TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_SHIFT;
   3377 	    ret_val &=read_data;
   3378     
   3379         /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/
   3380         SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3381                                   TX_PI_TX_PI_CONTROL_5, &read_data));
   3382 
   3383         read_data &=TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK;
   3384         read_data = read_data >> TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_SHIFT;
   3385         ret_val &=(!read_data);
   3386 
   3387         /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/
   3388 
   3389         SOC_IF_ERROR_RETURN (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3390                             TX_PI_TX_PI_CONTROL_0, &read_data));
   3391 
   3392         read_data &=TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK;
   3393         read_data = read_data >> TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_SHIFT;
   3394         ret_val &=read_data;
   3395         
   3396         *enable &= ret_val;
   3397 
   3398     SOC_IF_ERROR_RETURN(
   3399        phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   3400     return SOC_E_NONE;
   3401 }
   3402 
   3403 
   3404 STATIC int32
   3405 phy_82328_lb_set(int32 unit, soc_port_t port, int32 enable)
   3406 {
   3407     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3408 
   3409     /* Loopback requires 20-bit datapath */	
   3410     if (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20) {
   3411         return SOC_E_RESOURCE;
   3412     }
   3413      /* LB Set API Supports System Side*/
   3414         SOC_IF_ERROR_RETURN(
   3415          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS));
   3416 
   3417         SOC_IF_ERROR_RETURN
   3418             (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, PHY82328_INTF_SIDE_LINE));
   3419         SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3420              MGT_TOP_GP_REG_0,
   3421              (enable << MGT_TOP_CMN_CTLR_GP_REG_0_DISABLE_TX_SQUELCHING_SHIFT),
   3422              MGT_TOP_CMN_CTLR_GP_REG_0_DISABLE_TX_SQUELCHING_MASK));
   3423         
   3424         SOC_IF_ERROR_RETURN
   3425             (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_XPMD_REGS_SEL, PHY82328_INTF_SIDE_SYS));
   3426 
   3427         if (enable) {
   3428             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3429                                                   TX_ANATXACONTROL7, 0,
   3430                                                   QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_VAL_SM_MASK));
   3431 
   3432             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3433                                                   TX_ANATXACONTROL7, 0,
   3434                                                   QSFI_TX_ANATXACONTROL7_TX_DISABLE_FORCE_EN_SM_MASK));
   3435              SOC_IF_ERROR_RETURN
   3436              (_phy_82328_modify_pma_pmd_reg (unit, port, pc, 
   3437                                              PHY82328_DEV_PMA_PMD, TX_PI_TX_PI_CONTROL_0,
   3438                                              TX_PI_TX_PI_CONTROL_0_TX_PI_LOOP_TIMING_EN_SHIFT,
   3439                                              TX_PI_TX_PI_CONTROL_0_TX_PI_EN_SHIFT, 0x3));
   3440 
   3441             /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/
   3442             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3443                                                             TLB_TX_RMT_LPBK_CONFIG,
   3444                                                             (1<<TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_SHIFT), 
   3445                                                             TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK));
   3446             sal_udelay(100);
   3447             /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/		
   3448             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3449                                                             TX_PI_TX_PI_CONTROL_5,
   3450                                                             0, 
   3451                                                             TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK));
   3452 
   3453             /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/
   3454             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3455                                                             TX_PI_TX_PI_CONTROL_0,
   3456                                                             (1<<TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_SHIFT),
   3457                                                             TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK));
   3458         } else {
   3459             /*1 rmt_lpbk_config.rmt_lpbk_en 1.D0E2.0 1*/
   3460             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3461                                                             TLB_TX_RMT_LPBK_CONFIG,
   3462                                                             0, 
   3463                                                             TLB_TX_RMT_LPBK_CONFIG_RMT_LPBK_EN_MASK));
   3464             /*2 tx_pi_control_5.tx_pi_pass_thru_sel 1.D075.2 0*/		
   3465             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3466                                                             TX_PI_TX_PI_CONTROL_5,
   3467                                                             (1<<TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_SHIFT), 
   3468                                                             TX_PI_TX_PI_CONTROL_5_TX_PI_PASS_THRU_SEL_MASK));
   3469             sal_udelay(100);
   3470             /*3 tx_pi_control_0.tx_pi_ext_ctrl_en 1.D070.2 1*/
   3471             SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3472                                                             TX_PI_TX_PI_CONTROL_0,
   3473                                                             0, 
   3474                                                             TX_PI_TX_PI_CONTROL_0_TX_PI_EXT_CTRL_EN_MASK));	
   3475         }
   3476     SOC_IF_ERROR_RETURN(
   3477      phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   3478     return SOC_E_NONE;
   3479 }
   3480 
   3481 STATIC int32
   3482 _phy_82328_intf_type_set(int32 unit, soc_port_t port, soc_port_if_t pif, int32 must_update)
   3483 {
   3484     int32			rv = SOC_E_NONE;
   3485     phy_ctrl_t      *pc = EXT_PHY_SW_STATE(unit, port);
   3486     phy82328_intf_cfg_t *line_intf;
   3487     int32			update = 0;
   3488     uint16          reg_data = 0, reg_mask = 0;
   3489     uint16          data = 0, mask = 0;
   3490 
   3491     line_intf = &(LINE_INTF(pc));
   3492 	
   3493     reg_data = 0;
   3494     reg_mask = 0;
   3495 
   3496     if (_phy_82328_intf_is_single_port(pif)) {
   3497         if (!PHY82328_SINGLE_PORT_MODE(pc)) {
   3498             LOG_ERROR(BSL_LS_SOC_PHY,
   3499                       (BSL_META_U(unit,
   3500                                   "82328 invalid interface for quad port: u=%d p=%d\n"),
   3501                                   unit, port));
   3502             return SOC_E_CONFIG;
   3503         }
   3504         /* 
   3505          * If rx polarity is flipped and the interface is CR4, then change the datapath
   3506          * to 20-bit as rx polarity cannot be handle on the line side in 4-bit
   3507          */
   3508         if (pif == SOC_PORT_IF_CR4) {
   3509             if (AN_EN(pc)) {
   3510                 if (POL_RX_CFG(pc) && (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20)) {
   3511                     CUR_DATAPATH(pc) = PHY82328_DATAPATH_20;
   3512                     update = 1;
   3513                 }
   3514             } else if (CUR_DATAPATH(pc) != CFG_DATAPATH(pc)) {
   3515                 CUR_DATAPATH(pc) = CFG_DATAPATH(pc);
   3516                 update = 1;
   3517             }
   3518             SOC_IF_ERROR_RETURN(
   3519                 _phy_82328_intf_datapath_reg_get(unit, port, CUR_DATAPATH(pc), &data, &mask));
   3520             reg_data |= data;
   3521             reg_mask |= mask;
   3522         }
   3523         if ((pif != line_intf->type) || must_update) {
   3524             update = 1;
   3525         }
   3526     } else if (_phy_82328_intf_is_quad_port(pif)) {
   3527         if (PHY82328_SINGLE_PORT_MODE(pc)) {
   3528             LOG_ERROR(BSL_LS_SOC_PHY,
   3529                       (BSL_META_U(unit,
   3530                                   "82328 invalid interface for single port: u=%d p=%d\n"),
   3531                                   unit, port));
   3532             return SOC_E_CONFIG;
   3533         }
   3534 
   3535         if ((line_intf->type != pif) || must_update) {
   3536             update = 1;
   3537             SOC_IF_ERROR_RETURN(
   3538                _phy_82328_intf_type_reg_get(unit, port, pif, PHY82328_INTF_SIDE_LINE,
   3539                                            &reg_data, &reg_mask));
   3540         }
   3541     } else {
   3542         LOG_ERROR(BSL_LS_SOC_PHY,
   3543                   (BSL_META_U(unit,
   3544                               "82328 invalid interface for port: u=%d p=%d intf=%d\n"),
   3545                               unit, port, pif));
   3546         return SOC_E_CONFIG;
   3547     }
   3548     if (update) {
   3549         line_intf->type = pif;
   3550         SOC_IF_ERROR_RETURN(
   3551             _phy_82328_intf_type_reg_get(unit, port, pif, PHY82328_INTF_SIDE_LINE,
   3552                                              &data, &mask));
   3553         reg_data |= data;
   3554         reg_mask |= mask;
   3555         SOC_IF_ERROR_RETURN(_phy_82328_intf_update(unit, port, reg_data, reg_mask));
   3556     }
   3557     return rv;
   3558 }
   3559 
   3560 STATIC int32
   3561 _phy_82328_intf_line_forced(int32 unit, soc_port_t port, soc_port_if_t intf_type)
   3562 {
   3563     int32 rv;
   3564     switch (intf_type) {
   3565         case SOC_PORT_IF_SR:
   3566         case SOC_PORT_IF_SR4:
   3567         case SOC_PORT_IF_LR:
   3568         case SOC_PORT_IF_ZR:
   3569         case SOC_PORT_IF_LR4:
   3570         case SOC_PORT_IF_XLAUI:
   3571         case SOC_PORT_IF_XFI:
   3572         case SOC_PORT_IF_SFI:
   3573         case SOC_PORT_IF_CR:
   3574             rv = TRUE;
   3575         break;
   3576         default:
   3577             rv = FALSE;
   3578     }
   3579     return rv;
   3580 }
   3581 
   3582 /*
   3583  * Function:
   3584  *      phy_82328_interface_set
   3585  * Purpose:
   3586  *
   3587  *
   3588  * Parameters:
   3589  *      unit - StrataSwitch unit #.
   3590  *      port - StrataSwitch port #.
   3591  *      pif - one of SOC_PORT_IF_*
   3592  * Returns:
   3593  *      SOC_E_NONE - success
   3594  *      SOC_E_UNAVAIL - unsupported interface
   3595  */
   3596  
   3597 STATIC int32
   3598 phy_82328_interface_set(int32 unit, soc_port_t port, soc_port_if_t pif)
   3599 {
   3600     int32 rv;
   3601 
   3602     LOG_CLI((BSL_META_U(unit,
   3603                         "82328 interface set: u=%d p=%d pif=%s\n"), 
   3604              unit, port, phy82328_intf_names[pif]));
   3605 
   3606     if (pif == SOC_PORT_IF_XGMII) {
   3607         return phy_null_interface_set(unit, port, pif);
   3608     }
   3609 
   3610     rv = _phy_82328_intf_type_set(unit, port, pif, FALSE);
   3611     if (SOC_FAILURE(rv)) {
   3612         LOG_INFO(BSL_LS_SOC_PHY,
   3613                  (BSL_META_U(unit,
   3614                              "82328  interface set check failed: u=%d p=%d\n"),
   3615                              unit, port));
   3616     }
   3617     if (_phy_82328_intf_line_forced(unit, port, pif)) {
   3618         SOC_IF_ERROR_RETURN(phy_82328_an_set(unit, port, 0));
   3619     }
   3620     return SOC_E_NONE;
   3621 }
   3622 
   3623 /*
   3624  * Function:
   3625  *      phy_82328_interface_get
   3626  * Purpose:
   3627  *      Get the current operating mode of the PHY.
   3628  * Parameters:
   3629  *      unit - StrataSwitch unit #.
   3630  *      port - StrataSwitch port #.
   3631  *      pif - (OUT) one of SOC_PORT_IF_*
   3632  * Returns:
   3633  *      SOC_E_NONE
   3634  */
   3635 STATIC int32
   3636 phy_82328_interface_get(int32 unit, soc_port_t port, soc_port_if_t *pif)
   3637 {
   3638     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3639     phy82328_intf_cfg_t *line_intf;
   3640 
   3641     line_intf = &(LINE_INTF(pc));
   3642     *pif = line_intf->type;
   3643 
   3644     return SOC_E_NONE;
   3645 }
   3646 
   3647 STATIC int32
   3648 _phy_82328_micro_tx_squelch_enable(int32 unit, soc_port_t port, int32 enable)
   3649 {
   3650     uint16 data;
   3651     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3652 
   3653     /* 1.ca18[7] 0=micro squelching enabled, 1=micro squelching disabled */
   3654     data = enable ? 0 : 0x80;
   3655         SOC_IF_ERROR_RETURN(
   3656                 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, data, 0x80));
   3657     return SOC_E_NONE;
   3658 }
   3659 
   3660 /*
   3661  * Function:
   3662  *      _phy_82328_control_prbs_enable_set
   3663  * Purpose:
   3664  *      Get the current operating mode of the PHY.
   3665  * Parameters:
   3666  *      unit - StrataSwitch unit #.
   3667  *      port - StrataSwitch port #.
   3668  *      enable - PRBS Generator Enable
   3669  * Returns:
   3670  *      SOC_E_NONE
   3671  */
   3672 STATIC int32
   3673 _phy_82328_control_prbs_enable_set(int32 unit, soc_port_t port, int32 enable)
   3674 {
   3675     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3676 
   3677     /* PRBS requires 20-bit datapath */	
   3678     if (CUR_DATAPATH(pc) != PHY82328_DATAPATH_20) {
   3679         return SOC_E_RESOURCE;
   3680     }
   3681         /* Disable Prbs Gen/Chkr First -> Refer Programming Guide 1.2*/
   3682         /* Disable Prbs Gen in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.1 */
   3683         SOC_IF_ERROR_RETURN
   3684 
   3685             (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3686                    TLB_TX_PRBS_GEN_CONFIG, 0, TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_EN_MASK));
   3687 	    														
   3688         /* Disable Prbs Chkr in in TLB_RX_PRBS_CHK_CONFIG 1.D0D1.0*/	  
   3689         SOC_IF_ERROR_RETURN
   3690             (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 
   3691                    TLB_RX_PRBS_CHK_CONFIG, 0, TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_EN_MASK));
   3692 
   3693         if (enable) {
   3694             /* Enable Prbs Gen in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.0 */
   3695             /*PRBS Gen Enable*/
   3696             SOC_IF_ERROR_RETURN(
   3697                 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TLB_TX_PRBS_GEN_CONFIG,
   3698                     (1 << TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_EN_SHIFT), 
   3699                     TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_EN_MASK));
   3700 	    			
   3701             /*Prbs Checker En in TLB_RX_PRBS_CHK_CONFIG 1.D0D1.0*/
   3702             /*PRBS Chk Enable*/
   3703             SOC_IF_ERROR_RETURN (
   3704                MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   3705                 TLB_RX_PRBS_CHK_CONFIG, (1 << TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_EN_SHIFT), 
   3706                 TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_EN_MASK));
   3707         }
   3708     /*
   3709      * If enabling prbs
   3710      *    disable micro tx squelch updates
   3711      *    unsquelch tx system
   3712      * else
   3713      *    enable micro tx squelch updates
   3714      */
   3715     SOC_IF_ERROR_RETURN(_phy_82328_micro_tx_squelch_enable(unit, port, !enable));
   3716     if (enable) {
   3717         SOC_IF_ERROR_RETURN(_phy_82328_tx_squelch(unit, port, PHY82328_INTF_SIDE_SYS, 0));
   3718     }
   3719     return SOC_E_NONE;
   3720 }
   3721 
   3722 /*
   3723  * Function:
   3724  *      _phy_82328_control_prbs_invert_data_set
   3725  * Purpose:
   3726  *      Get the current operating mode of the PHY.
   3727  * Parameters:
   3728  *      unit - StrataSwitch unit #.
   3729  *      port - StrataSwitch port #.
   3730  *      invert - PRBS Invert
   3731  * Returns:
   3732  *      SOC_E_NONE
   3733  */
   3734 STATIC int32
   3735 _phy_82328_control_prbs_invert_data_set(int32 unit, soc_port_t port, int32 invert)
   3736 {
   3737     uint16          data;
   3738     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3739  
   3740     data = invert ? (1 << TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_INV_SHIFT):0;
   3741         /*PRBS Gen Invert*/
   3742         SOC_IF_ERROR_RETURN(
   3743             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 
   3744                   TLB_TX_PRBS_GEN_CONFIG, data,
   3745                   TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_INV_MASK));
   3746 
   3747         /*PRBS Chk Invert*/
   3748         SOC_IF_ERROR_RETURN(
   3749              MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 
   3750                     TLB_RX_PRBS_CHK_CONFIG, data,
   3751                     TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_INV_MASK));
   3752     return SOC_E_NONE;
   3753 }
   3754 
   3755 /*
   3756  * Function:
   3757  *      _phy_82328_control_prbs_polynomial_set
   3758  * Purpose:
   3759  *      Get the current operating mode of the PHY.
   3760  * Parameters:
   3761  *      unit - StrataSwitch unit #.
   3762  *      port - StrataSwitch port #.
   3763  *      polynomial - PRBS Polynomial
   3764  *       0==prbs7, 
   3765  *       1==prbs=15 
   3766  *       2==prbs=23 
   3767  *       3==prbs=31 
   3768  *
   3769  * Returns:
   3770  *      SOC_E_NONE
   3771  */
   3772 STATIC int32
   3773 _phy_82328_control_prbs_polynomial_set(int32 unit, soc_port_t port, int32 polynomial)
   3774 {
   3775     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3776  
   3777     LOG_INFO(BSL_LS_SOC_PHY,
   3778              (BSL_META_U(unit,
   3779                          "82328  prbs polynomial set: u=%d p=%d polynomial=%d\n"),
   3780                          unit, port, polynomial));
   3781     switch(polynomial) {
   3782         case 0: /* PRBS 7*/
   3783             polynomial = 0;
   3784             break;
   3785         case 1: /*PRBS15*/
   3786             polynomial = 3;
   3787             break;
   3788         case 2:/*PRBS23*/
   3789             polynomial = 4;
   3790             break;
   3791         case 3:/*PRBS31*/
   3792             polynomial = 5;
   3793             break;
   3794         case 4:/*PRBS 9*/
   3795             polynomial = 1;
   3796             break;
   3797         case 5:/*PRBS 11*/
   3798             polynomial = 2;
   3799             break;
   3800         case 6: /*PRBS58*/
   3801             polynomial = 6;
   3802             break;
   3803         default:
   3804             return SOC_E_PARAM;
   3805     }
   3806         /* Prbs Polynomial in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.[3:1] */
   3807         /*Set Gen Poly*/
   3808         SOC_IF_ERROR_RETURN(
   3809             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TLB_TX_PRBS_GEN_CONFIG,
   3810                     (polynomial << TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_MODE_SEL_SHIFT),
   3811                     TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_MODE_SEL_MASK));
   3812 	    	
   3813         /*Prbs Polynomial in TLB_RX_PRBS_CHK_CONFIG 1.D0D1.[3:1]*/
   3814         /*Set Checker Poly*/
   3815         SOC_IF_ERROR_RETURN(
   3816              MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TLB_RX_PRBS_CHK_CONFIG,
   3817                (polynomial << TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_MODE_SEL_SHIFT),
   3818                TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_MODE_SEL_MASK));
   3819 
   3820     return SOC_E_NONE;
   3821 }
   3822 
   3823 
   3824 int32 phy82328_validate_preemphasis(uint8 pre, uint8 main, uint8 post1, uint8 post2) 
   3825 {
   3826     uint8 post2to1 = (post2==0);
   3827     if (pre > 10) {
   3828         LOG_ERROR(BSL_LS_SOC_PHY,
   3829                   (BSL_META("Invalid PRE CURSOR TAP. It should be less than 10\n")));
   3830         return SOC_E_PARAM;
   3831     }
   3832     if (main > 60) {
   3833         LOG_ERROR(BSL_LS_SOC_PHY,
   3834                   (BSL_META("Invalid MAIN CURSOR TAP. It should be less than 60\n")));
   3835         return SOC_E_PARAM;
   3836     }
   3837     if ((!post2to1) && (post1 > 18)) {
   3838         LOG_ERROR(BSL_LS_SOC_PHY,
   3839                   (BSL_META("Invalid POST1 CURSOR TAP. It should be less than 18\n")));
   3840         return SOC_E_PARAM;
   3841     }
   3842     if ((post2to1) && (post1 > 23)) {
   3843         LOG_ERROR(BSL_LS_SOC_PHY,
   3844                   (BSL_META("Invalid POST1 CURSOR TAP. It should be less than 23\n")));
   3845         return SOC_E_PARAM;
   3846     }
   3847     if (post2 > 5) {
   3848         LOG_ERROR(BSL_LS_SOC_PHY,
   3849                   (BSL_META("Invalid POST2 TAP. It should be less than 5\n")));
   3850         return SOC_E_PARAM;
   3851     }
   3852     if (main < (pre + post1 + post2 + 1)) {
   3853         LOG_ERROR(BSL_LS_SOC_PHY,
   3854                   (BSL_META("Invalid MAIN TAP. It should be greater than (pre + post1 + post2 + 1)\n")));
   3855         return SOC_E_PARAM;
   3856     }
   3857     if ((pre + main + post1 + post2) > 60) {
   3858         LOG_ERROR(BSL_LS_SOC_PHY,
   3859                   (BSL_META("Invalid Value. pre + main + post1 + post2 should be less than 60\n")));
   3860         return SOC_E_PARAM;
   3861     }
   3862     if ((!post2to1) && ((pre + post1) > 22)) {
   3863         LOG_ERROR(BSL_LS_SOC_PHY,
   3864                   (BSL_META("Invalid Value. pre + post1 greater than 22\n")));
   3865         return SOC_E_PARAM;
   3866     }
   3867     if (post2to1 && ((pre + post1) > 27)) {
   3868         LOG_ERROR(BSL_LS_SOC_PHY,
   3869                   (BSL_META("Invalid Value. pre + post1 greater than 27\n")));
   3870         return SOC_E_PARAM;
   3871     }
   3872     return SOC_E_NONE;  
   3873 }
   3874 
   3875 STATIC int32
   3876 _phy_82328_control_preemphasis_get(int32 unit, soc_port_t port, soc_phy_control_t type, 
   3877 								   phy82328_intf_side_t side, uint32 *value)
   3878 {
   3879 	int32			lane, lane_idx;
   3880     uint16      data16 = 0;
   3881 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3882     /* coverity [mixed_enums:FALSE] */
   3883 	PHY82328_PREEMPHASIS_LANE_GET(type, lane);
   3884 	lane_idx = (lane == PHY82328_ALL_LANES) ? 0 : lane;
   3885 
   3886 
   3887     SOC_IF_ERROR_RETURN(
   3888      phy82328_intf_side_reg_select(unit, port, side));
   3889 
   3890 	if (PHY82328_SINGLE_PORT_MODE(pc)) {
   3891 		SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, lane_idx));
   3892 	} 
   3893     /*
   3894 	 * Value format:
   3895 	 * bit 21:18: post2_tap        - see 1.d111[10:7]
   3896 	 * bit 16:12: postcursor_tap   - see 1.d110[9:5]
   3897 	 * bit 10:05: main_tap         - see 1.d111[5:0]
   3898 	 * bit 03:00: precursor_tap    - see 1.d110[3:0]
   3899 	 */
   3900     *value = 0;
   3901 	
   3902 	SOC_IF_ERROR_RETURN(
   3903 		READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL2, &data16));
   3904 	
   3905     *value = ((data16 & TX_FED_TXFIR_CONTROL2_TXFIR_POST2_MASK) >> 
   3906               TX_FED_TXFIR_CONTROL2_TXFIR_POST2_SHIFT) << 18;
   3907     *value |= ((data16 & TX_FED_TXFIR_CONTROL2_TXFIR_MAIN_OVERRIDE_MASK) << 5);
   3908      
   3909     SOC_IF_ERROR_RETURN(
   3910 		READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL1, &data16));
   3911 	
   3912     *value |= ((data16 & TX_FED_TXFIR_CONTROL1_TXFIR_POST_OVERRIDE_MASK) >> 
   3913               TX_FED_TXFIR_CONTROL1_TXFIR_POST_OVERRIDE_SHIFT) << 12;
   3914     *value |= (data16 & TX_FED_TXFIR_CONTROL1_TXFIR_PRE_OVERRIDE_MASK);
   3915 
   3916     if (PHY82328_SINGLE_PORT_MODE(pc)) {
   3917         SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, PHY82328_ALL_LANES));
   3918     }
   3919     SOC_IF_ERROR_RETURN(
   3920      phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   3921 
   3922     return SOC_E_NONE;
   3923 }
   3924 
   3925 STATIC int32
   3926 _phy_82328_control_preemphasis_set(int32 unit, soc_port_t port, 
   3927 								   soc_phy_control_t type, 
   3928 								   phy82328_intf_side_t side,
   3929 								   uint32 value)
   3930 {
   3931     int32       lane, lane_idx, lane_start, lane_end;
   3932 	uint8       pre_cursor_tap = 0;
   3933 	uint8       main_tap = 0;
   3934 	uint8       post_cursor_tap = 0;
   3935 	uint8       post2_tap = 0;
   3936 
   3937 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   3938 
   3939     /* coverity [mixed_enums:FALSE] */
   3940 	PHY82328_PREEMPHASIS_LANE_GET(type, lane);
   3941 	if (!PHY82328_SINGLE_PORT_MODE(pc) && (lane != PHY82328_ALL_LANES)) {
   3942 		    if (lane != (pc->phy_id & 0x03)) {
   3943 		    	return SOC_E_PARAM;
   3944 		    }
   3945 	}
   3946 
   3947 	/*
   3948 	 * Value format:
   3949 	 * bit 21:18: post2_tap        - see 1.d111[10:7]
   3950 	 * bit 16:12: postcursor_tap   - see 1.d110[9:5]
   3951 	 * bit 10:05: main_tap         - see 1.d111[5:0]
   3952 	 * bit 03:00: precursor_tap    - see 1.d110[3:0]
   3953 	 */
   3954      pre_cursor_tap = (value & 0xf);
   3955      main_tap = (value & 0x7E0) >> 5;
   3956      post_cursor_tap = (value & 0x1F000) >> 12;
   3957      post2_tap = (value & 0x3c0000) >> 18;
   3958     
   3959      SOC_IF_ERROR_RETURN(
   3960          phy82328_validate_preemphasis(pre_cursor_tap, main_tap, 
   3961                  post_cursor_tap, post2_tap));
   3962 
   3963     /*
   3964 	 * Single mode: if lane specified, enable only that lane, otherwise enable all lanes
   3965 	 * Quad mode: if specified lane matches lane for the channel, set the lane
   3966 	 */
   3967 	if (PHY82328_SINGLE_PORT_MODE(pc)) {
   3968 		lane_start = (lane == PHY82328_ALL_LANES) ? 0 : lane;
   3969 		lane_end   = (lane == PHY82328_ALL_LANES) ? PHY82328_NUM_LANES : lane + 1;
   3970 	}
   3971     else {
   3972 		/* Make sure specified lane matches lane for the channel */
   3973 		if (lane != PHY82328_ALL_LANES) {
   3974 			if (lane != (pc->phy_id & 0x03)) {
   3975 				return SOC_E_PARAM;
   3976 			}
   3977 		}
   3978 		lane_start = 0;
   3979 		lane_end   = 1;
   3980 	}
   3981 
   3982     SOC_IF_ERROR_RETURN(
   3983 	 phy82328_intf_side_reg_select(unit, port, side));
   3984 	/* Update all requested lanes */
   3985 	for (lane_idx = lane_start; lane_idx < lane_end; lane_idx++) {
   3986 		if (PHY82328_SINGLE_PORT_MODE(pc)) {
   3987 			/* Select the lane and side to write */
   3988 			SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, lane_idx));
   3989 		} 
   3990         SOC_IF_ERROR_RETURN(
   3991 			MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, AMS_TX_TX_CTRL_5,
   3992                 (((post2_tap == 0)?1:0) << AMS_TX_TX_CTRL_5_POST2TO1_SHIFT) ,
   3993                 AMS_TX_TX_CTRL_5_POST2TO1_MASK));
   3994 
   3995         /* Enable/Disable precursor */
   3996 		SOC_IF_ERROR_RETURN(
   3997 			MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, AMS_TX_TX_CTRL_5,
   3998                 ((pre_cursor_tap?1:0) << AMS_TX_TX_CTRL_5_EN_PRE_SHIFT) ,
   3999                 AMS_TX_TX_CTRL_5_EN_PRE_MASK));
   4000      	/* Set precursor */
   4001 		SOC_IF_ERROR_RETURN(
   4002 			MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL1,
   4003               pre_cursor_tap , TX_FED_TXFIR_CONTROL1_TXFIR_PRE_OVERRIDE_MASK));
   4004 
   4005 		/* Main tap */
   4006         SOC_IF_ERROR_RETURN(
   4007 			MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL2,
   4008               main_tap, TX_FED_TXFIR_CONTROL2_TXFIR_MAIN_OVERRIDE_MASK));
   4009         
   4010         /* Enable/Disable postcursor */
   4011 		SOC_IF_ERROR_RETURN(
   4012 		    MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, AMS_TX_TX_CTRL_5,
   4013               ((post_cursor_tap?1:0) << AMS_TX_TX_CTRL_5_EN_POST1_SHIFT) ,
   4014               AMS_TX_TX_CTRL_5_EN_POST1_MASK));
   4015 
   4016      	/* Set postcursor */
   4017 		SOC_IF_ERROR_RETURN(
   4018 			MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL1,
   4019              (post_cursor_tap << TX_FED_TXFIR_CONTROL1_TXFIR_POST_OVERRIDE_SHIFT), 
   4020              TX_FED_TXFIR_CONTROL1_TXFIR_POST_OVERRIDE_MASK));
   4021  
   4022         /* Enable/Disable post2cursor */
   4023 		SOC_IF_ERROR_RETURN(
   4024 			    MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, AMS_TX_TX_CTRL_5,
   4025                 ((post2_tap?1:0) << AMS_TX_TX_CTRL_5_EN_POST2_SHIFT) ,
   4026                 AMS_TX_TX_CTRL_5_EN_POST2_MASK));
   4027 
   4028      	/* Set post2cursor */
   4029 		SOC_IF_ERROR_RETURN(
   4030 			MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_CONTROL2,
   4031              (post2_tap << TX_FED_TXFIR_CONTROL2_TXFIR_POST2_SHIFT),
   4032              TX_FED_TXFIR_CONTROL2_TXFIR_POST2_MASK));
   4033 	}
   4034 
   4035 	if (PHY82328_SINGLE_PORT_MODE(pc)) {
   4036 		SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, PHY82328_ALL_LANES));
   4037 	}
   4038     SOC_IF_ERROR_RETURN(
   4039      phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   4040     return SOC_E_NONE;
   4041 }
   4042 
   4043 STATIC int32
   4044 _phy_82328_rx_los_control_set(int32 unit, soc_port_t port, uint32 value)
   4045 {
   4046     phy_ctrl_t *pc= EXT_PHY_SW_STATE(unit, port);
   4047 
   4048     SOC_IF_ERROR_RETURN(
   4049      phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   4050 
   4051         SOC_IF_ERROR_RETURN(               
   4052             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, SIGDET_SIGDET_CTRL_1, 
   4053             (value?(1<<SIGDET_SIGDET_CTRL_1_SIGNAL_DETECT_FRC_SHIFT):0), 
   4054              SIGDET_SIGDET_CTRL_1_SIGNAL_DETECT_FRC_MASK));
   4055     FW_RX_LOS(pc) = value;
   4056     return SOC_E_NONE;
   4057 }
   4058 
   4059 STATIC int32
   4060 _phy_82328_do_rxseq_restart(int32 unit, soc_port_t port, phy82328_intf_side_t side)
   4061 {
   4062 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   4063 	PHY_82328_MICRO_PAUSE(unit, port, "rxseq restart1");
   4064     if (side == PHY82328_INTF_SIDE_SYS) {
   4065         SOC_IF_ERROR_RETURN(
   4066          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS));
   4067     }
   4068 	SOC_IF_ERROR_RETURN
   4069 		(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, XGXS_BLK0_XGXSCONTROL,
   4070 					 0,	QSFI_XGXS_BLK0_XGXSCONTROL_START_SEQUENCER_MASK));
   4071     
   4072     if (side == PHY82328_INTF_SIDE_SYS) {
   4073         SOC_IF_ERROR_RETURN(
   4074          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   4075     }
   4076 	PHY_82328_MICRO_RESUME(unit, port);
   4077 
   4078 	sal_udelay(800);
   4079 	
   4080 	PHY_82328_MICRO_PAUSE(unit, port, "rxseq restart 2");
   4081     if (side == PHY82328_INTF_SIDE_SYS) {
   4082         SOC_IF_ERROR_RETURN(
   4083          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS));
   4084     }
   4085     SOC_IF_ERROR_RETURN
   4086 		(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, 
   4087 							XGXS_BLK0_XGXSCONTROL, QSFI_XGXS_BLK0_XGXSCONTROL_START_SEQUENCER_MASK,
   4088                             QSFI_XGXS_BLK0_XGXSCONTROL_START_SEQUENCER_MASK));
   4089     if (side == PHY82328_INTF_SIDE_SYS) {
   4090         SOC_IF_ERROR_RETURN(
   4091          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   4092     }
   4093 	PHY_82328_MICRO_RESUME(unit, port);
   4094 
   4095 	return SOC_E_NONE;
   4096 }
   4097 
   4098 STATIC int
   4099 _phy_82328_mod_auto_detect_set(int unit, soc_port_t port, uint32 value)
   4100 {
   4101     phy_ctrl_t *pc;
   4102     uint16 data;
   4103     uint16 rddata;
   4104     uint16 count = 0;
   4105     uint16 mask;
   4106 
   4107     pc = EXT_PHY_SW_STATE(unit, port);
   4108     mask = (MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_QSFP_MOD_DETECT_MASK |
   4109                 MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK);
   4110     data = value ? mask : 0;
   4111 
   4112     SOC_IF_ERROR_RETURN(
   4113         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, data, 
   4114                                         mask));
   4115  
   4116     if (!value) {
   4117         /* Request is disabling mod auto detect, need to wait until I2CM FSM  becomes IDLE */
   4118         /* Wait approx for 325 ms */ 
   4119         while (count < PHY82328_I2CM_IDLE_WAIT_COUNT){
   4120             SOC_IF_ERROR_RETURN(
   4121                 READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_I2C_CONTROL_REGISTER, &rddata));
   4122             if ((rddata & 0xC) == 0) {
   4123                 break;
   4124             }
   4125             count ++;
   4126             sal_usleep(PHY82328_I2CM_IDLE_WAIT_CHUNK * 1000);
   4127         }
   4128         if (count >= PHY82328_I2CM_IDLE_WAIT_COUNT) {
   4129             return SOC_E_BUSY;
   4130         }
   4131     }
   4132  
   4133     /* Update the global database */
   4134     MOD_AUTO_DETECT(pc) = value ? 1:0; 
   4135     
   4136     return SOC_E_NONE;
   4137 }
   4138 
   4139 STATIC int
   4140 _phy_82328_mod_auto_detect_get(int unit, soc_port_t port, uint32 *value)
   4141 {
   4142     phy_ctrl_t *pc;
   4143     uint16 data;
   4144  
   4145     pc = EXT_PHY_SW_STATE(unit, port);
   4146 
   4147     SOC_IF_ERROR_RETURN(
   4148         READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_GP_REG_0, &data));
   4149 
   4150     if( data & (MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_QSFP_MOD_DETECT_MASK |
   4151                 MGT_TOP_CMN_CTLR_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK)) {
   4152         *value = 1;
   4153     } else {
   4154         *value = 0;
   4155     } 
   4156     return SOC_E_NONE;
   4157 }
   4158 
   4159 /*
   4160  * Function:
   4161  *      _phy_82328_control_set
   4162  * Purpose:
   4163  *      Configure PHY device specific control fucntion.
   4164  * Parameters:
   4165  *      unit  - StrataSwitch unit #.
   4166  *      port  - StrataSwitch port #.
   4167  *      type  - Control to update
   4168  *      value - New setting for the control
   4169  * Returns:
   4170  *      SOC_E_NONE
   4171  */
   4172 STATIC int32
   4173 _phy_82328_control_set(int32 unit, soc_port_t port, int32 intf, int32 lane,
   4174                      soc_phy_control_t type, uint32 value)
   4175 {
   4176     phy_ctrl_t    *pc;       /* PHY software state */
   4177     int32 rv = SOC_E_UNAVAIL;
   4178  
   4179     pc = EXT_PHY_SW_STATE(unit, port);
   4180 
   4181     PHY_CONTROL_TYPE_CHECK(type);
   4182 	
   4183     if (intf == PHY_DIAG_INTF_SYS) {
   4184         SOC_IF_ERROR_RETURN(
   4185          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS));
   4186     }
   4187 
   4188     switch (type) {
   4189         case SOC_PHY_CONTROL_PREEMPHASIS:
   4190 		    /* fall through */
   4191         case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   4192             /* fall through */
   4193         case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   4194             /* fall through */
   4195         case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   4196             /* fall through */
   4197         case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   4198 		    rv = _phy_82328_control_preemphasis_set(unit, port, type, 
   4199 												(pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   4200 												PHY82328_INTF_SIDE_SYS : PHY82328_INTF_SIDE_LINE, 
   4201 												value);
   4202 		    break;
   4203         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   4204         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   4205         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   4206         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   4207         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   4208         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   4209         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   4210         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   4211         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   4212         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   4213             rv = SOC_E_UNAVAIL;
   4214         break;
   4215 
   4216         case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   4217             rv = _phy_82328_control_prbs_polynomial_set(unit, port, value);					
   4218         break;
   4219         case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   4220             rv = _phy_82328_control_prbs_invert_data_set(unit, port, value);					
   4221         break;
   4222         case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   4223         /* fall through */
   4224         case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   4225             rv = _phy_82328_control_prbs_enable_set(unit, port, value);
   4226         break;
   4227         case SOC_PHY_CONTROL_LOOPBACK_REMOTE_PCS_BYPASS:
   4228             rv = _phy_82328_remote_loopback_set(unit, port, value);
   4229         break;
   4230         case SOC_PHY_CONTROL_TX_LANE_SQUELCH:
   4231 		    /*Squelch Tx Line Side*/
   4232             rv = _phy_82328_tx_squelch(unit,port,PHY82328_INTF_SIDE_LINE,value);
   4233         break;
   4234         case SOC_PHY_CONTROL_PORT_PRIMARY:
   4235             rv = soc_phyctrl_primary_set(unit, port, (soc_port_t)value);
   4236         break;
   4237         case SOC_PHY_CONTROL_PORT_OFFSET:
   4238             rv = soc_phyctrl_offset_set(unit, port, (int32)value);
   4239         break;
   4240         case SOC_PHY_CONTROL_RX_POLARITY:
   4241             rv = _phy_82328_polarity_flip (unit, port, 
   4242 		          PHY82328_POL_DND, (uint16)value);
   4243         break;
   4244         case SOC_PHY_CONTROL_TX_POLARITY:
   4245             rv = _phy_82328_polarity_flip (unit, port, 
   4246 		             (uint16)value, PHY82328_POL_DND);
   4247         break;
   4248         case SOC_PHY_CONTROL_DUMP:
   4249             rv = _phy_82328_debug_info(unit, port);
   4250         break;
   4251         case SOC_PHY_CONTROL_SOFTWARE_RX_LOS:
   4252             /* enable/disable RX los on line side*/
   4253             rv = _phy_82328_rx_los_control_set(unit, port, value);
   4254         break;
   4255         case SOC_PHY_CONTROL_RX_SEQ_TOGGLE:
   4256 		/* value is not used since this is always a toggle ->1->0 */
   4257 		rv = _phy_82328_do_rxseq_restart(unit, port,
   4258                             (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   4259                             PHY82328_INTF_SIDE_SYS : PHY82328_INTF_SIDE_LINE);
   4260 		break;
   4261         case SOC_PHY_CONTROL_MOD_AUTO_DETECT_ENABLE:
   4262             rv = _phy_82328_mod_auto_detect_set(unit, port, value); 
   4263         break;
   4264 
   4265         case SOC_PHY_CONTROL_LOOPBACK_INTERNAL:
   4266             rv = SOC_E_UNAVAIL;
   4267         break;
   4268  
   4269         default:
   4270             return SOC_E_UNAVAIL;
   4271     }
   4272     return rv;
   4273 }
   4274 
   4275 STATIC int32
   4276 phy_82328_control_set(int32 unit, soc_port_t port,
   4277                      soc_phy_control_t type, uint32 value)
   4278 {
   4279     SOC_IF_ERROR_RETURN(
   4280             _phy_82328_control_set(unit, port, PHY_DIAG_INTF_LINE,
   4281                                    PHY_DIAG_LN_DFLT, type, value));
   4282     return SOC_E_NONE;
   4283 }
   4284 
   4285 /*
   4286  * Function:
   4287  *      _phy_82328_control_prbs_enable_get
   4288  * Purpose:
   4289  *      Configure PHY device specific control fucntion.
   4290  * Parameters:
   4291  *      unit  - StrataSwitch unit #.
   4292  *      port  - StrataSwitch port #. *      
   4293  *      value - (OUT)Current setting for the PRBS Gen & Chkr
   4294  * Returns:
   4295  *      SOC_E_NONE
   4296  */
   4297 STATIC int32
   4298 _phy_82328_control_prbs_enable_get(int32 unit, soc_port_t port, uint32 *value)
   4299 {
   4300     uint16  gen_data=0,chkr_data=0;
   4301     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4302  
   4303     *value = 0;
   4304     /*Prbs Gen in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.0*/
   4305     SOC_IF_ERROR_RETURN(
   4306             READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4307 			  TLB_TX_PRBS_GEN_CONFIG, &gen_data));
   4308     gen_data &= TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_EN_MASK;
   4309     gen_data = gen_data >> TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_EN_SHIFT;
   4310 		
   4311     /*Prbs Checker En in TLB_RX_PRBS_CHK_CONFIG 1.D0D1.0*/     
   4312     SOC_IF_ERROR_RETURN(
   4313         READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4314             TLB_RX_PRBS_CHK_CONFIG, &chkr_data));
   4315     chkr_data &= TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_EN_MASK;
   4316     chkr_data = chkr_data >> TLB_RX_PRBS_CHK_CONFIG_PRBS_CHK_EN_SHIFT;
   4317 		
   4318     *value = gen_data && chkr_data;
   4319  
   4320     return SOC_E_NONE;
   4321 }
   4322 
   4323 /*
   4324  * Function:
   4325  *      _phy_82328_control_prbs_rx_status_get
   4326  * Purpose:
   4327  *      Configure PHY device specific control fucntion.
   4328  * Parameters:
   4329  *      unit  - StrataSwitch unit #.
   4330  *      port  - StrataSwitch port #. *      
   4331  *      value - (OUT)PRBS Status Lock & Error Cntr 
   4332  * Returns:
   4333  *      SOC_E_NONE
   4334  */
   4335 STATIC int32
   4336 _phy_82328_control_prbs_rx_status_get(int32 unit, soc_port_t port, uint16 intf, uint32 *value)
   4337 {
   4338     uint16  lock = 0, err_lsb = 0, err_msb = 0, lanes = 0, lane_idx = 0;
   4339     uint32  err_cnt = 0;
   4340     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4341     
   4342     if (PHY82328_SINGLE_PORT_MODE(pc)) {
   4343         lanes = PHY82328_NUM_LANES;
   4344     }
   4345     else {
   4346         lanes = 1;
   4347     }
   4348  
   4349     *value = 0;
   4350     for (lane_idx = 0; lane_idx < lanes; lane_idx++) {
   4351         if (PHY82328_SINGLE_PORT_MODE(pc)) {
   4352             /* Select the lane and side to access */
   4353             SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, 
   4354                                            (intf == PHY_DIAG_INTF_LINE) ? PHY82328_INTF_SIDE_LINE
   4355                                            : PHY82328_INTF_SIDE_SYS , lane_idx));
   4356         }
   4357         
   4358         /*Prbs Lock Status in TLB_RX_PRBS_CHK_LOCK_STATUS 1.D0D9.0*/
   4359         SOC_IF_ERROR_RETURN
   4360             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 
   4361                   TLB_RX_PRBS_CHK_LOCK_STATUS, &lock));
   4362         lock &= TLB_RX_PRBS_CHK_LOCK_STATUS_PRBS_CHK_LOCK_MASK;
   4363 	    	
   4364         /*Prbs Err Cnt MSB in TLB_RX_PRBS_CHK_ERR_CNT_MSB_STATUS 1.D0DA*/     
   4365         SOC_IF_ERROR_RETURN(
   4366              READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4367                   TLB_RX_PRBS_CHK_ERR_CNT_MSB_STATUS, &err_msb));
   4368 
   4369         err_msb &= TLB_RX_PRBS_CHK_ERR_CNT_MSB_STATUS_PRBS_CHK_ERR_CNT_MSB_MASK;
   4370 	    	
   4371         /*Prbs Err Cnt LSB in TLB_RX_PRBS_CHK_ERR_CNT_LSB_STATUS 1.D0DB*/     
   4372         SOC_IF_ERROR_RETURN(
   4373              READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4374                    TLB_RX_PRBS_CHK_ERR_CNT_LSB_STATUS, &err_lsb));
   4375 	    	
   4376 	    err_cnt = (err_msb << TLB_RX_PRBS_CHK_ERR_CNT_LSB_STATUS_PRBS_CHK_ERR_CNT_LSB_BITS) 
   4377                   |err_lsb;
   4378         
   4379         if (lock && !err_cnt) { /*Locked and No errors*/
   4380             *value |= 0;
   4381         } else {
   4382             if (!lock) { /*Not Locked*/	
   4383                 *value |= -1;	
   4384             } else {
   4385                 /*Locked With Errors*/
   4386                 *value |= err_cnt;
   4387             }
   4388         }
   4389     }
   4390     
   4391     /* Restore to default single port register access */
   4392     if (PHY82328_SINGLE_PORT_MODE(pc)) {
   4393         SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port,
   4394                              PHY82328_INTF_SIDE_LINE, PHY82328_ALL_LANES));
   4395     }
   4396 
   4397     return SOC_E_NONE;
   4398 }
   4399 
   4400 /*
   4401  * Function:
   4402  *      _phy_82328_control_prbs_tx_invert_data_get
   4403  * Purpose:
   4404  *      Configure PHY device specific control fucntion.
   4405  * Parameters:
   4406  *      unit  - StrataSwitch unit #.
   4407  *      port  - StrataSwitch port #. *      
   4408  *      value - (OUT)Current setting for the PRBS Invert
   4409  * Returns:
   4410  *      SOC_E_NONE
   4411  */
   4412 STATIC int32
   4413 _phy_82328_control_prbs_tx_invert_data_get(int32 unit, soc_port_t port, uint32 *value)
   4414 {
   4415     uint16  data=0;		
   4416     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4417  
   4418     *value = 0;
   4419     /*Prbs Invert in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.4 */ 
   4420     SOC_IF_ERROR_RETURN
   4421         (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4422               TLB_TX_PRBS_GEN_CONFIG, &data));
   4423 
   4424     data &= TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_INV_MASK;
   4425 
   4426     *value = data >> TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_INV_SHIFT;		
   4427  
   4428     return SOC_E_NONE;
   4429 }
   4430 
   4431 /*
   4432  * Function:
   4433  *      _phy_82328_control_prbs_polynomial_get
   4434  * Purpose:
   4435  *      Configure PHY device specific control fucntion.
   4436  * Parameters:
   4437  *      unit  - StrataSwitch unit #.
   4438  *      port  - StrataSwitch port #. *      
   4439  *      value - (OUT)Current setting for the PRBS Polynomial
   4440  *       0=prbs7, 
   4441  *       1=prbs=15 
   4442  *       2=prbs=23 
   4443  *       3=prbs=31 
   4444  * Returns:
   4445  *      SOC_E_NONE
   4446  */
   4447 STATIC int32
   4448 _phy_82328_control_prbs_polynomial_get(int32 unit, soc_port_t port, uint32 *value)
   4449 {
   4450     uint16  data;
   4451     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4452  
   4453     *value = 0;
   4454     /* Prbs Polynomial in TLB_TX_PRBS_GEN_CONFIG 1.D0E1.[3:1] */        
   4455     SOC_IF_ERROR_RETURN
   4456         (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4457              TLB_TX_PRBS_GEN_CONFIG, &data));
   4458 
   4459     data &= TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_MODE_SEL_MASK;
   4460     data = data >> TLB_TX_PRBS_GEN_CONFIG_PRBS_GEN_MODE_SEL_SHIFT;
   4461     switch(data) {
   4462         case 0: /* PRBS 7*/
   4463             *value = 0;
   4464         break;
   4465         case 3: /*PRBS15*/
   4466             *value = 1;
   4467         break;
   4468         case 4:/*PRBS23*/
   4469             *value = 2;
   4470         break;
   4471         case 5:/*PRBS31*/
   4472             *value = 3;
   4473         break;
   4474         case 1:/*PRBS 9*/
   4475             *value = 4;
   4476         break;
   4477         case 2:/*PRBS 11*/
   4478             *value = 5;
   4479         break;
   4480         case 6: /*PRBS58*/
   4481             *value = 6;
   4482         break;
   4483     }
   4484     return SOC_E_NONE;
   4485 }
   4486 
   4487 STATIC int32
   4488 _phy_82328_debug_info(int32 unit, soc_port_t port)
   4489 {
   4490     phy_ctrl_t			*pc;     
   4491     phy_ctrl_t			*int_pc; 
   4492     phy82328_intf_cfg_t *intf;
   4493     phy82328_intf_cfg_t *line_intf;
   4494     phy82328_intf_cfg_t *sys_intf;
   4495     phy82328_intf_side_t side, saved_side;
   4496     soc_port_if_t		iif;
   4497     int32					lane, die_temp = 0, i = 0;
   4498     int32					ian, ian_done, ilink, ispeed;
   4499     uint16				link_sts[PHY82328_NUM_LANES];
   4500     uint16				pol_sts[PHY82328_NUM_LANES];
   4501     uint16				data0, data1, data2, data3, data4;
   4502     uint32				primary_port, offset;
   4503     uint32              preemphasis[PHY82328_NUM_LANES];
   4504     char *rx_los_sts;
   4505  
   4506     pc = EXT_PHY_SW_STATE(unit, port);
   4507     int_pc = INT_PHY_SW_STATE(unit, port);
   4508 	
   4509     SOC_IF_ERROR_RETURN(phy_82328_control_get(unit, port, SOC_PHY_CONTROL_PORT_PRIMARY, 
   4510                                              &primary_port));
   4511 
   4512     SOC_IF_ERROR_RETURN(phy_82328_control_get(unit, port, SOC_PHY_CONTROL_PORT_OFFSET,
   4513                                               &offset));
   4514 
   4515 	/* Access line side registers */
   4516     saved_side = _phy_82328_intf_side_regs_get(unit, port);
   4517     if (saved_side == PHY82328_INTF_SIDE_SYS) {
   4518         SOC_IF_ERROR_RETURN(
   4519          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   4520     }
   4521 
   4522     /* firware rev: 1.c161  */
   4523     SOC_IF_ERROR_RETURN
   4524         (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4525                           0xc161, &data0));
   4526 
   4527     /* micro enabled: 1.ca18 */
   4528     SOC_IF_ERROR_RETURN
   4529         (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4530                           MGT_TOP_GP_REG_0, &data1));
   4531 	/* Link sts 1.c0b0*/
   4532     SOC_IF_ERROR_RETURN
   4533         (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4534                           RX_ANARXSTATUS, &data2));
   4535     SOC_IF_ERROR_RETURN
   4536         (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4537                           MGT_TOP_VTMON_STATUS, &data3));
   4538     data3 &= MGT_TOP_CMN_CTLR_VTMON_STATUS_VTMON_DATA_MASK;
   4539     rx_los_sts = "NONE";
   4540     die_temp = 425 - ((49935 * data3)/100000);
   4541     if ((FW_RX_LOS(pc) & 0x1) == 0x1) {
   4542         rx_los_sts = "FW";
   4543     }
   4544 
   4545     LOG_CLI((BSL_META_U(unit,
   4546                         "Port %-2d: devid=%d, chiprev=%04x, "
   4547                         "micro ver(1.%04x)=%04x, micro(1.%04x)=%04x, \n"
   4548                         "     pri:offs=%d:%d, mdio=0x%x, datapath=%d, "
   4549                         "Link (1.%04x)=%04x\n DieTemprature= %d*c,"
   4550                         "        Rx LOS=%s\n"),
   4551              port, DEVID(pc), DEVREV(pc), XGXS_BLK8_CL73CONTROL8, data0,
   4552              MGT_TOP_GP_REG_0, data1,
   4553              primary_port, offset, pc->phy_id, 
   4554              CUR_DATAPATH(pc) == PHY82328_DATAPATH_20 ? 20 : 4,
   4555              RX_ANARXSTATUS, data2, die_temp, rx_los_sts));
   4556     LOG_CLI((BSL_META_U(unit,
   4557                         "AN:%d\n"), AN_EN(pc)));
   4558     /* Single PMD control: 1.ca86 */
   4559     SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4560                                 MGT_TOP_SINGLE_PMD_CTRL, &data0));
   4561 
   4562     /* Broadcast control: 1.c8fe */
   4563     SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4564                                 MGT_TOP_BROADCAST_CTRL, &data1));
   4565 
   4566     /* Global intf type/speed - driver csr: 1.c841 */
   4567     SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4568                                MGT_TOP_GP_REGISTER_1, &data2));
   4569 
   4570     /* Micro csr 1.c843 */
   4571     SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4572                                MGT_TOP_GP_REGISTER_3, &data3));
   4573 
   4574     LOG_CLI((BSL_META_U(unit,
   4575                         "     PMD(1.%04x)=%04x, bcctrl(1.%04x)=%04x, \n"
   4576                         "     drvcsr(1.%04x)=%04x, ucsr(1.%04x)=%04x\n"),
   4577              MGT_TOP_SINGLE_PMD_CTRL , data0,
   4578              MGT_TOP_BROADCAST_CTRL, data1, 
   4579              MGT_TOP_GP_REGISTER_1, data2,
   4580              MGT_TOP_GP_REGISTER_3, data3));
   4581 
   4582     /* Interfaces: software, hardware, internal serdes */
   4583     line_intf = &(LINE_INTF(pc));
   4584     sys_intf = &(SYS_INTF(pc));
   4585     for (side = PHY82328_INTF_SIDE_LINE; side <= PHY82328_INTF_SIDE_SYS; side++) {
   4586 
   4587         SOC_IF_ERROR_RETURN(
   4588          phy82328_intf_side_reg_select(unit, port, side));
   4589 
   4590         /* control: 1.0000 */
   4591         SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4592                                            IEEE0_BLK_PMA_PMD_PMD_CONTROL_REGISTER, &data1));
   4593 		
   4594         /* PMD type: 1.0007 */
   4595         SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4596                                          IEEE0_BLK_PMA_PMD_PMD_CONTROL_2_REGISTER, &data2));
   4597 
   4598         /* Loopback 1.d0e2 */
   4599         SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 
   4600                                            TLB_TX_RMT_LPBK_CONFIG, &data3));
   4601 
   4602         /* Tx disable 1.c08b */
   4603         SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_ANATXACONTROL7, 
   4604                                            &data4));
   4605         
   4606         if (PHY82328_SINGLE_PORT_MODE(pc)) {
   4607             if (side == PHY82328_INTF_SIDE_SYS) {
   4608                 PHY_82328_MICRO_PAUSE(unit, port, "");
   4609             }
   4610             for (lane = 0; lane < PHY82328_NUM_LANES; lane++) {
   4611                 SOC_IF_ERROR_RETURN
   4612                   (_phy_82328_control_preemphasis_get(unit, port, 
   4613                   (SOC_PHY_CONTROL_PREEMPHASIS_LANE0 + lane), side, &preemphasis[lane]));
   4614 
   4615                 /* Select the lane and side to write */
   4616                 SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, lane));
   4617 
   4618                 /* Link: 1.c0b0 */
   4619                 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4620                                     RX_ANARXSTATUS, &(link_sts[lane])));
   4621              
   4622                 if (CUR_DATAPATH(pc) == PHY82328_DATAPATH_20) {
   4623                     /* Polarity setting: 1.d0e3 */
   4624                     SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4625                                        TLB_TX_TLB_TX_MISC_CONFIG, &(pol_sts[lane])));
   4626                 } else {
   4627                     /* Polarity setting: 1.d0a0 */
   4628                     SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4629                                         AMS_TX_TX_CTRL_0, &(pol_sts[lane])));
   4630                 }
   4631             }
   4632             /* Back to default channel selection through lane 0 */
   4633             SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, PHY82328_ALL_LANES));
   4634             SOC_IF_ERROR_RETURN(
   4635              phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   4636             if (side == PHY82328_INTF_SIDE_SYS) {
   4637                 PHY_82328_MICRO_RESUME(unit, port);
   4638             }
   4639         } else {
   4640                 SOC_IF_ERROR_RETURN
   4641                       (_phy_82328_control_preemphasis_get(unit, port, 
   4642                         SOC_PHY_CONTROL_PREEMPHASIS, side, &preemphasis[i]));
   4643 
   4644                 /* Link: 1.c0b0 */
   4645                 SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4646                                     RX_ANARXSTATUS, &(link_sts[i])));
   4647                 if (CUR_DATAPATH(pc) == PHY82328_DATAPATH_20) {
   4648                     /* Polarity setting: 1.doe3 */
   4649                     SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   4650                                         TLB_TX_TLB_TX_MISC_CONFIG, 
   4651                                         &(pol_sts[i])));
   4652                 } else {
   4653                     /* Polarity setting: 1.d0a0 */
   4654                     SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 
   4655                                         AMS_TX_TX_CTRL_0, 
   4656                                         &(pol_sts[i])));
   4657             }
   4658         }
   4659         intf = (side == PHY82328_INTF_SIDE_LINE) ? line_intf : sys_intf;			
   4660         if (PHY82328_SINGLE_PORT_MODE(pc)) {
   4661             LOG_CLI((BSL_META_U(unit,
   4662                                 " %s: type=%s, speed=%d, "
   4663                                 "forced cl72=%d, mode(1.%04x)=%04x\n"
   4664                                 "           pmdtype(1.%04x)=%04x, "
   4665                                 "lb(1.%04x)=%04x, txdis(1.%04x)=%04x\n"
   4666                                 "           link(1.%04x)      : "
   4667                                 "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n"
   4668                                 "           pol(1.%04x)       : "
   4669                                 "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n"
   4670                                 "           Preemphasis       : "
   4671                                 "(ln0=%08x, ln1=%08x, ln2=%08x, ln3=%08x)\n"),
   4672                      (side == PHY82328_INTF_SIDE_LINE) ?
   4673                      "Line    " : "System  ",
   4674                      phy82328_intf_names[intf->type], intf->speed,
   4675                      SYS_FORCED_CL72(pc),
   4676                      IEEE0_BLK_PMA_PMD_PMD_CONTROL_REGISTER, data1,
   4677                      IEEE0_BLK_PMA_PMD_PMD_CONTROL_2_REGISTER, data2,
   4678                      TLB_TX_RMT_LPBK_CONFIG, data3,
   4679                      TX_ANATXACONTROL7, data4,
   4680                      RX_ANARXSTATUS, link_sts[0], link_sts[1],
   4681                      link_sts[2], link_sts[3],
   4682                      CUR_DATAPATH(pc) == PHY82328_DATAPATH_20 ?
   4683                      TLB_TX_TLB_TX_MISC_CONFIG : AMS_TX_TX_CTRL_0,
   4684                      pol_sts[0], pol_sts[1], pol_sts[2], pol_sts[3],
   4685                      preemphasis[0], preemphasis[1],
   4686                      preemphasis[2], preemphasis[3]));
   4687         } else {
   4688             LOG_CLI((BSL_META_U(unit,
   4689                                 " %s: type=%s, speed=%d, "
   4690                                 "forced cl72=%d, mode(1.%04x)=%04x\n"
   4691                                 "           pmdtype(1.%04x)=%04x, "
   4692                                 "lb(1.%04x)=%04x, txdis(1.%04x)=%04x\n"),
   4693                      (side == PHY82328_INTF_SIDE_LINE) ? 
   4694                      "Line    " : "System  ",
   4695                      phy82328_intf_names[intf->type], 
   4696                      intf->speed, SYS_FORCED_CL72(pc),
   4697                      IEEE0_BLK_PMA_PMD_PMD_CONTROL_REGISTER, data1,
   4698                      IEEE0_BLK_PMA_PMD_PMD_CONTROL_2_REGISTER, data2,
   4699                      TLB_TX_RMT_LPBK_CONFIG, data3,
   4700                      TX_ANATXACONTROL7, data4));
   4701 
   4702                 LOG_CLI((BSL_META_U(unit,
   4703                                     "   Lane %d : link(1.%04x)=%04x,"
   4704                                     "pol(1.%04x)=%04x, Preemphasis:%08x"),
   4705                          i, RX_ANARXSTATUS, link_sts[i],
   4706                          CUR_DATAPATH(pc) == PHY82328_DATAPATH_20 ? 
   4707                          TLB_TX_TLB_TX_MISC_CONFIG : AMS_TX_TX_CTRL_0,
   4708                          pol_sts[i], preemphasis[i]));
   4709         }
   4710         LOG_CLI((BSL_META_U(unit,
   4711                             "\n")));
   4712     }
   4713     SOC_IF_ERROR_RETURN(
   4714      phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   4715     if (int_pc) {
   4716         int32 lb;
   4717         SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET(int_pc->pd, unit, port, &iif));
   4718         SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &ilink));
   4719         SOC_IF_ERROR_RETURN(phy_82328_lb_get(unit, port, &lb));
   4720         if (lb) {
   4721             /* Clear the sticky bit if in loopback */
   4722             SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &ilink));
   4723         }
   4724         SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &ispeed));
   4725         SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &ian, &ian_done));
   4726         LOG_CLI((BSL_META_U(unit,
   4727                             " Internal: type=%s, speed=%d, link=%d, an=%d\n===\n"), 
   4728                  phy82328_intf_names[iif], ispeed, ilink, ian));
   4729     }
   4730     if (saved_side == PHY82328_INTF_SIDE_SYS) {
   4731         SOC_IF_ERROR_RETURN(
   4732          phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS));
   4733     }
   4734 
   4735     return SOC_E_NONE;
   4736 }
   4737 
   4738 STATIC int32
   4739 _phy_82328_rx_los_control_get(int32 unit, soc_port_t port, uint32 *value)
   4740 {
   4741     phy_ctrl_t *pc= EXT_PHY_SW_STATE(unit, port);
   4742     *value = FW_RX_LOS(pc);
   4743     return SOC_E_NONE;
   4744 }
   4745 
   4746 /*
   4747  * Function:
   4748  *      phy_82328_control_get
   4749  * Purpose:
   4750  *      Get current control settign of the PHY.
   4751  * Parameters:
   4752  *      unit  - StrataSwitch unit #.
   4753  *      port  - StrataSwitch port #.
   4754  *      type  - Control to get
   4755  *      value - (OUT)Current setting for the control
   4756  * Returns:
   4757  *      SOC_E_NONE
   4758  */
   4759 STATIC int32
   4760 _phy_82328_control_get(int32 unit, soc_port_t port, int32 intf, int32 lane,
   4761                      soc_phy_control_t type, uint32 *value)
   4762 {
   4763     phy_ctrl_t *pc;
   4764     soc_port_t offset, primary;
   4765     int32 rv = SOC_E_UNAVAIL;    
   4766     pc = EXT_PHY_SW_STATE(unit, port);
   4767 
   4768     PHY_CONTROL_TYPE_CHECK(type);
   4769 	
   4770     if (intf == PHY_DIAG_INTF_SYS) {
   4771        SOC_IF_ERROR_RETURN(
   4772         phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS));
   4773     }
   4774     rv = SOC_E_UNAVAIL;
   4775     switch(type) {
   4776         case SOC_PHY_CONTROL_PREEMPHASIS:
   4777         case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   4778         case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   4779         case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   4780         case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   4781         /* fall through */
   4782 		rv = _phy_82328_control_preemphasis_get(unit, port, type,
   4783 												(pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   4784 												PHY82328_INTF_SIDE_SYS : PHY82328_INTF_SIDE_LINE, 
   4785 												value);
   4786 		break;
   4787         case SOC_PHY_CONTROL_DRIVER_CURRENT:
   4788         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   4789         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   4790         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   4791         case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   4792         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   4793         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   4794         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   4795         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   4796         case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   4797             /* fall through */
   4798             rv = SOC_E_UNAVAIL;
   4799         break;
   4800         case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   4801             rv = _phy_82328_control_prbs_polynomial_get(unit, port, value);
   4802         break;
   4803         case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   4804             rv = _phy_82328_control_prbs_tx_invert_data_get(unit, port, value);
   4805         break;
   4806         case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   4807            /* fall through */
   4808         case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   4809             rv = _phy_82328_control_prbs_enable_get(unit, port, value);
   4810         break;
   4811         case SOC_PHY_CONTROL_PRBS_RX_STATUS:
   4812             rv = _phy_82328_control_prbs_rx_status_get(unit, port, intf, value);
   4813         break;
   4814         case SOC_PHY_CONTROL_LOOPBACK_REMOTE_PCS_BYPASS:
   4815             rv = _phy_82328_remote_loopback_get(unit, port, value);
   4816         break;
   4817         case SOC_PHY_CONTROL_PORT_PRIMARY:
   4818             SOC_IF_ERROR_RETURN
   4819               (soc_phyctrl_primary_get(unit, port, &primary));
   4820             *value = (uint32) primary;
   4821             rv = SOC_E_NONE;
   4822         break;
   4823         case SOC_PHY_CONTROL_PORT_OFFSET:
   4824             SOC_IF_ERROR_RETURN
   4825               (soc_phyctrl_offset_get(unit, port, &offset));
   4826             *value = (uint32) offset;
   4827 		    rv = SOC_E_NONE;
   4828         break;
   4829         case SOC_PHY_CONTROL_RX_SEQ_DONE:
   4830            rv = _phy_82328_intf_link_get(unit, port, (int32*)value);
   4831         break;
   4832         case SOC_PHY_CONTROL_SOFTWARE_RX_LOS:
   4833             rv = _phy_82328_rx_los_control_get(unit, port, value);
   4834         break;
   4835 
   4836         case SOC_PHY_CONTROL_MOD_AUTO_DETECT_ENABLE:
   4837             rv = _phy_82328_mod_auto_detect_get(unit, port, value);
   4838         break;
   4839 
   4840         default:
   4841             rv = SOC_E_UNAVAIL;
   4842         break;
   4843 	}
   4844 
   4845     return rv;
   4846 }
   4847 
   4848 STATIC int32
   4849 phy_82328_control_get(int32 unit, soc_port_t port,
   4850                      soc_phy_control_t type, uint32 *value)
   4851 {
   4852     SOC_IF_ERROR_RETURN
   4853         (_phy_82328_control_get (unit, port, 
   4854                     PHY_DIAG_INTF_LINE, PHY_DIAG_LN_DFLT, type, value));
   4855  
   4856     return SOC_E_NONE;
   4857 }
   4858 
   4859 STATIC int
   4860 _phy_82328_bsc_rw(int unit, soc_port_t port, int dev_addr, int opr,
   4861                     int addr, int count, void *data_array,uint32 ram_start)
   4862 {
   4863     phy_ctrl_t  *pc;
   4864     soc_timeout_t  to;
   4865     uint16 data16;
   4866     int i;
   4867     int access_type;
   4868     int data_type;
   4869 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   4870     sal_usecs_t start;
   4871     sal_usecs_t end;
   4872 #endif
   4873 
   4874     if (!data_array) {
   4875         return SOC_E_PARAM;
   4876     }
   4877 
   4878     if (count > PHY82328_BSC_XFER_MAX) {
   4879         return SOC_E_PARAM;
   4880     }
   4881 
   4882     pc = EXT_PHY_SW_STATE(unit, port);
   4883     data_type = PHY82328_I2C_DATA_TYPE(opr);
   4884     access_type = PHY82328_I2C_ACCESS_TYPE(opr);
   4885 
   4886     if (access_type == PHY82328_I2CDEV_WRITE) {
   4887         for (i = 0; i < count; i++) {
   4888             if (data_type == PHY82328_I2C_8BIT) {
   4889                 SOC_IF_ERROR_RETURN
   4890                     (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, ram_start + i,
   4891                           ((uint8 *)data_array)[i]));
   4892             } else {  /* 16 bit */
   4893                 SOC_IF_ERROR_RETURN
   4894                     (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, ram_start + i,
   4895                           ((uint16 *)data_array)[i]));
   4896             }
   4897         }
   4898     }
   4899 
   4900     data16 = ram_start;
   4901     SOC_IF_ERROR_RETURN
   4902         (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0x8004, data16));
   4903     SOC_IF_ERROR_RETURN
   4904         (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0x8003, addr));
   4905     SOC_IF_ERROR_RETURN
   4906         (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0x8002, count));
   4907 
   4908     data16 = 1;
   4909     data16 |= (dev_addr<<9);
   4910     if (access_type == PHY82328_I2CDEV_WRITE) {
   4911         data16 |= PHY82328_WR_FREQ_400KHZ;
   4912     }
   4913 
   4914     SOC_IF_ERROR_RETURN
   4915         (WRITE_PHY82328_MMF_PMA_PMD_REG(unit,pc,0x8005,data16));
   4916 
   4917     if (access_type == PHY82328_I2CDEV_WRITE) {
   4918         data16 =  0x8000 | PHY82328_BSC_WRITE_OP;
   4919     } else {
   4920         data16 =  0x8000 | PHY82328_BSC_READ_OP;
   4921     }
   4922 
   4923     if (data_type == PHY82328_I2C_16BIT) {
   4924         data16 |= (1 << 12);
   4925     }
   4926 
   4927 	/* Select first i2c port */
   4928 	if (PHY82328_SINGLE_PORT_MODE(pc)) {
   4929 		SOC_IF_ERROR_RETURN
   4930 			(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MISC_CTRL,
   4931 											 0, MGT_TOP_CMN_CTLR_MISC_CTRL_I2C_PORT_SEL_MASK));
   4932 	} else {
   4933         SOC_IF_ERROR_RETURN
   4934             (MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, MGT_TOP_MISC_CTRL,
   4935             (pc->phy_id & 0x3), MGT_TOP_CMN_CTLR_MISC_CTRL_I2C_PORT_SEL_MASK));
   4936     }
   4937 		
   4938 	SOC_IF_ERROR_RETURN
   4939 		(WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0x8000, data16));
   4940 
   4941 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   4942     start = sal_time_usecs();
   4943 #endif
   4944     soc_timeout_init(&to, 1000000, 0);
   4945     while (!soc_timeout_check(&to)) {
   4946         SOC_IF_ERROR_RETURN
   4947             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, 0x8000, &data16));
   4948         if (((data16 & PHY82328_2W_STAT) == PHY82328_2W_STAT_COMPLETE)) {
   4949             break;
   4950         }
   4951     }
   4952 
   4953 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   4954     end = sal_time_usecs();
   4955 #endif
   4956     /* need some delays */
   4957     sal_usleep(10000);
   4958 
   4959 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   4960     LOG_INFO(BSL_LS_SOC_PHY,
   4961              (BSL_META_U(unit,
   4962                          "BSC command status %d time=%d\n"),
   4963               (data16 & PHY82328_2W_STAT), SAL_USECS_SUB(end, start)));
   4964 #endif
   4965 
   4966     if (access_type == PHY82328_I2CDEV_WRITE) {
   4967         return SOC_E_NONE;
   4968     }
   4969 
   4970     if ((data16 & PHY82328_2W_STAT) == PHY82328_2W_STAT_COMPLETE) {
   4971         for (i = 0; i < count; i++) {
   4972             SOC_IF_ERROR_RETURN
   4973                 (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, (ram_start+i), &data16));
   4974             if (data_type == PHY82328_I2C_16BIT) {
   4975                 ((uint16 *)data_array)[i] = data16;
   4976                 LOG_INFO(BSL_LS_SOC_PHY,
   4977                          (BSL_META_U(unit,
   4978                                      "%04x "), data16));
   4979             } else {
   4980                 ((uint8 *)data_array)[i] = (uint8)data16;
   4981                 LOG_INFO(BSL_LS_SOC_PHY,
   4982                          (BSL_META_U(unit,
   4983                                      "%02x "), data16));
   4984             }
   4985         }
   4986     }
   4987     return SOC_E_NONE;
   4988 }
   4989 
   4990 /*
   4991  * Read a slave device such as NVRAM/EEPROM connected to the 82328's I2C
   4992  * interface. This function will be mainly used for diagnostic or workaround
   4993  * purpose.
   4994  * Note:
   4995  * The size of read_array buffer must be greater than or equal to the
   4996  * parameter nbytes.
   4997  * usage example:
   4998  *   Retrieve the first 100 byte data of the non-volatile storage device with
   4999  *   I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0,
   5000  *   port 2.
   5001  *   uint8 data8[100];
   5002  *   phy_82328_i2cdev_read(0,2,0x50,0,100,data8);
   5003  */
   5004 int
   5005 phy_82328_i2cdev_read(int unit,
   5006                      soc_port_t port,
   5007                      int dev_addr,  /* 7 bit I2C bus device address */
   5008                      int offset,    /* starting data address to read */
   5009                      int nbytes,    /* number of bytes to read */
   5010                      uint8 *read_array)   /* buffer to hold retrieved data */
   5011 {
   5012     return _phy_82328_bsc_rw(unit, port, dev_addr, PHY82328_I2CDEV_READ,
   5013              offset, nbytes, (void *)read_array, PHY82328_READ_START_ADDR);
   5014 
   5015 }
   5016 
   5017 /*
   5018  * Write to a slave device such as NVRAM/EEPROM connected to the 82328's I2C
   5019  * interface. This function will be mainly used for diagnostic or workaround
   5020  * purpose.
   5021  * Note:
   5022  * The size of write_array buffer should be equal to the parameter nbytes.
   5023  * The EEPROM may limit the maximun write size to 16 bytes
   5024  * usage example:
   5025  *   Write to first 100 byte space of the non-volatile storage device with
   5026  *   I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0,
   5027  *   port 2, with written data specified in array data8.
   5028  *   uint8 data8[100];
   5029  *   *** initialize the data8 array with written data ***
   5030  *
   5031  *   phy_82328_i2cdev_write(0,2,0x50,0,100,data8);
   5032  */
   5033 
   5034 int
   5035 phy_82328_i2cdev_write(int unit,
   5036                      soc_port_t port,
   5037                      int dev_addr,  /* I2C bus device address */
   5038                      int offset,    /* starting data address to write to */
   5039                      int nbytes,    /* number of bytes to write */
   5040                      uint8 *write_array)   /* buffer to hold written data */
   5041 {
   5042     int j;
   5043     int rv = SOC_E_NONE;
   5044 
   5045     for (j = 0; j < (nbytes/PHY82328_BSC_WR_MAX); j++) {
   5046         rv = _phy_82328_bsc_rw(unit, port, dev_addr,PHY82328_I2CDEV_WRITE,
   5047                     offset + j * PHY82328_BSC_WR_MAX, PHY82328_BSC_WR_MAX,
   5048                     (void *)(write_array + j * PHY82328_BSC_WR_MAX),
   5049                     PHY82328_WRITE_START_ADDR);
   5050         if (rv != SOC_E_NONE) {
   5051             return rv;
   5052         }
   5053         sal_usleep(20000);
   5054     }
   5055     if (nbytes % PHY82328_BSC_WR_MAX) {
   5056         rv = _phy_82328_bsc_rw(unit, port, dev_addr,PHY82328_I2CDEV_WRITE,
   5057                 offset + j * PHY82328_BSC_WR_MAX, (nbytes % PHY82328_BSC_WR_MAX),
   5058                 (void *)(write_array + j * PHY82328_BSC_WR_MAX),
   5059                 PHY82328_WRITE_START_ADDR);
   5060     }
   5061     return rv;
   5062 }
   5063 
   5064 /*
   5065  * Function:
   5066  *      phy_82328_reg_read
   5067  * Purpose:
   5068  *      Routine to read PHY register
   5069  * Parameters:
   5070  *      uint         - BCM unit number
   5071  *      port         - port number
   5072  *      flags        - Flags which specify the register type
   5073  *      phy_reg_addr - Encoded register address
   5074  *      phy_data     - (OUT) Value read from PHY register
   5075  * Note:
   5076  *      This register read function is not thread safe. Higher level
   5077  * function that calls this function must obtain a per port lock
   5078  * to avoid overriding register page mapping between threads.
   5079  */
   5080 STATIC int32
   5081 phy_82328_reg_read(int32 unit, soc_port_t port, uint32 flags,
   5082                   uint32 phy_reg_addr, uint32 *phy_data)
   5083 {
   5084     uint16               data16;
   5085     phy_ctrl_t           *pc;      /* PHY software state */
   5086     int32                rv = SOC_E_NONE;
   5087     int32 rd_cnt = 1;
   5088     uint16 regdata = 0;
   5089 
   5090     pc = EXT_PHY_SW_STATE(unit, port);
   5091 
   5092     if (flags & SOC_PHY_I2C_DATA8) {
   5093         SOC_IF_ERROR_RETURN
   5094             (phy_82328_i2cdev_read(unit, port,
   5095                         SOC_PHY_I2C_DEVAD(phy_reg_addr),
   5096                         SOC_PHY_I2C_REGAD(phy_reg_addr),
   5097                         rd_cnt,
   5098                         (uint8 *)&data16));
   5099         *phy_data = *((uint8 *)&data16);
   5100     } else if (flags & SOC_PHY_I2C_DATA16) {
   5101         /* This operation is generally targeted to access 16-bit device,
   5102          * such as PHY IC inside the SFP.  However there is no 16-bit
   5103          * scratch register space on the device.  Use 1.800e
   5104          * for this operation.
   5105          */
   5106         SOC_IF_ERROR_RETURN
   5107             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, PHY82328_I2C_TEMP_RAM,
   5108                    &regdata));
   5109 
   5110         rv = _phy_82328_bsc_rw(unit, port,
   5111                SOC_PHY_I2C_DEVAD(phy_reg_addr),
   5112                PHY82328_I2C_OP_TYPE(PHY82328_I2CDEV_READ, PHY82328_I2C_16BIT),
   5113                SOC_PHY_I2C_REGAD(phy_reg_addr), 1,
   5114                (void *)&data16, PHY82328_I2C_TEMP_RAM);
   5115 
   5116         *phy_data = data16;
   5117 
   5118         /* restore the ram register value */
   5119         SOC_IF_ERROR_RETURN
   5120             (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, PHY82328_I2C_TEMP_RAM,
   5121                  regdata));
   5122     } else {
   5123         SOC_IF_ERROR_RETURN
   5124             (READ_PHY_REG(unit, pc, phy_reg_addr, &data16));
   5125         *phy_data = data16;
   5126     }
   5127     return rv;
   5128 }
   5129 
   5130 /*
   5131  * Function:
   5132  *      phy_82328_reg_write
   5133  * Purpose:
   5134  *      Routine to write PHY register
   5135  * Parameters:
   5136  *      uint         - BCM unit number
   5137  *      port         - port number
   5138  *      flags        - Flags which specify the register type
   5139  *      phy_reg_addr - Encoded register address
   5140  *      phy_data     - Value write to PHY register
   5141  * Note:
   5142  *      This register read function is not thread safe. Higher level
   5143  * function that calls this function must obtain a per port lock
   5144  * to avoid overriding register page mapping between threads.
   5145  */
   5146 STATIC int32
   5147 phy_82328_reg_write(int32 unit, soc_port_t port, uint32 flags,
   5148                    uint32 phy_reg_addr, uint32 phy_data)
   5149 {
   5150     phy_ctrl_t          *pc;      /* PHY software state */
   5151     int32 rv = SOC_E_NONE;
   5152     uint8  data8[4];
   5153     uint16 data16[2];
   5154     uint16 regdata[2];
   5155     int32 wr_cnt = 1;
   5156 
   5157     pc = EXT_PHY_SW_STATE(unit, port);
   5158  
   5159     if (flags & SOC_PHY_I2C_DATA8) {
   5160         data8[0] = (uint8)phy_data;
   5161         SOC_IF_ERROR_RETURN
   5162             (phy_82328_i2cdev_write(unit, port,
   5163                         SOC_PHY_I2C_DEVAD(phy_reg_addr),
   5164                         SOC_PHY_I2C_REGAD(phy_reg_addr),
   5165                         wr_cnt,
   5166                         data8));
   5167 
   5168     } else if (flags & SOC_PHY_I2C_DATA16) {
   5169         /* This operation is generally targeted to access 16-bit device,
   5170          * such as PHY IC inside the SFP.  However there is no 16-bit
   5171          * scratch register space on the device.  Use 1.800e
   5172          * for this operation.
   5173          */
   5174         /* save the temp ram register */
   5175         SOC_IF_ERROR_RETURN
   5176             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, PHY82328_I2C_TEMP_RAM,
   5177                  &regdata[0]));
   5178         data16[0] = phy_data;
   5179         rv = _phy_82328_bsc_rw(unit, port,
   5180               SOC_PHY_I2C_DEVAD(phy_reg_addr),
   5181               PHY82328_I2C_OP_TYPE(PHY82328_I2CDEV_WRITE, PHY82328_I2C_16BIT),
   5182               SOC_PHY_I2C_REGAD(phy_reg_addr),wr_cnt,
   5183               (void *)data16, PHY82328_I2C_TEMP_RAM);
   5184 
   5185         /* restore the ram register value */
   5186         SOC_IF_ERROR_RETURN
   5187             (WRITE_PHY82328_MMF_PMA_PMD_REG(unit, pc, PHY82328_I2C_TEMP_RAM,
   5188                   regdata[0]));
   5189     } else {
   5190             SOC_IF_ERROR_RETURN
   5191                 (WRITE_PHY_REG (unit, pc, phy_reg_addr, 
   5192                                       (uint16)phy_data));
   5193     }
   5194     return rv;
   5195 }
   5196 
   5197 /*
   5198  * Function:
   5199  *      phy_82328_probe
   5200  * Purpose:
   5201  *      Complement the generic phy probe routine to identify this phy when its
   5202  *      phy id0 and id1 is same as some other phy's.
   5203  * Parameters:
   5204  *      unit - StrataSwitch unit #.
   5205  *      pc   - phy ctrl descriptor.
   5206  * Returns:
   5207  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   5208  */
   5209 STATIC int32
   5210 phy_82328_probe(int32 unit, phy_ctrl_t *pc)
   5211 {
   5212     uint32 devid;
   5213     uint16 chip_rev;
   5214     SOC_IF_ERROR_RETURN(_phy_82328_config_devid(pc->unit, pc->port, pc, &devid));
   5215     SOC_IF_ERROR_RETURN(
   5216         READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   5217                                       MGT_TOP_CHIP_REV_REGISTER,
   5218                                       &chip_rev));
   5219     if (devid == PHY82328_ID_82328) {
   5220         if (chip_rev == PHY82328A0_CHIP_REV) {
   5221             LOG_INFO(BSL_LS_SOC_PHY,
   5222                      (BSL_META_U(unit,
   5223                                  "PHY82328 Dev found")));
   5224             pc->dev_name = dev_name_82328_a0;
   5225         } else if (chip_rev == PHY82328B0_CHIP_REV) {
   5226             LOG_INFO(BSL_LS_SOC_PHY,
   5227                      (BSL_META_U(unit,
   5228                                  "PHY82328 B0 Dev found")));
   5229             pc->dev_name = dev_name_82328_b0;
   5230         } else if (chip_rev == PHY82328B1_CHIP_REV) {
   5231             LOG_INFO(BSL_LS_SOC_PHY,
   5232                      (BSL_META_U(unit,
   5233                                  "PHY82328 B1 Dev found")));
   5234             pc->dev_name = dev_name_82328_b1;
   5235         }
   5236 
   5237     } else if (devid == PHY82328_ID_82328F) {
   5238         if (chip_rev == PHY82328A0_CHIP_REV) {
   5239             LOG_INFO(BSL_LS_SOC_PHY,
   5240                      (BSL_META_U(unit,
   5241                                  "PHY82328F A0 Dev found")));
   5242             pc->dev_name = dev_name_82328f_a0;
   5243         } else if (chip_rev == PHY82328B0_CHIP_REV) {
   5244             LOG_INFO(BSL_LS_SOC_PHY,
   5245                      (BSL_META_U(unit,
   5246                                   "PHY82328F B0 Dev found")));
   5247             pc->dev_name = dev_name_82328f_b0;
   5248         } else if (chip_rev == PHY82328B1_CHIP_REV) {
   5249             LOG_INFO(BSL_LS_SOC_PHY,
   5250                      (BSL_META_U(unit,
   5251                                   "PHY82328F B1 Dev found")));
   5252             pc->dev_name = dev_name_82328f_b1;
   5253         }
   5254 
   5255     } else if (devid == PHY82328_ID_82322) {
   5256         if (chip_rev == PHY82328B1_CHIP_REV) { 
   5257             pc->dev_name = dev_name_82322_b1;
   5258         } else {
   5259             pc->dev_name = dev_name_82322;
   5260         }
   5261     } else {  /* not found */
   5262         LOG_WARN(BSL_LS_SOC_PHY,
   5263                  (BSL_META_U(unit,
   5264                              "port %d: BCM82xxx type PHY device detected, please use "
   5265                              "phy_82<xxx> config variable to select the specific type\n"),
   5266                   pc->port));
   5267         return SOC_E_NOT_FOUND;
   5268     }
   5269     pc->size = sizeof(phy82328_dev_desc_t);
   5270     return SOC_E_NONE;
   5271 }
   5272 
   5273 /*
   5274  * Function:
   5275  *      phy_82328_ability_advert_set
   5276  * Purpose:
   5277  *      Set the current advertisement for auto-negotiation.
   5278  * Parameters:
   5279  *      unit - StrataSwitch unit #.
   5280  *      port - StrataSwitch port #.
   5281  *      mode - Port mode mask indicating supported options/speeds.
   5282  * Returns:
   5283  *      SOC_E_XXX
   5284  * Notes:
   5285  *      The advertisement is set only for the ACTIVE medium.
   5286  *      No synchronization performed at this level.
   5287  */
   5288  
   5289 STATIC int32
   5290 phy_82328_ability_advert_set(int32 unit, soc_port_t port,
   5291                               soc_port_ability_t *ability)
   5292 {
   5293     uint16 pause;
   5294     phy_ctrl_t  *pc, *int_pc;
   5295     phy82328_intf_cfg_t *line_intf;
   5296 
   5297     LOG_INFO(BSL_LS_SOC_PHY,
   5298              (BSL_META_U(unit,
   5299                          "82328 Ablity advert Set\n")));
   5300     if (ability == NULL) {
   5301         return SOC_E_PARAM;
   5302     }
   5303 	pc = EXT_PHY_SW_STATE(unit, port);
   5304     
   5305     line_intf = &(LINE_INTF(pc));
   5306     if ((line_intf->type == SOC_PORT_IF_KX) || (line_intf->type == SOC_PORT_IF_GMII)) {
   5307         int_pc = INT_PHY_SW_STATE(unit, port);
   5308         if (int_pc) {
   5309             SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_SET(int_pc->pd, unit, port, ability));
   5310         }
   5311         return SOC_E_NONE;
   5312     }
   5313 	
   5314     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   5315         case SOC_PA_PAUSE_TX: /*7.0x0010.10 1*/
   5316             pause = (1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT);
   5317 		break;
   5318         case SOC_PA_PAUSE_RX: /*7.0x0010.11:10 1*/
   5319             pause = (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)) |
   5320 		            (1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT);
   5321         break;
   5322         case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: /*7.0x0010.11 1*/
   5323             pause = (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1));
   5324         break;
   5325         default:
   5326             pause = 0;
   5327         break;
   5328     }
   5329 
   5330     SOC_IF_ERROR_RETURN
   5331         (MODIFY_PHY82328_MMF_AN_REG(unit, pc, 
   5332          IEEE1_AN_BLK_AN_ADVERTISEMENT_1_REGISTER,
   5333          pause, QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_MASK)); 
   5334     LOG_INFO(BSL_LS_SOC_PHY,
   5335              (BSL_META_U(unit,
   5336                          "phy_82328_ability_advert_set: u=%d p=%d speed(FD)=%x pause=0x%x\n"),
   5337               unit, port, ability->speed_full_duplex, ability->pause));
   5338     return SOC_E_NONE;
   5339 }
   5340 
   5341 /*
   5342  * Function:
   5343  *      phy_82328_ability_advert_get
   5344  * Purpose:
   5345  *      Get the current advertisement for auto-negotiation.
   5346  * Parameters:
   5347  *      unit - StrataSwitch unit #.
   5348  *      port - StrataSwitch port #.
   5349  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   5350  * Returns:
   5351  *      SOC_E_XXX
   5352  * Notes:
   5353  *      The advertisement is retrieved for the ACTIVE medium.
   5354  *      No synchronization performed at this level.
   5355  */
   5356  
   5357 STATIC int32
   5358 phy_82328_ability_advert_get(int32 unit, soc_port_t port,
   5359                            soc_port_ability_t *ability)
   5360 {
   5361     phy_ctrl_t  *pc, *int_pc;
   5362     uint16 pause_adv;
   5363     phy82328_intf_cfg_t *line_intf;
   5364 
   5365     soc_port_mode_t mode = 0;        
   5366     if (ability == NULL) {
   5367         return SOC_E_PARAM;
   5368     } 
   5369     sal_memset(ability, 0, sizeof(soc_port_ability_t)); 
   5370     pc = EXT_PHY_SW_STATE(unit, port);
   5371     int_pc = INT_PHY_SW_STATE(unit, port);
   5372     line_intf = &(LINE_INTF(pc));
   5373 
   5374     if ((line_intf->type == SOC_PORT_IF_KX) || (line_intf->type == SOC_PORT_IF_GMII)) {
   5375         int_pc = INT_PHY_SW_STATE(unit, port);
   5376         if (int_pc) {
   5377             SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_GET(int_pc->pd, unit, port, ability));
   5378         }
   5379         return SOC_E_NONE;
   5380     }
   5381 
   5382     if(PHY82328_SINGLE_PORT_MODE(pc)) {
   5383         ability->speed_full_duplex = SOC_PA_SPEED_40GB;
   5384     }
   5385     else {
   5386         ability->speed_full_duplex = SOC_PA_SPEED_10GB;
   5387     }
   5388     
   5389     SOC_IF_ERROR_RETURN
   5390         (READ_PHY82328_MMF_AN_REG
   5391          (unit, pc, IEEE1_AN_BLK_AN_ADVERTISEMENT_1_REGISTER, &pause_adv)); 
   5392     mode = 0;
   5393     
   5394     switch (pause_adv & QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_MASK) {		
   5395         case (1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT):  /*7.0x0010.10 1*/
   5396 			mode = SOC_PA_PAUSE_TX;		
   5397         break;
   5398         case (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)): /*7.0x0010.11 1*/
   5399 			mode = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   5400         break;		
   5401         case (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)) |
   5402 				(1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT):/*7.0x0010.11:10 1*/
   5403             mode = SOC_PA_PAUSE_RX;
   5404         break;		
   5405         default:
   5406             mode = 0;
   5407         break;
   5408     }
   5409     ability->pause = mode;	 
   5410     LOG_INFO(BSL_LS_SOC_PHY,
   5411              (BSL_META_U(unit,
   5412                          "phy_82328_ability_advert_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"),
   5413               unit, port, ability->speed_full_duplex, ability->pause));
   5414     return SOC_E_NONE;
   5415 }
   5416 
   5417 /*
   5418  * Function:
   5419  *      phy_82328_ability_local_get
   5420  * Purpose:
   5421  *      Get the device's complete abilities.
   5422  * Parameters:
   5423  *      unit - StrataSwitch unit #.
   5424  *      port - StrataSwitch port #.
   5425  *      ability - return device's abilities.
   5426  * Returns:
   5427  *      SOC_E_XXX
   5428  */
   5429  
   5430 STATIC int32
   5431 phy_82328_ability_local_get(int32 unit, soc_port_t port, soc_port_ability_t *ability)
   5432 {
   5433     uint32		pa_speed = 0;
   5434     phy_ctrl_t  *pc;
   5435 
   5436     pc = EXT_PHY_SW_STATE(unit, port);
   5437 	
   5438     if (ability == NULL) {
   5439         return SOC_E_PARAM;
   5440     }
   5441     sal_memset(ability, 0, sizeof(soc_port_ability_t));
   5442     pa_speed = PHY82328_SINGLE_PORT_MODE(pc) ? (SOC_PA_SPEED_40GB|SOC_PA_SPEED_42GB) :
   5443                (SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB);
   5444     ability->speed_full_duplex = pa_speed;
   5445     ability->speed_half_duplex = SOC_PA_ABILITY_NONE;
   5446     ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   5447     ability->interface = SOC_PA_INTF_XGMII;
   5448     ability->medium    = SOC_PA_MEDIUM_FIBER;
   5449     ability->loopback  = SOC_PA_LB_PHY;
   5450     ability->flags     = SOC_PA_AUTONEG;
   5451 
   5452     LOG_INFO(BSL_LS_SOC_PHY,
   5453              (BSL_META_U(unit,
   5454                          "phy_82328_ability_local_get: u=%d p=%d speed=0x%x\n"),
   5455               unit, port, ability->speed_full_duplex));
   5456                                                                                
   5457     return SOC_E_NONE;
   5458 }
   5459 
   5460 /*
   5461  * Function:
   5462  *      phy_82328_firmware_set
   5463  * Purpose:
   5464  *      program the given firmware into the SPI-ROM
   5465  * Parameters:
   5466  *      unit - StrataSwitch unit #.
   5467  *      port - StrataSwitch port #.
   5468  *      offset - offset to the data stream
   5469  *      array  - the given data
   5470  *      datalen- the data length
   5471  * Returns:
   5472  *      SOC_E_NONE
   5473  */
   5474  
   5475 STATIC int32
   5476 phy_82328_firmware_set(int32 unit, int32 port, int32 offset, uint8 *array,int32 datalen)
   5477 {
   5478     /* overload this function a littl bit if array == NULL 
   5479      * special handling for init. uCode broadcast. Internal use only 
   5480      */
   5481      uint16 chip_rev;
   5482      phy_ctrl_t *pc = (phy_ctrl_t*)NULL;
   5483      pc = EXT_PHY_SW_STATE(unit, port); 
   5484      chip_rev = DEVREV(pc);
   5485      if (array == NULL) {
   5486         if(chip_rev == PHY82328B0_CHIP_REV || chip_rev == PHY82328B1_CHIP_REV) {
   5487            return _phy_82328_rom_fw_dload (unit, port, offset, 
   5488                             phy82328B0_ucode_bin, phy82328B0_ucode_bin_len);
   5489         } else if(chip_rev == PHY82328A0_CHIP_REV) {
   5490            return _phy_82328_rom_fw_dload (unit, port, offset, 
   5491                             phy82328_ucode_bin, phy82328_ucode_bin_len);
   5492         } else {
   5493            return SOC_E_UNAVAIL; 
   5494         }
   5495     } else {
   5496         LOG_WARN(BSL_LS_SOC_PHY,
   5497                  (BSL_META_U(unit,
   5498                              "u=%d p=%d firmware download method not supported\n"),
   5499                              unit, port));
   5500         return SOC_E_UNAVAIL;
   5501     }
   5502 
   5503     return SOC_E_NONE;
   5504 }
   5505 
   5506 int32 phy82328_uc_dsc_rdy_tim_out(int32 unit, phy_ctrl_t *pc,  uint16 timeout_ms) 
   5507 {
   5508     uint16 tim_out = 0, rdy = 0;
   5509     for (tim_out = 0; tim_out < 100; tim_out ++) {
   5510         PHY82328_RD_UC_DSC_RDY_FOR_CMD(unit, pc, rdy);
   5511         if (rdy) {
   5512             return SOC_E_NONE;
   5513         }
   5514         sal_udelay(10 * timeout_ms);
   5515     }
   5516     LOG_CLI((BSL_META_U(unit,
   5517                         "UC DSC rdy timeout\n")));
   5518     return SOC_E_INTERNAL;
   5519 
   5520 }
   5521 int32 phy82328_serdes_pmd_uc_cmd(int32 unit, soc_port_t port, phy_ctrl_t *pc, uint16 cmd, uint8 supp_info, uint16 timeout) 
   5522 {
   5523 
   5524     /* Poll for uc_dsc_ready_for_cmd = 1 to indicate serdes ready for command */
   5525     SOC_IF_ERROR_RETURN(phy82328_uc_dsc_rdy_tim_out(unit, pc, timeout));
   5526    
   5527     SOC_IF_ERROR_RETURN(
   5528         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_DSC_UC_CTRL, 
   5529             (supp_info << DSC_A_DSC_UC_CTRL_UC_DSC_SUPP_INFO_SHIFT), DSC_A_DSC_UC_CTRL_UC_DSC_SUPP_INFO_MASK));
   5530     SOC_IF_ERROR_RETURN(
   5531         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_DSC_UC_CTRL, 
   5532             0x0, DSC_A_DSC_UC_CTRL_UC_DSC_ERROR_FOUND_MASK));
   5533     SOC_IF_ERROR_RETURN(
   5534         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_DSC_UC_CTRL,
   5535             cmd ,DSC_A_DSC_UC_CTRL_UC_DSC_GP_UC_REQ_MASK));
   5536 
   5537     SOC_IF_ERROR_RETURN(
   5538         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_DSC_UC_CTRL, 
   5539             0x0, DSC_A_DSC_UC_CTRL_UC_DSC_READY_FOR_CMD_MASK));
   5540   
   5541     /* Poll for uc_dsc_ready_for_cmd = 1 to indicate serdes ready for command */
   5542     SOC_IF_ERROR_RETURN(phy82328_uc_dsc_rdy_tim_out(unit, pc, timeout));
   5543 
   5544     return SOC_E_NONE;
   5545 }
   5546 
   5547 /* Micro RAM Lane Byte Read */
   5548 int32 phy82328_serdes_rdbl_uc_var(int32 unit, soc_port_t port, phy_ctrl_t *pc,  uint8 s_info, uint16 *data16) 
   5549 {
   5550     /* Each lane can have a maximum of 208 bytes in Gallardo */
   5551     if (s_info > 207) {
   5552         return SOC_E_INTERNAL;
   5553     }
   5554     *data16 = 0;
   5555 
   5556     /* Use Serdes FW DSC Command Interface for reading RAM */
   5557     SOC_IF_ERROR_RETURN(
   5558             phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_READ_UC_LANE_BYTE, s_info, 10));
   5559     SOC_IF_ERROR_RETURN
   5560             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_DSC_SCRATCH, data16));
   5561 
   5562     return SOC_E_NONE;
   5563 }
   5564 
   5565 int32 phy82328_restore_trnsum_ctrls(int32 unit, phy_ctrl_t *pc) 
   5566 {
   5567     /* DSC_D_TRNSUM_CTL_1 - Trnsum Ctl 1 */
   5568     SOC_IF_ERROR_RETURN(
   5569             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK));
   5570     SOC_IF_ERROR_RETURN(
   5571             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_ERR_SEL_MASK));
   5572     SOC_IF_ERROR_RETURN(
   5573             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_RANDOM_TAPSEL_DISABLE_MASK));
   5574     SOC_IF_ERROR_RETURN(
   5575             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_INV_PATTERN_EN_MASK));
   5576     SOC_IF_ERROR_RETURN(
   5577             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_PATTERN_FULL_CHECK_OFF_MASK));
   5578     SOC_IF_ERROR_RETURN(
   5579             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_GAIN_MASK));
   5580     SOC_IF_ERROR_RETURN(
   5581             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_EYE_CLOSURE_EN_MASK));
   5582     SOC_IF_ERROR_RETURN(
   5583         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_CDR_QPHASE_MULT_EN_MASK));
   5584     SOC_IF_ERROR_RETURN(
   5585         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_TAP_RANGE_SEL_MASK));
   5586 
   5587     /* DSC_D_TRNSUM_CTL_2 - Trnsum Ctl 2 */
   5588     SOC_IF_ERROR_RETURN(
   5589         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_2, 0, DSC_D_TRNSUM_CTL_2_TRNSUM_PATTERN_MASK));
   5590     SOC_IF_ERROR_RETURN(
   5591         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_2, 0, DSC_D_TRNSUM_CTL_2_TRNSUM_PATTERN_BIT_EN_MASK));
   5592 
   5593     /* DSC_D_TRNSUM_CTL_3 - Trnsum Ctl 3 */
   5594     SOC_IF_ERROR_RETURN(
   5595         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_3, 0, DSC_D_TRNSUM_CTL_3_TRNSUM_TAP_EN_MASK));
   5596     SOC_IF_ERROR_RETURN(
   5597         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_3, 0, DSC_D_TRNSUM_CTL_3_TRNSUM_TAP_SIGN_MASK));
   5598 
   5599     /* DSC_D_TRNSUM_CTL_4 - Trnsum Ctl 4 */
   5600     SOC_IF_ERROR_RETURN(
   5601         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TDR_TRNSUM_EN_MASK));
   5602     SOC_IF_ERROR_RETURN(
   5603         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TDR_CYCLE_BIN_MASK));
   5604     SOC_IF_ERROR_RETURN(
   5605         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TDR_CYCLE_SEL_MASK));
   5606     SOC_IF_ERROR_RETURN(
   5607         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TDR_BIT_SEL_MASK));
   5608     SOC_IF_ERROR_RETURN(
   5609         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TRNSUM_UNSIGNED_FLIP_MASK));
   5610     SOC_IF_ERROR_RETURN(
   5611         MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 0, DSC_D_TRNSUM_CTL_4_TRNSUM_UNSIGNED_CORR_MASK));
   5612 
   5613     return SOC_E_NONE;
   5614 }
   5615 
   5616 /* Configures trnsum block before calibrating the P1 slicers */
   5617 /* Desired equation is Sum of [ p(n) ] */
   5618 int32 phy82328_cfg_trnsum_for_eyediag(int32 unit, soc_port_t port, uint8 timeout) 
   5619 {
   5620     phy_ctrl_t *pc;
   5621 
   5622     pc = EXT_PHY_SW_STATE(unit, port);
   5623  
   5624     SOC_IF_ERROR_RETURN(phy82328_restore_trnsum_ctrls(unit, pc));
   5625     
   5626     /* Select d[0] */
   5627     SOC_IF_ERROR_RETURN(
   5628             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_3, 
   5629                 (PHY82328_TRNSUM_TAP_0 << DSC_D_TRNSUM_CTL_3_TRNSUM_TAP_EN_SHIFT), DSC_D_TRNSUM_CTL_3_TRNSUM_TAP_EN_MASK));
   5630 
   5631     /* Delay range 5 to -2 */
   5632     SOC_IF_ERROR_RETURN(
   5633             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 
   5634                 (PHY82328_TRNSUM_TAP_5_TO_N2 << DSC_D_TRNSUM_CTL_1_TRNSUM_TAP_RANGE_SEL_SHIFT), DSC_D_TRNSUM_CTL_1_TRNSUM_TAP_RANGE_SEL_MASK));
   5635 
   5636     /* Select error from only P1 slicer */
   5637      SOC_IF_ERROR_RETURN(
   5638             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 
   5639                 (PHY82328_TRNSUM_ERR_SEL_P1 << DSC_D_TRNSUM_CTL_1_TRNSUM_ERR_SEL_SHIFT) , DSC_D_TRNSUM_CTL_1_TRNSUM_ERR_SEL_MASK));
   5640 
   5641     /* Comparison */
   5642     SOC_IF_ERROR_RETURN(
   5643             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4,
   5644             1, DSC_D_TRNSUM_CTL_4_TRNSUM_UNSIGNED_CORR_MASK));
   5645 
   5646     /* Not equals */
   5647     SOC_IF_ERROR_RETURN(
   5648             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_4, 
   5649             (1 << DSC_D_TRNSUM_CTL_4_TRNSUM_UNSIGNED_FLIP_SHIFT) , DSC_D_TRNSUM_CTL_4_TRNSUM_UNSIGNED_FLIP_MASK));
   5650 
   5651     /* Enable the trnsum function (posedge clears) */
   5652     SOC_IF_ERROR_RETURN(
   5653             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 
   5654             (1 << DSC_D_TRNSUM_CTL_1_TRNSUM_EN_SHIFT), DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK));
   5655 
   5656     SOC_IF_ERROR_RETURN(
   5657             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_5, 
   5658                 timeout , DSC_B_DSC_SM_CTRL_5_MEASURE_TIMEOUT_MASK));
   5659     return SOC_E_NONE;
   5660 }
   5661 
   5662 
   5663 STATIC int32
   5664 _phy_82328_diag_eyescan_livelink_en(int32 unit, soc_port_t port, int32 en)
   5665 {
   5666     uint16 is_micro_stopped = 0;
   5667     phy_ctrl_t *pc;
   5668 
   5669     pc = EXT_PHY_SW_STATE(unit, port);
   5670     PHY82328_STS_IS_MICRO_STOPPED(unit, port, pc, is_micro_stopped);
   5671     if (!is_micro_stopped) {
   5672         SOC_IF_ERROR_RETURN(
   5673             phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_UC_CTRL, PHY82328_CMD_UC_CTRL_STOP_GRACEFULLY, 2000));
   5674     }
   5675      /* Enable tuning by uC */
   5676     SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_0, 
   5677             (en << DSC_B_DSC_SM_CTRL_0_UC_TUNE_EN_SHIFT), DSC_B_DSC_SM_CTRL_0_UC_TUNE_EN_MASK));
   5678     if (en) {
   5679         SOC_IF_ERROR_RETURN(phy82328_cfg_trnsum_for_eyediag(unit, port, 31));
   5680     } else {
   5681         SOC_IF_ERROR_RETURN(
   5682                 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 0, DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK));
   5683         SOC_IF_ERROR_RETURN(
   5684                 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_0, 0, DSC_B_DSC_SM_CTRL_0_UC_TRNSUM_EN_MASK));
   5685         
   5686         if (!is_micro_stopped) {
   5687             SOC_IF_ERROR_RETURN(
   5688                 phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_UC_CTRL, PHY82328_CMD_UC_CTRL_RESUME, 2000));
   5689         }
   5690     }
   5691 
   5692     return SOC_E_NONE;
   5693 }
   5694 
   5695 int32 phy82328_move_clkp1_offset(int32 unit, phy_ctrl_t *pc , int8 delta) 
   5696 {
   5697     uint8 cnt = 0;
   5698 
   5699     /* Select p1 slicer to adjust */
   5700     SOC_IF_ERROR_RETURN(
   5701             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_CONTROL, 
   5702             (2 << DSC_A_RX_PI_CONTROL_PI_SLICERS_EN_SHIFT), DSC_A_RX_PI_CONTROL_PI_SLICERS_EN_MASK));
   5703 
   5704     /* 1 for positive step   */
   5705     SOC_IF_ERROR_RETURN(
   5706             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_CONTROL, 
   5707             ((delta >0) << DSC_A_RX_PI_CONTROL_PI_PHASE_STEP_DIR_SHIFT) , DSC_A_RX_PI_CONTROL_PI_PHASE_STEP_DIR_MASK));
   5708 
   5709     /* Step set to 1 */
   5710     SOC_IF_ERROR_RETURN(
   5711             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_CONTROL, 
   5712                 1, DSC_A_RX_PI_CONTROL_PI_PHASE_STEP_CNT_MASK));
   5713     if (delta < 0) {
   5714         delta = -(delta);
   5715     }
   5716   
   5717     for (cnt=0; cnt < delta; cnt++) {
   5718         /* Increments/Decrements by 1 every strobe */
   5719         SOC_IF_ERROR_RETURN(
   5720                 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_CONTROL, 
   5721                 (1 << DSC_A_RX_PI_CONTROL_PI_MANUAL_STROBE_SHIFT), DSC_A_RX_PI_CONTROL_PI_MANUAL_STROBE_MASK));
   5722     }
   5723     return SOC_E_NONE;
   5724 }
   5725 
   5726 STATIC 
   5727 int32 phy82328_serdes_poll_dsc_state_equals_uc_tune(int32 unit, phy_ctrl_t *pc, uint32 timeout_ms) 
   5728 {
   5729   
   5730     uint16 loop, data16 = 0;
   5731     for (loop = 0; loop < 110; loop++) {
   5732         SOC_IF_ERROR_RETURN(READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   5733               DSC_B_DSC_SM_STATUS_DSC_STATE, &data16));
   5734         data16 = (data16 & DSC_B_DSC_SM_STATUS_DSC_STATE_DSC_STATE_MASK) >> DSC_B_DSC_SM_STATUS_DSC_STATE_DSC_STATE_SHIFT;
   5735         if (data16 == PHY82328_DSC_STATE_UC_TUNE) {
   5736             return (SOC_E_NONE);
   5737         }
   5738         sal_udelay(10 * timeout_ms);
   5739     }
   5740     LOG_CLI((BSL_META_U(unit,
   5741                         "uc Tune State not occured:Timeout:%d\n"),data16));
   5742     return SOC_E_INTERNAL;
   5743 }    
   5744 
   5745 STATIC int32
   5746 _phy_82328_diag_eyescan_livelink_read(int32 unit, soc_port_t port, int32 *err_counter)
   5747 {
   5748 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   5749     uint16 data1 = 0, data2 = 0;
   5750 
   5751     SOC_IF_ERROR_RETURN (
   5752             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 
   5753                 0, DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK));
   5754 
   5755     SOC_IF_ERROR_RETURN (
   5756             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 
   5757             (1 << DSC_D_TRNSUM_CTL_1_TRNSUM_EN_SHIFT), DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK));
   5758 
   5759     SOC_IF_ERROR_RETURN (
   5760             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_0, 
   5761             (1 << DSC_B_DSC_SM_CTRL_0_UC_TRNSUM_EN_SHIFT) ,DSC_B_DSC_SM_CTRL_0_UC_TRNSUM_EN_MASK));
   5762 
   5763     SOC_IF_ERROR_RETURN(
   5764               phy82328_serdes_poll_dsc_state_equals_uc_tune(unit, pc, 2000));
   5765     
   5766     SOC_IF_ERROR_RETURN (
   5767             READ_PHY82328_MMF_PMA_PMD_REG (unit, pc, DSC_D_TRNSUM_STS_5, &data1));
   5768     SOC_IF_ERROR_RETURN (
   5769             READ_PHY82328_MMF_PMA_PMD_REG (unit, pc, DSC_D_TRNSUM_STS_6, &data2));
   5770     data2 &= 0x3ff;
   5771     *err_counter = (data1 << 10) | data2;
   5772     SOC_IF_ERROR_RETURN(
   5773                 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_CONTROL, 
   5774                 (1 << DSC_A_RX_PI_CONTROL_PI_MANUAL_STROBE_SHIFT), DSC_A_RX_PI_CONTROL_PI_MANUAL_STROBE_MASK));
   5775     return SOC_E_NONE;
   5776 
   5777 }
   5778 
   5779 STATIC int32
   5780 _phy_82328_diag_eyescan_hoffset_set(int32 unit, soc_port_t port, int32 hoffset)
   5781 {
   5782     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   5783     
   5784     /* Setup the P1 slicer vertical level  */
   5785     /* Configure dfe_vga_write_tapsel to p1_eyediag mode  */
   5786     SOC_IF_ERROR_RETURN(
   5787                 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_C_DFE_VGA_OVERRIDE, 
   5788                 (0xd << DSC_C_DFE_VGA_OVERRIDE_DFE_VGA_WRITE_TAPSEL_SHIFT) , DSC_C_DFE_VGA_OVERRIDE_DFE_VGA_WRITE_TAPSEL_MASK));
   5789 
   5790     /* dfe_vga_write_val[8:3] are used to drive the analog control port. */
   5791     SOC_IF_ERROR_RETURN(
   5792                MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_C_DFE_VGA_OVERRIDE,  
   5793                    ((-(hoffset))<< 3), DSC_C_DFE_VGA_OVERRIDE_DFE_VGA_WRITE_VAL_MASK));
   5794 
   5795      /* Enable f/w to write the tap values */
   5796     SOC_IF_ERROR_RETURN(
   5797                MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_C_DFE_VGA_OVERRIDE, 
   5798                    (1 << DSC_C_DFE_VGA_OVERRIDE_DFE_VGA_WRITE_EN_SHIFT), DSC_C_DFE_VGA_OVERRIDE_DFE_VGA_WRITE_EN_MASK));
   5799     
   5800     SOC_IF_ERROR_RETURN(phy82328_move_clkp1_offset(unit, pc, -32));
   5801     SOC_IF_ERROR_RETURN(phy82328_move_clkp1_offset(unit, pc, 1));
   5802 
   5803 	return SOC_E_NONE;
   5804 }
   5805 
   5806 STATIC int32
   5807 _phy_82328_diag_eyescan(int32 unit, soc_port_t port, uint32 inst)
   5808 {
   5809     int32 lane;
   5810     int32 intf;
   5811     phy82328_intf_side_t side;
   5812 	int32 rv = SOC_E_NONE, hoffset = 0, voffset = 0, err = 0;
   5813     int32 limits[7] = {1835008, 183501, 18350, 1835, 184, 18, 2};
   5814     int8 num_limit = 0;
   5815 
   5816     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   5817     intf = PHY_DIAG_INST_INTF(inst);
   5818     if (intf == PHY_DIAG_INTF_SYS) {
   5819         side = PHY82328_INTF_SIDE_SYS;
   5820         SOC_IF_ERROR_RETURN(
   5821 		   phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_SYS));
   5822 	} else {
   5823         side = PHY82328_INTF_SIDE_LINE;
   5824     }
   5825     lane = PHY_DIAG_INST_LN(inst);
   5826     if (PHY82328_SINGLE_PORT_MODE(pc) && (lane != 0)) {
   5827         SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, lane));
   5828     }
   5829     
   5830     SOC_IF_ERROR_RETURN(
   5831         _phy_82328_diag_eyescan_livelink_en(unit, port, 1));
   5832 
   5833     LOG_CLI((BSL_META_U(unit,
   5834                         "Fast eyescan under Processing")));
   5835     for (hoffset = 31; hoffset>=-31; hoffset--) {
   5836         rv = _phy_82328_diag_eyescan_hoffset_set(unit, port, hoffset);
   5837         if (SOC_FAILURE(rv)) {
   5838             LOG_ERROR(BSL_LS_SOC_PHY,
   5839                       (BSL_META_U(unit,
   5840                                   "82328 failed in HOFFSET SET: u=%d p=%d err=%d\n"),
   5841                                   unit, port, rv));
   5842             goto eye_fail;
   5843         }
   5844 
   5845         for (voffset=-31; voffset < 32; voffset++) {
   5846             rv = _phy_82328_diag_eyescan_livelink_read(unit, port, &err);
   5847             if (SOC_FAILURE(rv)) {
   5848                 LOG_ERROR(BSL_LS_SOC_PHY,
   5849                           (BSL_META_U(unit,
   5850                                       "82328 failed in Read BER: u=%d p=%d err=%d\n"),
   5851                                       unit, port, rv));
   5852                 goto eye_fail;
   5853             }
   5854             eye_consol_val[hoffset+31][voffset+31] = err;
   5855         }
   5856         LOG_CLI((BSL_META_U(unit,
   5857                             ".")));
   5858         SOC_IF_ERROR_RETURN(phy82328_move_clkp1_offset(unit, pc, -32));
   5859     }
   5860     LOG_CLI((BSL_META_U(unit,
   5861                         "\n\n")));
   5862     LOG_CLI((BSL_META_U(unit,
   5863                         "-30  -25  -20  -15  -10  -5    0    5    10   15   20   25   30\n")));
   5864     LOG_CLI((BSL_META_U(unit,
   5865                         "-|----|----|----|----|----|----|----|----|----|----|----|----|-\n")));
   5866     
   5867     for (hoffset = 31; hoffset >=-31; hoffset = hoffset - 1) {
   5868         for (voffset = -31; voffset < 32; voffset++) {
   5869             err = eye_consol_val[hoffset+31][voffset+31];
   5870             for (num_limit = 0; num_limit < 7; num_limit++) {
   5871                 if (err >= limits[num_limit]) {
   5872                      LOG_CLI((BSL_META_U(unit,
   5873                                          "%c"), '0' + num_limit + 1));
   5874                      break;
   5875                 }
   5876             }
   5877             if (num_limit == 7) {
   5878                  if ((voffset % 5 )== 0 && (hoffset % 5)==0) {
   5879                      LOG_CLI((BSL_META_U(unit,
   5880                                          "+")));
   5881                  } else if ((voffset % 5)!=0 && (hoffset % 5)==0) {
   5882                      LOG_CLI((BSL_META_U(unit,
   5883                                          "-")));
   5884                  } else if ((voffset % 5)==0 && (hoffset % 5)!=0) {
   5885                      LOG_CLI((BSL_META_U(unit,
   5886                                          ":")));
   5887                  } else {
   5888                      LOG_CLI((BSL_META_U(unit,
   5889                                          " ")));
   5890                  }
   5891             }
   5892         }
   5893         LOG_CLI((BSL_META_U(unit,
   5894                             "\n")));
   5895     }
   5896     LOG_CLI((BSL_META_U(unit,
   5897                         "\n-|----|----|----|----|----|----|----|----|----|----|----|----|-\n")));
   5898     LOG_CLI((BSL_META_U(unit,
   5899                         "-30  -25  -20  -15  -10  -5    0    5    10   15   20   25   30\n")));
   5900 
   5901 eye_fail:
   5902     SOC_IF_ERROR_RETURN(MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_0, 
   5903             0, DSC_B_DSC_SM_CTRL_0_UC_TUNE_EN_MASK));
   5904     SOC_IF_ERROR_RETURN (
   5905             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_TRNSUM_CTL_1, 
   5906                 0, DSC_D_TRNSUM_CTL_1_TRNSUM_EN_MASK));
   5907     SOC_IF_ERROR_RETURN (
   5908             MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_B_DSC_SM_CTRL_0, 
   5909             (0 << DSC_B_DSC_SM_CTRL_0_UC_TRNSUM_EN_SHIFT) ,DSC_B_DSC_SM_CTRL_0_UC_TRNSUM_EN_MASK));
   5910     SOC_IF_ERROR_RETURN(
   5911             phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_UC_CTRL, 
   5912                 PHY82328_CMD_UC_CTRL_RESUME, 2000));
   5913     if (PHY82328_SINGLE_PORT_MODE(pc) && (lane != 0)) {
   5914         SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, PHY82328_INTF_SIDE_LINE,
   5915                                                       PHY82328_ALL_LANES));
   5916     }
   5917     if (intf == PHY_DIAG_INTF_SYS) {
   5918         SOC_IF_ERROR_RETURN(
   5919 		 phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   5920 	}
   5921 	return rv;
   5922 }
   5923 
   5924 /*
   5925  * Function:
   5926  *      _phy_82328_diag_dsc 
   5927  * Purpose:
   5928  *      Diag function for DSC .
   5929  * Parameters:
   5930  *      unit  - StrataSwitch unit #.
   5931  *      port  - StrataSwitch port #.
   5932  *      intf - line/system
   5933  *      lane - lane number 
   5934  *      type  - Control to update
   5935  * Returns:
   5936  *      SOC_E_NONE
   5937  */
   5938 STATIC int32 
   5939 _phy_82328_diag_dsc(int32 unit, soc_port_t port, int32 intf, int32 lane)
   5940 {
   5941     int32	 i, lanes;
   5942     uint16 data16 = 0;
   5943     int16 temp = 0;
   5944     uint16 is_micro_stopped = 0;
   5945     phy_ctrl_t *pc;
   5946 	phy82328_intf_side_t side;
   5947 	phy82328_serdes_lane_state *dsc_cbp;
   5948 	phy82328_serdes_lane_state dsc_cb[PHY82328_NUM_LANES];
   5949     pc = EXT_PHY_SW_STATE(unit, port);
   5950 
   5951 	if (PHY82328_SINGLE_PORT_MODE(pc)) {
   5952         lanes = PHY82328_NUM_LANES;
   5953     }
   5954     else {
   5955         lanes = 1;
   5956     }
   5957 	side =  (intf == PHY_DIAG_INTF_LINE) ? PHY82328_INTF_SIDE_LINE :
   5958 		PHY82328_INTF_SIDE_SYS;
   5959     sal_memset(dsc_cb, 0, (sizeof(dsc_cb)));
   5960     PHY82328_STS_IS_MICRO_STOPPED(unit, port, pc, is_micro_stopped);
   5961     if (!is_micro_stopped) {
   5962         SOC_IF_ERROR_RETURN(
   5963             phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_UC_CTRL, PHY82328_CMD_UC_CTRL_STOP_GRACEFULLY, 2000));
   5964     }
   5965 
   5966     SOC_IF_ERROR_RETURN(
   5967 	  phy82328_intf_side_reg_select(unit, port, side));
   5968     for (i = 0; i < lanes; i++) {
   5969 		if (PHY82328_SINGLE_PORT_MODE(pc)) {
   5970             /* Select the lane and side to access */
   5971             SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, i));
   5972         }
   5973         dsc_cbp = &(dsc_cb[i]);
   5974         SOC_IF_ERROR_RETURN
   5975             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, CKRST_CTRL_OSR_MODE_STATUS, &data16));
   5976         dsc_cbp->osr_mode = data16 & CKRST_CTRL_OSR_MODE_STATUS_ST_OSR_MODE_MASK;
   5977  
   5978         SOC_IF_ERROR_RETURN 
   5979            (phy82328_serdes_rdbl_uc_var (unit, port, pc, 0x0, &data16));
   5980         dsc_cbp->ucv_config = (data16 & 0xff) << 8;
   5981         SOC_IF_ERROR_RETURN 
   5982            (phy82328_serdes_rdbl_uc_var (unit, port, pc, 0x1, &data16));
   5983         dsc_cbp->ucv_config |= (data16 & 0xff);
   5984 
   5985         SOC_IF_ERROR_RETURN
   5986             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, SIGDET_SIGDET_STATUS_0, &data16));
   5987         dsc_cbp->sig_det = (data16 & SIGDET_SIGDET_STATUS_0_SIGNAL_DETECT_MASK); 
   5988         
   5989         SOC_IF_ERROR_RETURN
   5990             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TLB_RX_PMD_RX_LOCK_STATUS, &data16));
   5991         dsc_cbp->rx_lock = (data16 & TLB_RX_PMD_RX_LOCK_STATUS_PMD_RX_LOCK_MASK);
   5992 
   5993         SOC_IF_ERROR_RETURN
   5994             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_CDR_STATUS_INTEG_REG, &data16));
   5995         temp = (int16) data16;
   5996         temp <<= (15 -15); 
   5997         temp >>= (15 - 15 + 0);
   5998 
   5999         dsc_cbp->rx_ppm = (temp/84);
   6000         
   6001         SOC_IF_ERROR_RETURN
   6002             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_RX_PI_DIFF_BIN, &data16));
   6003         dsc_cbp->clk90 = (data16 & DSC_A_RX_PI_DIFF_BIN_CNT_D_MINUS_M1_MASK); 
   6004         dsc_cbp->clkp1 = (data16 & DSC_A_RX_PI_DIFF_BIN_CNT_D_MINUS_P1_MASK) 
   6005                          >> DSC_A_RX_PI_DIFF_BIN_CNT_D_MINUS_P1_SHIFT;
   6006                          
   6007         /* drop the MSB, the result is actually valid modulo 128 */
   6008         /* Also flip the sign to account for d-m1, versus m1-d */
   6009         dsc_cbp->clk90 = dsc_cbp->clk90 << 1;
   6010         dsc_cbp->clk90 = -(dsc_cbp->clk90 >> 1);
   6011         dsc_cbp->clkp1 = dsc_cbp->clkp1 << 1;
   6012         dsc_cbp->clkp1 = -(dsc_cbp->clkp1 >> 1);
   6013 
   6014         SOC_IF_ERROR_RETURN
   6015             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_A_CDR_CONTROL_0, &data16));
   6016         dsc_cbp->br_pd_en = (data16 & DSC_A_CDR_CONTROL_0_BR_PD_EN_MASK) >>
   6017                          DSC_A_CDR_CONTROL_0_BR_PD_EN_SHIFT;
   6018 
   6019         SOC_IF_ERROR_RETURN
   6020             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_PF_CTRL, &data16));
   6021         dsc_cbp->pf_main = (data16 & DSC_E_DSC_E_PF_CTRL_PF_CTRL_MASK);
   6022 
   6023         SOC_IF_ERROR_RETURN
   6024             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_CTRL, &data16));
   6025         dsc_cbp->pf_hiz = (data16 & DSC_E_DSC_E_CTRL_PF_HIZ_MASK) >>
   6026                            DSC_E_DSC_E_CTRL_PF_HIZ_SHIFT;
   6027         
   6028         SOC_IF_ERROR_RETURN
   6029             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_PF2_LOWP_CTRL, &data16));
   6030         dsc_cbp->pf_low = (data16 & DSC_E_DSC_E_PF2_LOWP_CTRL_PF2_LOWP_CTRL_MASK);
   6031 
   6032         SOC_IF_ERROR_RETURN
   6033             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_VGA_P1EYEDIAG_STS, &data16));
   6034         dsc_cbp->vga = (data16 & DSC_D_VGA_P1EYEDIAG_STS_VGA_BIN_MASK);
   6035         temp = (int16)data16;
   6036         PHY82328_CONV_SIGNED_BYTE(temp, 13, 8);
   6037         dsc_cbp->p1_lvl_ctrl = -(temp);
   6038 
   6039         SOC_IF_ERROR_RETURN
   6040             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_DC_OFFSET, &data16));
   6041         temp = (int16)data16;
   6042         PHY82328_CONV_SIGNED_BYTE(temp, 6, 0);
   6043         dsc_cbp->dc_offset = temp;
   6044         
   6045         SOC_IF_ERROR_RETURN
   6046             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, AMS_RX_RX_CTRL_5, &data16));
   6047         dsc_cbp->pf_bst = ((data16 & AMS_RX_RX_CTRL_5_PKBST_MASK) >> AMS_RX_RX_CTRL_5_PKBST_SHIFT);
   6048 
   6049         SOC_IF_ERROR_RETURN
   6050             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_DFE_1_STS, &data16));
   6051 
   6052         dsc_cbp->dfe1 = (((data16 & DSC_D_DFE_1_STS_DFE_1_E_MASK) >> DSC_D_DFE_1_STS_DFE_1_E_SHIFT) +
   6053                          (data16 & DSC_D_DFE_1_STS_DFE_1_CMN_MASK));
   6054         dsc_cbp->dfe1_dcd = (((data16 & DSC_D_DFE_1_STS_DFE_1_E_MASK) >> DSC_D_DFE_1_STS_DFE_1_E_SHIFT) -
   6055                              ((data16 & DSC_D_DFE_1_STS_DFE_1_O_MASK) >> DSC_D_DFE_1_STS_DFE_1_O_SHIFT)); 
   6056         SOC_IF_ERROR_RETURN
   6057             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_DFE_2_STS, &data16));
   6058 
   6059         dsc_cbp->dfe2 = (((data16 & DSC_D_DFE_2_STS_DFE_2_SE_MASK) >> DSC_D_DFE_2_STS_DFE_2_SE_SHIFT) ?
   6060                         -(((data16 & DSC_D_DFE_2_STS_DFE_2_E_MASK) >> DSC_D_DFE_2_STS_DFE_2_E_SHIFT) +
   6061                                                            (data16 & DSC_D_DFE_2_STS_DFE_2_CMN_MASK)) : 
   6062                         (((data16 & DSC_D_DFE_2_STS_DFE_2_E_MASK) >> DSC_D_DFE_2_STS_DFE_2_E_SHIFT) +
   6063                                                           (data16 & DSC_D_DFE_2_STS_DFE_2_CMN_MASK)));
   6064 
   6065 
   6066         dsc_cbp->dfe2_dcd = (((data16 & DSC_D_DFE_2_STS_DFE_2_SE_MASK) >> DSC_D_DFE_2_STS_DFE_2_SE_SHIFT) ?
   6067                             -((data16 & DSC_D_DFE_2_STS_DFE_2_E_MASK) >> DSC_D_DFE_2_STS_DFE_2_E_SHIFT) :
   6068                              ((data16 & DSC_D_DFE_2_STS_DFE_2_E_MASK) >> DSC_D_DFE_2_STS_DFE_2_E_SHIFT)) - 
   6069                             (((data16 & DSC_D_DFE_2_STS_DFE_2_SO_MASK) >> DSC_D_DFE_2_STS_DFE_2_SO_SHIFT) ?
   6070                             -((data16 & DSC_D_DFE_2_STS_DFE_2_O_MASK) >> DSC_D_DFE_2_STS_DFE_2_O_SHIFT) :
   6071                              ((data16 & DSC_D_DFE_2_STS_DFE_2_O_MASK) >> DSC_D_DFE_2_STS_DFE_2_O_SHIFT));
   6072 
   6073         SOC_IF_ERROR_RETURN
   6074             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_DFE_3_4_5_STS, &data16));
   6075         temp = (int16)data16;
   6076         PHY82328_CONV_SIGNED_BYTE(temp, 5, 0);
   6077         dsc_cbp->dfe3 = temp;
   6078 
   6079         SOC_IF_ERROR_RETURN
   6080             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_DFE_3_4_5_STS, &data16));
   6081         temp = (int16)data16;
   6082         PHY82328_CONV_SIGNED_BYTE(temp, 10, 6);
   6083         dsc_cbp->dfe4 = temp;
   6084 
   6085         SOC_IF_ERROR_RETURN
   6086             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_D_DFE_3_4_5_STS, &data16));
   6087         temp = (int16)data16;
   6088         PHY82328_CONV_SIGNED_BYTE(temp, 15, 11);
   6089         dsc_cbp->dfe5 = temp;
   6090 
   6091         SOC_IF_ERROR_RETURN
   6092             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_P1_EVEN, &data16));
   6093         temp = (int16)data16;
   6094         PHY82328_CONV_SIGNED_BYTE(temp, 5, 0);
   6095         dsc_cbp->pe = (4*temp) - 30;
   6096         
   6097         SOC_IF_ERROR_RETURN
   6098             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_DATA_EVEN, &data16));
   6099         temp = (int16)data16;
   6100         PHY82328_CONV_SIGNED_BYTE(temp, 5, 0);
   6101         dsc_cbp->ze = (4*temp) - 30;
   6102 
   6103         SOC_IF_ERROR_RETURN
   6104             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_M1_EVEN, &data16));
   6105         temp = (int16)data16;
   6106         PHY82328_CONV_SIGNED_BYTE(temp, 5, 0);
   6107         dsc_cbp->me = (4*temp) - 30;
   6108 
   6109         SOC_IF_ERROR_RETURN
   6110             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_P1_ODD, &data16));
   6111         temp = (int16)data16;
   6112         PHY82328_CONV_SIGNED_BYTE(temp, 5, 0);
   6113         dsc_cbp->po = (4*temp) - 30;
   6114 
   6115         SOC_IF_ERROR_RETURN
   6116             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_DATA_ODD, &data16));
   6117         temp = (int16)data16;
   6118         PHY82328_CONV_SIGNED_BYTE(temp, 5, 0);
   6119         dsc_cbp->zo = (4*temp) - 30;
   6120 
   6121         SOC_IF_ERROR_RETURN
   6122             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, DSC_E_DSC_E_OFFSET_ADJ_M1_ODD, &data16));
   6123         temp = (int16)data16;
   6124         PHY82328_CONV_SIGNED_BYTE(temp, 5, 0);
   6125         dsc_cbp->mo = (4*temp) - 30;
   6126 
   6127         SOC_IF_ERROR_RETURN
   6128             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_PI_TX_PI_STATUS_1, &data16));
   6129         dsc_cbp->tx_ppm = data16/21;
   6130 
   6131         SOC_IF_ERROR_RETURN
   6132             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_STATUS1, &data16));
   6133         dsc_cbp->txfir_pre = data16 & TX_FED_TXFIR_STATUS1_TXFIR_PRE_AFTER_OVR_MASK;
   6134 
   6135         SOC_IF_ERROR_RETURN
   6136             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_STATUS2, &data16));
   6137         dsc_cbp->txfir_main = data16 & TX_FED_TXFIR_STATUS2_TXFIR_MAIN_AFTER_OVR_MASK;
   6138 
   6139         SOC_IF_ERROR_RETURN
   6140             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_STATUS1, &data16));
   6141         dsc_cbp->txfir_post1 = (data16 & TX_FED_TXFIR_STATUS1_TXFIR_POST_AFTER_OVR_MASK) >>
   6142                               TX_FED_TXFIR_STATUS1_TXFIR_POST_AFTER_OVR_SHIFT;
   6143         
   6144         SOC_IF_ERROR_RETURN
   6145             (READ_PHY82328_MMF_PMA_PMD_REG(unit, pc, TX_FED_RPTR_TXFIR_STATUS1, &data16));
   6146         dsc_cbp->txfir_post2 = (data16 & TX_FED_TXFIR_CONTROL2_TXFIR_POST2_MASK) >>
   6147                                TX_FED_TXFIR_CONTROL2_TXFIR_POST2_SHIFT;
   6148 
   6149         SOC_IF_ERROR_RETURN
   6150             (phy82328_serdes_rdbl_uc_var(unit, port, pc, 0xd, &data16));
   6151         dsc_cbp->heye_left = data16;
   6152 
   6153         SOC_IF_ERROR_RETURN
   6154             (phy82328_serdes_rdbl_uc_var(unit, port, pc, 0xe, &data16));
   6155         dsc_cbp->heye_right = data16;
   6156         SOC_IF_ERROR_RETURN
   6157             (phy82328_serdes_rdbl_uc_var(unit, port, pc, 0xf, &data16));
   6158         dsc_cbp->veye_upper = data16;
   6159         SOC_IF_ERROR_RETURN
   6160             (phy82328_serdes_rdbl_uc_var(unit, port, pc, 0x10, &data16));
   6161         dsc_cbp->veye_lower = data16;
   6162     }
   6163 	/* Restore to default single port register access */
   6164 	if (PHY82328_SINGLE_PORT_MODE(pc)) {
   6165 		SOC_IF_ERROR_RETURN(_phy_82328_channel_select(unit, port, side, PHY82328_ALL_LANES));
   6166 	}
   6167     SOC_IF_ERROR_RETURN(
   6168         phy82328_intf_side_reg_select(unit, port, PHY82328_INTF_SIDE_LINE));
   6169     if (!is_micro_stopped) {
   6170             SOC_IF_ERROR_RETURN(
   6171                 phy82328_serdes_pmd_uc_cmd(unit, port, pc, PHY82328_CMD_UC_CTRL, PHY82328_CMD_UC_CTRL_RESUME, 2000));
   6172         }
   6173 
   6174     /* display */
   6175     LOG_CLI((BSL_META_U(unit,
   6176                         "\nDSC parameters for port %d\n"), port));
   6177 
   6178     LOG_CLI((BSL_META_U(unit,
   6179                         "SNO OSR SIGDET UCV_CON RXLCK RXPPM CLK90 CLKP1 "
   6180                         "PFMAIN PFLOW DCOFFSET VGA P1LVLCTRL DFE1 DFE2 "
   6181                         "DFE3 DFE4 DFE5 PE  ZE  ME  PO  ZO  MO TXPPM PRE "
   6182                         "MAIN POST1 POST2 \n")));
   6183     for (i = 0; i < lanes; i++) {
   6184         dsc_cbp = &(dsc_cb[i]);
   6185         LOG_CLI((BSL_META_U(unit,
   6186                             "%03d %03d %06d %07d %05d %05d %05d %05d %06d %05d %08d "
   6187                             "%03d %09d %04d %04d %04d %04d %04d %03d %03d %03d %03d"
   6188                             "%03d %03d %04d %03d %04d %04d %04d \n"), 
   6189                  i, dsc_cbp->osr_mode, dsc_cbp->sig_det, dsc_cbp->ucv_config,
   6190                  dsc_cbp->rx_lock, dsc_cbp->rx_ppm,
   6191                  dsc_cbp->clk90, dsc_cbp->clkp1,
   6192                  dsc_cbp->pf_main, dsc_cbp->pf_low,
   6193                  dsc_cbp->dc_offset,dsc_cbp->vga,dsc_cbp->p1_lvl_ctrl,
   6194                  dsc_cbp->dfe1, dsc_cbp->dfe2,
   6195                  dsc_cbp->dfe3,dsc_cbp->dfe4,dsc_cbp->dfe5,
   6196                  dsc_cbp->pe,dsc_cbp->ze,dsc_cbp->me, dsc_cbp->po,
   6197                  dsc_cbp->zo, dsc_cbp->mo,
   6198                  dsc_cbp->tx_ppm, dsc_cbp->txfir_pre, dsc_cbp->txfir_main,
   6199                  dsc_cbp->txfir_post1, dsc_cbp->txfir_post2));
   6200     }
   6201     return SOC_E_NONE;
   6202 }
   6203 
   6204 
   6205 STATIC int32
   6206 phy_82328_diag_ctrl(int32 unit, soc_port_t port, uint32 inst, int32 op_type,  int32 op_cmd,  
   6207 					void *arg)   
   6208 {
   6209     int32 lane;
   6210     int32 intf;
   6211     int32 rv = SOC_E_NONE;
   6212 
   6213     lane = PHY_DIAG_INST_LN(inst);
   6214     intf = PHY_DIAG_INST_INTF(inst);
   6215     if (intf == PHY_DIAG_INTF_DFLT) {
   6216         intf = PHY_DIAG_INTF_LINE;
   6217     }
   6218 
   6219     switch (op_cmd) {
   6220 	    case PHY_DIAG_CTRL_DSC:
   6221             rv = _phy_82328_diag_dsc(unit, port, intf, lane);
   6222         break;
   6223         case PHY_DIAG_CTRL_EYE_ENABLE_LIVELINK:
   6224         case PHY_DIAG_CTRL_EYE_DISABLE_LIVELINK:
   6225         case PHY_DIAG_CTRL_EYE_CLEAR_LIVELINK:
   6226         case PHY_DIAG_CTRL_EYE_START_LIVELINK:
   6227         case PHY_DIAG_CTRL_EYE_STOP_LIVELINK:
   6228         case PHY_DIAG_CTRL_EYE_READ_LIVELINK:
   6229         case PHY_DIAG_CTRL_EYE_GET_INIT_VOFFSET:
   6230         case PHY_DIAG_CTRL_EYE_SET_HOFFSET:
   6231         case PHY_DIAG_CTRL_EYE_SET_VOFFSET:
   6232         case PHY_DIAG_CTRL_EYE_GET_MAX_LEFT_HOFFSET:
   6233         case PHY_DIAG_CTRL_EYE_GET_MAX_RIGHT_HOFFSET:
   6234         case PHY_DIAG_CTRL_EYE_GET_MIN_VOFFSET:
   6235         case PHY_DIAG_CTRL_EYE_GET_MAX_VOFFSET:
   6236         case PHY_DIAG_CTRL_EYE_MARGIN_VEYE:
   6237         case PHY_DIAG_CTRL_EYE_MARGIN_HEYE_LEFT:
   6238         case PHY_DIAG_CTRL_EYE_MARGIN_HEYE_RIGHT:
   6239             rv = SOC_E_UNAVAIL;
   6240         break;
   6241         case PHY_DIAG_CTRL_START_FAST_EYESCAN:
   6242             rv =  _phy_82328_diag_eyescan(unit, port, inst);
   6243         break;
   6244 
   6245         default:
   6246            if (op_type == PHY_DIAG_CTRL_SET) {
   6247                SOC_IF_ERROR_RETURN
   6248                    (_phy_82328_control_set(unit, port, intf, lane, op_cmd, PTR_TO_INT(arg)));
   6249            } else if (op_type == PHY_DIAG_CTRL_GET) {
   6250                SOC_IF_ERROR_RETURN
   6251                    (_phy_82328_control_get(unit, port, intf, lane, op_cmd, (uint32 *)arg));
   6252            } else {
   6253                LOG_ERROR(BSL_LS_SOC_PHY,
   6254                          (BSL_META_U(unit,
   6255                                      "82328 diag_ctrl bad operation: u=%d p=%d ctrl=0x%x\n"), 
   6256                                      unit, port, op_cmd));
   6257                rv = SOC_E_UNAVAIL;
   6258         }
   6259         break;
   6260     }
   6261     return rv;
   6262 }
   6263 
   6264 /*
   6265 * Function:
   6266 *      phy_82328_ability_remote_get
   6267 * Purpose:
   6268 *      Get the device's complete abilities.
   6269 * Parameters:
   6270 *      unit - StrataSwitch unit #.
   6271 *      port - StrataSwitch port #.
   6272 *      ability - return device's abilities.
   6273 * Returns:
   6274 *      SOC_E_XXX
   6275 */
   6276 
   6277 STATIC int
   6278 phy_82328_ability_remote_get(int unit, soc_port_t port, 
   6279                             soc_port_ability_t *ability)
   6280 {
   6281     int an, an_done;
   6282     uint16      pause_adv;
   6283     soc_port_mode_t mode;
   6284     phy_ctrl_t *pc, *int_pc;
   6285 	phy82328_intf_cfg_t  *line_intf;
   6286 
   6287     if (ability == NULL) {
   6288         return SOC_E_PARAM;
   6289     }
   6290 	
   6291     /* Only firmware has visibility into remote ability */
   6292 	sal_memset(ability, 0, sizeof(soc_port_ability_t));
   6293 
   6294     pc = EXT_PHY_SW_STATE(unit, port);
   6295 	line_intf = &(LINE_INTF(pc));
   6296         if (  (line_intf->type != SOC_PORT_IF_CR4)
   6297               && (line_intf->type != SOC_PORT_IF_CR)
   6298               && (line_intf->type != SOC_PORT_IF_KR4)
   6299               && (line_intf->type != SOC_PORT_IF_KR)
   6300               && (line_intf->type != SOC_PORT_IF_GMII)
   6301               && (line_intf->type != SOC_PORT_IF_SGMII)) {
   6302             return SOC_E_NONE;
   6303         }
   6304 
   6305     if (line_intf->type == SOC_PORT_IF_GMII) {
   6306         int_pc = INT_PHY_SW_STATE(unit, port);
   6307         if (int_pc) {
   6308             SOC_IF_ERROR_RETURN(PHY_ABILITY_REMOTE_GET(int_pc->pd, unit, port, ability));
   6309         }
   6310         return SOC_E_NONE;
   6311     }
   6312 
   6313     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   6314 
   6315     mode = 0;
   6316 	/* Return what the firmware is setting */
   6317     /* If an done, then return the speed for the port */
   6318     SOC_IF_ERROR_RETURN(phy_82328_an_get(unit, port, &an, &an_done));
   6319     if (an && an_done) {
   6320         if(PHY82328_SINGLE_PORT_MODE(pc)) {
   6321             ability->speed_full_duplex = SOC_PA_SPEED_40GB;
   6322         }
   6323         else {
   6324             ability->speed_full_duplex = SOC_PA_SPEED_10GB;
   6325         }
   6326         
   6327         mode = 0;
   6328             SOC_IF_ERROR_RETURN
   6329               (READ_PHY82328_MMF_AN_REG(unit, pc, IEEE1_AN_BLK_AN_LP_BASE_PAGE_ABILITY_1_REG, &pause_adv));
   6330         switch (pause_adv & QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_MASK) {		
   6331             case (1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT):  /*7.0x0010.10 1*/
   6332 			    mode = SOC_PA_PAUSE_TX;		
   6333             break;
   6334             case (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)): /*7.0x0010.11 1*/
   6335                 mode = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   6336             break;		
   6337             case (1<<(QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT+1)) |
   6338 				(1<<QSFI_AN_IEEE1_AN_ADVERTISEMENT_1_REGISTER_PAUSE_SHIFT):/*7.0x0010.11:10 1*/
   6339                 mode = SOC_PA_PAUSE_RX;
   6340             break;		
   6341             default:
   6342                 mode = 0;
   6343             break;
   6344         }
   6345         ability->pause = mode;
   6346     }
   6347     LOG_INFO(BSL_LS_SOC_PHY,
   6348              (BSL_META_U(unit,
   6349                          "phy_82328_ability_remote_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"),
   6350               unit, port, ability->speed_full_duplex, ability->pause));
   6351     return SOC_E_NONE;
   6352 }
   6353 
   6354 /*
   6355  * Function:
   6356  *      phy_82328_precondition_before_probe
   6357  * Purpose:
   6358  *      When the device is in 40G, ie. after a power reset, and the 10G
   6359  *      port being probed does not have the 40G address in PRTAD, the
   6360  *      device will not respond until the port that has the 40G address
   6361  *      is probed. To avoid not programming ports correctly, make
   6362  *      sure the device is in quad (4x10G) PMD mode when the SDK port is 10G.
   6363  *      Need to set "port_phy_precondition_before_probe_xe0/4" in config file.
   6364  * Parameters: 
   6365  *      unit - StrataSwitch unit #.
   6366  *      pc   - phy ctrl descriptor.
   6367  * Returns:
   6368  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   6369  */
   6370 
   6371 STATIC int32
   6372 phy_82328_precondition_before_probe(int32 unit, phy_ctrl_t *pc)
   6373 {
   6374     int32 ids;
   6375     int32 rv = SOC_E_NOT_FOUND;
   6376     uint16 pmd_ctrl;
   6377     uint16 id0, id1;
   6378     uint16 saved_phy_id;
   6379     /* Not required when the port is single PMD */
   6380     if (PHY82328_SINGLE_PORT_MODE(pc)) {
   6381         LOG_INFO(BSL_LS_SOC_PHY,
   6382                  (BSL_META_U(unit,
   6383                              "PMD must not be called when in single PMD\n")));
   6384         return rv;
   6385     }
   6386     saved_phy_id = pc->phy_id;
   6387 
   6388     /* Look for first address that responds */
   6389     for (ids = 0; ids < 4; ids++) {
   6390 
   6391         pc->phy_id = (saved_phy_id & ~0x3) + ids;
   6392          LOG_INFO(BSL_LS_SOC_PHY,
   6393                   (BSL_META_U(unit,
   6394                               "Try device with address %x\n"), pc->phy_id));
   6395 
   6396         /*
   6397          * Make sure the device has the correct dev IDs
   6398          * Note that this is being called either because the soc probe found
   6399          * the ids or there was an id override. In the later case, the device
   6400          * might not have the 82328 ids so this PMD setup will not be supported
   6401          */
   6402         id0 = 0;
   6403         READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   6404                                       IEEE0_BLK_PMA_PMD_PMD_IDENTIFIER_REGISTER_0,
   6405                                       &id0);
   6406         if (id0 != 0xae02) {
   6407             continue;
   6408         }
   6409         id1 = 0;
   6410         READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   6411                                       IEEE0_BLK_PMA_PMD_PMD_IDENTIFIER_REGISTER_1,
   6412                                       &id1);
   6413         if (id1 != 0x5210) {
   6414             continue;
   6415         }
   6416 
   6417         /* Read device ids correctly so use this address to make sure device is in 10G */
   6418         pmd_ctrl = 0;
   6419         READ_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   6420                                       MGT_TOP_SINGLE_PMD_CTRL, &pmd_ctrl);
   6421         if (pmd_ctrl & MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK) {
   6422             LOG_INFO(BSL_LS_SOC_PHY,
   6423                      (BSL_META_U(unit,
   6424                                  "Device responded to address %x. Setting quad PMD mode\n"),
   6425                       pc->phy_id));
   6426             pmd_ctrl = 0;   /* Clear single PMD */
   6427             SOC_IF_ERROR_RETURN(
   6428                 MODIFY_PHY82328_MMF_PMA_PMD_REG(unit, pc,
   6429                                             MGT_TOP_SINGLE_PMD_CTRL , pmd_ctrl,
   6430                                             MGT_TOP_CMN_CTLR_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK));
   6431         }
   6432         /* Found the address that responds and the device now is in 4x10G */
   6433         rv = SOC_E_NONE;
   6434         break;
   6435     }
   6436 
   6437     pc->phy_id = saved_phy_id;
   6438 
   6439     return rv;
   6440 }
   6441 
   6442 
   6443 /*
   6444  * Function:
   6445  *     phy_82328_multi_get
   6446  * Purpose:
   6447  *      Multi data read interface through device I2C
   6448  * Parameters:
   6449  *      unit - StrataSwitch unit #
   6450  *      port - Port number
   6451  *      flags - flags passed in the transfer
   6452  *      dev_adr - Device address from which data need to be read.
   6453  *      offset - Starting addres from which data read starts.
   6454  *      max_size - Maximum Number of bytes to read
   6455  *      data - data buffer to receive the data
   6456  *      actual_size - Actual received number of byte
   6457  * Returns:
   6458  *      SOC_E_XXX
   6459  */
   6460 
   6461 STATIC int
   6462 phy_82328_multi_get(int unit, soc_port_t port, uint32 flags,
   6463                     uint32 dev_addr, uint32 offset, int max_size, uint8 *data,
   6464                     int *actual_size)
   6465 {
   6466     int rv;
   6467     rv = phy_82328_i2cdev_read(unit, port, (int)dev_addr, (int)offset, max_size,
   6468                                    data);
   6469     if (SOC_FAILURE(rv)) {
   6470         *actual_size = 0;
   6471         return SOC_E_FAIL;
   6472     }
   6473     *actual_size = max_size;
   6474     return SOC_E_NONE;
   6475 }
   6476 
   6477 /*
   6478  * Variable:   phy_82328drv_xe
   6479  * Purpose:    Phy driver callouts for a  phy 82328
   6480  * Notes:     
   6481  */
   6482 phy_driver_t phy_82328drv_xe = {
   6483     "82328 40-Gigabit PHY Driver",
   6484     phy_82328_init,              /* phy_init                     */
   6485     phy_null_reset,              /* phy_reset                    */
   6486     phy_82328_link_get,          /* phy_link_get                 */
   6487     phy_82328_enable_set,        /* phy_enable_set               */
   6488     phy_null_enable_get,         /* phy_enable_get               */
   6489     phy_null_duplex_set,         /* phy_duplex_set               */
   6490     phy_null_duplex_get,         /* phy_duplex_get               */
   6491     phy_82328_speed_set,         /* phy_speed_set                */
   6492     phy_82328_speed_get,         /* phy_speed_get                */
   6493     phy_null_set,                /* phy_master_set               */
   6494     phy_null_zero_get,           /* phy_master_get               */
   6495     phy_82328_an_set,            /* phy_an_set                   */
   6496     phy_82328_an_get,            /* phy_an_get                   */
   6497     phy_null_mode_set,           /* phy_adv_local_set            */
   6498     phy_null_mode_get,           /* phy_adv_local_get            */
   6499     phy_null_mode_get,           /* phy_adv_remote_get           */
   6500     phy_82328_lb_set,            /* phy_lb_set                   */
   6501     phy_82328_lb_get,            /* phy_lb_get                   */
   6502     phy_82328_interface_set,     /* phy_interface_set            */
   6503     phy_82328_interface_get,     /* phy_interface_get            */
   6504     phy_null_mode_get,           /* phy_ability                  */
   6505     NULL,                        /* phy_linkup_evt               */
   6506     NULL,                        /* phy_linkdn_evt               */
   6507     phy_null_mdix_set,           /* phy_mdix_set                 */
   6508     phy_null_mdix_get,           /* phy_mdix_get                 */
   6509     phy_null_mdix_status_get,    /* phy_mdix_status_get          */
   6510 #if 1
   6511     NULL,                        /* phy_medium_config_set        */
   6512     NULL,                        /* phy_medium_config_get        */
   6513     phy_null_medium_get,         /* phy_medium_get               */
   6514 #endif
   6515     NULL,                        /* phy_cable_diag               */
   6516     NULL,                        /* phy_link_change              */
   6517     phy_82328_control_set,       /* phy_control_set              */
   6518     phy_82328_control_get,       /* phy_control_get              */
   6519     phy_82328_reg_read,          /* phy_reg_read                 */
   6520     phy_82328_reg_write,         /* phy_reg_write                */
   6521     NULL,                        /* phy_reg_modify               */
   6522     NULL,                        /* phy_notify                   */
   6523     phy_82328_probe,             /* phy_probe                    */
   6524     phy_82328_ability_advert_set,/* phy_ability_advert_set       */
   6525     phy_82328_ability_advert_get,/* phy_ability_advert_get       */
   6526     phy_82328_ability_remote_get,/* phy_ability_remote_get       */
   6527     phy_82328_ability_local_get, /* phy_ability_local_get        */
   6528     phy_82328_firmware_set,      /* phy_firmware_set             */
   6529     NULL,                        /* phy_timesync_config_set      */
   6530     NULL,                        /* phy_timesync_config_get      */
   6531     NULL,                        /* phy_timesync_control_set     */
   6532     NULL,                        /* phy_timesync_control_get     */
   6533     phy_82328_diag_ctrl,         /* phy_diag_ctrl                */
   6534     NULL,                        /* pd_lane_control_set */
   6535     NULL,                        /* pd_lane_control_get */
   6536     NULL,                        /* pd_lane_reg_read */
   6537     NULL,                        /* pd_lane_reg_write */
   6538     NULL,                        /* pd_oam_config_set */
   6539     NULL,                        /* pd_oam_config_get */
   6540     NULL,                        /* pd_oam_control_set */
   6541     NULL,                        /* pd_oam_control_get */
   6542     NULL,                        /* pd_timesync_enhanced_capture_get */
   6543     phy_82328_multi_get,         /* pd_multi_get */
   6544     phy_82328_precondition_before_probe /* pd_precondition_before_probe */
   6545 
   6546 };
   6547 #else /* INCLUDE_PHY_82328 */
   6548 int _phy_82328_not_empty;
   6549 #endif /* INCLUDE_PHY_82328 */