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

phy84328.c (303527B)


      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:       phy84328.c
      8  * Purpose:    Phys Driver support for Broadcom 84328 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  * 4x10.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  * Single 125.00 MHz differential clock for 1.25 Gbps, 10.3125 Gbps and 11.5 Gbps
     32  * line rates
     33  *
     34  * Supports autonegotiation as follows:
     35  * Clause 73 only for starting Clause 72 and requesting FEC 
     36  * No speed resolution performed
     37  * No Clause 73 in 11.5 Gbps line rate, only Clause 72 supported
     38  * Clause 72 may be enabled standalone for close systems
     39  * Clause 37 is not supported
     40  * No on-chip FEC encoding/decoding, but shall pass-through FEC-encoded data. 
     41  */
     42 
     43 #if defined(INCLUDE_PHY_84328)   
     44 
     45 static unsigned int phy84328_maj_rev = 1200;
     46 static unsigned int phy84328_min_rev = 0;
     47 
     48 #include <sal/types.h>
     49 #include <soc/drv.h>
     50 #include <soc/debug.h>
     51 #include <soc/error.h>
     52 #include <soc/phyreg.h>
     53 #include <shared/bsl.h>
     54 #include <soc/phy.h>
     55 #include <soc/phy/phyctrl.h>
     56 #include <soc/phy/drv.h>
     57 
     58 #include "phydefs.h"      /* Must include before other phy related includes */
     59 #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
     60 #include "phyident.h"
     61 #include "phyreg.h"
     62 #include "phynull.h"
     63 #include "phyxehg.h"
     64 #include "phy84328.h"
     65 
     66 #define PHY84328_SINGLE_PORT_MODE(_pc)  \
     67 (SOC_INFO((_pc)->unit).port_num_lanes[(_pc)->port] >= 4)
     68 #define PHY84328_ID_84328 0x84328 /* Gallardo_oct_opt */
     69 #define PHY84328_ID_84324 0x84324 /* Gallardo_opt     */
     70 #define PHY84328_ID_84088 0x84088 /* Gallardo_oct_bp  */
     71 #define PHY84328_ID_84024 0x84024 /* Gallardo_bp      */
     72 /* PMD_CONTROL_REG - speed selection */
     73 #define PHY84328_PMD_CONTROL_REG_VAL_4_SPEED_MASK		\
     74 	(PHY84328_DEV1_PMD_CONTROL_REGISTER_SPEED_SELECTIONLSB_MASK | \
     75 	 PHY84328_DEV1_PMD_CONTROL_REGISTER_SPEED_SELECTIONMSB_MASK | \
     76 	 PHY84328_DEV1_PMD_CONTROL_REGISTER_SPEED_SELECTION_MASK)
     77 
     78 #define PHY84328_PMD_CONTROL_REG_VAL_4_SPEED_SELECTIONLSB		\
     79 	(1 << PHY84328_DEV1_PMD_CONTROL_REGISTER_SPEED_SELECTIONLSB_SHIFT)
     80 #define PHY84328_PMD_CONTROL_REG_VAL_4_SPEED_SELECTIONMSB		\
     81 	(1 << PHY84328_DEV1_PMD_CONTROL_REGISTER_SPEED_SELECTIONMSB_SHIFT)
     82 
     83 #define PHY84328_PMD_CONTROL_REG_VAL_4_SPEED_10GB				\
     84 	(PHY84328_PMD_CONTROL_REG_VAL_4_SPEED_SELECTIONLSB |		\
     85 	 PHY84328_PMD_CONTROL_REG_VAL_4_SPEED_SELECTIONMSB)
     86 
     87 #define PHY84328_PMD_CONTROL_REG_VAL_4_SPEED_40GB				\
     88 	(PHY84328_PMD_CONTROL_REG_VAL_4_SPEED_SELECTIONLSB |		\
     89 	 PHY84328_PMD_CONTROL_REG_VAL_4_SPEED_SELECTIONMSB |		\
     90 	 (2 << PHY84328_DEV1_PMD_CONTROL_REGISTER_SPEED_SELECTION_SHIFT))
     91 
     92 #define PHY84328_PMD_CONTROL_REG_VAL_4_SPEED_1GB				\
     93 	(1 << PHY84328_DEV1_PMD_CONTROL_REGISTER_SPEED_SELECTIONMSB_SHIFT)
     94 
     95 #define PHY84328_DEV1_PMD_CONTROL_REGISTER_PMA_LOOPBACK  \
     96 	(1 << PHY84328_DEV1_PMD_CONTROL_REGISTER_PMA_LOOPBACK_SHIFT) 
     97 
     98 /* PMD_CONTROL_2_REG - PMA type selection */
     99 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_LR4		0x23
    100 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_SR4		0x22
    101 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_CR4		0x21
    102 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_KR4		0x20
    103 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_10BASET	0x0f
    104 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_100BASETX 0x0e
    105 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_KX		0x0d
    106 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_1000BASET	0x0c
    107 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_KR		0x0b
    108 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_KX4		0x0a
    109 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_10GBASET	0x09
    110 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_LRM		0x08
    111 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_SR		0x07
    112 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_LR		0x06
    113 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_ER		0x05
    114 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_LX4		0x04
    115 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_SW		0x03
    116 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_LW		0x02
    117 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_EW		0x01
    118 #define PHY84328_DEV1_PMD_CONTROL_2_REGISTER_PMA_TYPE_CX4		0x00
    119 
    120 /* GP_REGISTER_0 new defined bits */
    121 #define	PHY84328_DEV1_GP_REG_0_P4_5_CTRL                (1 << 1)
    122 #define	PHY84328_DEV1_GP_REG_0_TX_GPIO                  (1 << 2)
    123 
    124 /* GP_REGISTER_1 */
    125 #define	PHY84328_DEV1_GP_REGISTER_1_LINE_TYPE_BKPLANE	(1 << PHY84328_DEV1_GP_REGISTER_1_LINE_TYPE_SHIFT)
    126 #define	PHY84328_DEV1_GP_REGISTER_1_SYSTEM_TYPE_BKPLANE	(1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_TYPE_SHIFT)
    127 #define	PHY84328_DEV1_GP_REGISTER_1_LINE_CU_TYPE_COPPER	(1 << PHY84328_DEV1_GP_REGISTER_1_LINE_CU_TYPE_SHIFT)
    128 #define	PHY84328_DEV1_GP_REGISTER_1_SYSTEM_CU_TYPE_COPPER (1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_CU_TYPE_SHIFT)
    129 #define PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE		(1 << PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE_SHIFT)
    130 #define PHY84328_DEV1_GP_REGISTER_1_SPEED_100G          (1 << PHY84328_DEV1_GP_REGISTER_1_SPEED_100G_SHIFT)
    131 #define PHY84328_DEV1_GP_REGISTER_1_SPEED_42G           ((1 << PHY84328_DEV1_GP_REGISTER_1_SPEED_40G_SHIFT) |  \
    132                                                          (1 << PHY84328_DEV1_GP_REGISTER_1_SPEED_1G_SHIFT)  |  \
    133                                                          (1 << PHY84328_DEV1_GP_REGISTER_1_SPEED_10G_SHIFT))
    134 #define PHY84328_DEV1_GP_REGISTER_1_SPEED_40G			(1 << PHY84328_DEV1_GP_REGISTER_1_SPEED_40G_SHIFT)
    135 #define PHY84328_DEV1_GP_REGISTER_1_SPEED_10G			(1 << PHY84328_DEV1_GP_REGISTER_1_SPEED_10G_SHIFT)
    136 #define PHY84328_DEV1_GP_REGISTER_1_SPEED_1G			(1 << PHY84328_DEV1_GP_REGISTER_1_SPEED_1G_SHIFT)
    137 
    138 /* Datapath4 */
    139 #define PHY84328_DEV1_GP_REGISTER_1_DATAPATH_MASK		0x0060
    140 #define PHY84328_DEV1_GP_REGISTER_1_DATAPATH_4_DEPTH1	0x0040
    141 #define PHY84328_DEV1_GP_REGISTER_1_DATAPATH_4_DEPTH2	0x0060
    142 
    143 /* GP_REGISTER_3 - microcode updated */
    144 #define PHY84328_DEV1_GP_REGISTER_3_FINISH_CHANGE_MASK  0x0080
    145 
    146 /* Rx polarity inversion */
    147 #define PHY84328_DEV1_GP_REGISTER_RX_INV				0xc0ba
    148 #define PHY84328_DEV1_GP_REGISTER_RX_INV_FORCE			(1 << 3)
    149 #define PHY84328_DEV1_GP_REGISTER_RX_INV_INVERT			(1 << 2)
    150 
    151 /* ANARXSTATUS - link status */
    152 #define PHY84328_DEV1_ANARXSTATUS_RXSTATUS_SIGDET		(1 << 15)
    153 #define PHY84328_DEV1_ANARXSTATUS_RXSTATUS_CDR			(1 << 12)
    154 /* Available when PRBS status is selected in anaRxControl */
    155 #define PHY84328_DEV1_ANARXSTATUS_RXSTATUS_RX_PRBS_LOCK	(1 << 15)
    156 #define PHY84328_DEV1_ANARXSTATUS_RXSTATUS_RX_PRBS_ERR_MASK	(0x1fff)
    157 
    158 /* Squelching done with lectrical idles */
    159 #define PHY84328_DEV1_ANATXACONTROL2_TX_ELECTRAL_IDLE	0x0100
    160 
    161 #define PHY84328_CSR_REG_MODULE_AUTO_DETECT		(1 << 4)
    162 /* 
    163  * This bounds how long to wait until giving up on configuration updates
    164  * - Delay is given in us
    165  * - timeout = (MAX_RETRIES * DELAY)us
    166  */
    167 #define PHY84328_UPDATE_CHECK_DELAY				20
    168 #define PHY84328_UPDATE_CHECK_MAX_RETRIES		100
    169 
    170 
    171 /* I2C related defines */
    172 #define PHY84328_BSC_XFER_MAX     0x1F9
    173 #define PHY84328_BSC_WR_MAX       16
    174 #define PHY84328_WRITE_START_ADDR 0x8007
    175 #define PHY84328_READ_START_ADDR  0x8007
    176 #define PHY84328_WR_FREQ_400KHZ   0x0100
    177 #define PHY84328_2W_STAT          0x000C
    178 #define PHY84328_2W_STAT_IDLE     0x0000
    179 #define PHY84328_2W_STAT_COMPLETE 0x0004
    180 #define PHY84328_2W_STAT_IN_PRG   0x0008
    181 #define PHY84328_2W_STAT_FAIL     0x000C
    182 #define PHY84328_BSC_WRITE_OP     0x22
    183 #define PHY84328_BSC_READ_OP      0x2
    184 #define PHY84328_I2CDEV_WRITE     0x1
    185 #define PHY84328_I2CDEV_READ      0x0
    186 #define PHY84328_I2C_8BIT         0
    187 #define PHY84328_I2C_16BIT        1
    188 #define PHY84328_I2C_TEMP_RAM     0xE
    189 #define PHY84328_I2C_OP_TYPE(access_type,data_type) \
    190         ((access_type) | ((data_type) << 8))
    191 #define PHY84328_I2C_ACCESS_TYPE(op_type) ((op_type) & 0xff)
    192 #define PHY84328_I2C_DATA_TYPE(op_type)   (((op_type) >> 8) & 0xff)
    193 #define I2CM_IDLE_WAIT_MSEC        350
    194 #define I2CM_IDLE_WAIT_CHUNK       10
    195 #define I2CM_IDLE_WAIT_COUNT       (I2CM_IDLE_WAIT_MSEC / I2CM_IDLE_WAIT_CHUNK)
    196 
    197 
    198 
    199 #define PHY84328_ALL_LANES						0x000f
    200 
    201 #define PHY84328_PREEMPH_CTRL_FORCE_SHIFT		15
    202 #define PHY84328_PREEMPH_CTRL_POST_TAP_SHIFT	10
    203 #define PHY84328_PREEMPH_CTRL_MAIN_TAP_SHIFT	4
    204 #define PHY84328_PREEMPH_CTRL_PRE_TAP_SHIFT		0
    205 
    206 #define PHY84328_PREEMPH_FORCE_GET(_val)		(((_val) >> PHY84328_PREEMPH_CTRL_FORCE_SHIFT) & 0x1)
    207 #define PHY84328_PREEMPH_POST_TAP_GET(_val)		(((_val) >> PHY84328_PREEMPH_CTRL_POST_TAP_SHIFT) & 0xf)
    208 #define PHY84328_PREEMPH_MAIN_TAP_GET(_val)		(((_val) >> PHY84328_PREEMPH_CTRL_MAIN_TAP_SHIFT) & 0x1f)
    209 #define PHY84328_PREEMPH_PRE_TAP_GET(_val)		(((_val) >> PHY84328_PREEMPH_CTRL_PRE_TAP_SHIFT) & 0x7)
    210 
    211 #define PHY84328_PREEMPH_FORCE_SET(_val)		(((_val) & 1) << PHY84328_PREEMPH_CTRL_FORCE_SHIFT)
    212 #define PHY84328_PREEMPH_POST_TAP_SET(_val)		(((_val) & 0xf) << PHY84328_PREEMPH_CTRL_POST_TAP_SHIFT)
    213 #define PHY84328_PREEMPH_MAIN_TAP_SET(_val)		(((_val) & 0x1f) << PHY84328_PREEMPH_CTRL_MAIN_TAP_SHIFT)
    214 #define PHY84328_PREEMPH_PRE_TAP_SET(_val)		(((_val) & 7) << PHY84328_PREEMPH_CTRL_PRE_TAP_SHIFT)
    215 
    216 /* CL73 pause advertisement */
    217 #define CL73_AN_ADV_PAUSE                       (1 << 10)
    218 #define CL73_AN_ADV_ASYM_PAUSE                  (1 << 11)
    219 
    220 /* Multicore port */
    221 #define PHY84328_MAX_CORES                      3
    222 #define PHY84328_CORE_STATE_SIZE                (sizeof(phy_ctrl_t) + sizeof(phy84328_dev_desc_t))
    223 
    224 #define PHY84328_MULTI_CORE_MODE(_pc)           ((_pc)->phy_mode == PHYCTRL_MULTI_CORE_PORT)
    225 #define PHY84328_VALID_CORE(_c)                 ((_c) < PHY84328_MAX_CORES)
    226 #define PHY84328_CORES(_u, _p)                  ((SOC_INFO((_u)).port_num_lanes[(_p)] + 3) / 4)
    227 #define PHY84328_CORE_PC(_pc, _c)               (phy_ctrl_t *) \
    228         (((uint8 *)(_pc)) + (PHY84328_CORE_STATE_SIZE * (_c)))
    229 
    230 #define PHY84328_CORE_STATE_SET(unit, port, core, pc)  \
    231     do {\
    232         EXT_PHY_SW_STATE(unit, port) = PHY84328_CORE_PC(pc, core);\
    233         if (core > 0) { \
    234             (PHY84328_CORE_PC(pc, core))->flags  = (pc)->flags;\
    235         } \
    236     } while (0)
    237 
    238 #define PHY84328_CALL_SET(_u, _p, _func) \
    239         do { \
    240             int _rv = SOC_E_NONE; \
    241             phy_ctrl_t *_pc = EXT_PHY_SW_STATE((_u), (_p)); \
    242             if (DBG_FLAGS(_pc) & PHY84328_DBG_F_API_SET) { \
    243                 LOG_INFO(BSL_LS_SOC_PHY,\
    244                       (BSL_META_U(unit,\
    245                            "%s(%d, %d)\n"), FUNCTION_NAME(), (_u), (_p))); \
    246             } \
    247             if (! PHY84328_MULTI_CORE_MODE(_pc)) { \
    248                 _rv = (_func); \
    249             } else { \
    250                 int _c, _ac; \
    251                 _ac = PHY84328_CORES((_u), (_p)); \
    252                 for (_c = 0; _c < _ac; _c++) { \
    253                     PHY84328_CORE_STATE_SET((_u), (_p), _c, _pc); \
    254                     _rv = (_func); \
    255                     if (_rv != SOC_E_NONE) { \
    256                         break; \
    257                     } \
    258                 } \
    259                 PHY84328_CORE_STATE_SET((_u), (_p), 0, _pc); \
    260             } \
    261             return _rv; \
    262          } while (0)
    263 
    264 
    265 #define PHY84328_CALL_GET(_u, _p, _func, _v, _pv) \
    266     do { \
    267         int _rv = SOC_E_NONE; \
    268         phy_ctrl_t *_pc = EXT_PHY_SW_STATE((_u), (_p)); \
    269         if (DBG_FLAGS(_pc) & PHY84328_DBG_F_API_GET) { \
    270             LOG_INFO(BSL_LS_SOC_PHY,\
    271                       (BSL_META_U(unit,\
    272                        "%s(%d, %d)\n"), FUNCTION_NAME(), (_u), (_p))); \
    273         } \
    274         if (! PHY84328_MULTI_CORE_MODE(_pc)) { \
    275             _rv = (_func); \
    276         } else { \
    277             int _c, _ac; \
    278             _ac = PHY84328_CORES((_u), (_p)); \
    279             for (_c = 0; _c < _ac; _c++) { \
    280                 PHY84328_CORE_STATE_SET((_u), (_p), _c, _pc); \
    281                 _rv = (_func); \
    282                 if (_rv != SOC_E_NONE) { \
    283                     break; \
    284                 } \
    285                 if (_c == 0) { \
    286                     (_pv) = *(_v); \
    287                 } else if (*(_v) != (_pv)) { \
    288                     LOG_ERROR(BSL_LS_SOC_PHY,\
    289                                   (BSL_META_U(unit,\
    290                               "84328 %s val does not match for all cores: u=%d p=%d\n"), \
    291                               FUNCTION_NAME(), (_u), (_p))); \
    292                 } \
    293             } \
    294             PHY84328_CORE_STATE_SET((_u), (_p), 0, _pc); \
    295         } \
    296         return _rv; \
    297     } while (0)
    298 
    299 
    300 #define PHY_84328_MICRO_PAUSE(_u, _p, _s) \
    301     do { \
    302         phy_ctrl_t *_pc; \
    303         _pc = EXT_PHY_SW_STATE((_u), (_p)); \
    304         if (DEVREV(_pc) == 0x00a0) { \
    305             _phy_84328_micro_pause((_u), (_p), (_s)); \
    306         } \
    307     } while (0) 
    308 
    309 #define PHY_84328_MICRO_RESUME(_u, _p) \
    310     do { \
    311         phy_ctrl_t *_pc; \
    312         _pc = EXT_PHY_SW_STATE((_u), (_p)); \
    313         if (DEVREV(_pc) == 0x00a0) { \
    314             _phy_84328_micro_resume((_u), (_p)); \
    315         } \
    316     } while (0) 
    317 
    318 /*
    319  * PHY system interface types 
    320  * These values are used when configuring system side interface with spn_PHY_SYS_INTERFACE 
    321  * Always add at the end but never change the order!! Adding also requires updating 
    322  * grog documentation
    323  */
    324 enum {
    325 	PHY_SYSTEM_INTERFACE_DFLT	= 0,
    326 	PHY_SYSTEM_INTERFACE_KX		= 1,
    327 	PHY_SYSTEM_INTERFACE_KR		= 2,
    328 	PHY_SYSTEM_INTERFACE_SR		= 3,
    329 	PHY_SYSTEM_INTERFACE_LR		= 4,
    330 	PHY_SYSTEM_INTERFACE_CR		= 5,	/* System side as XFI-DFE, or system side DAC */
    331 	PHY_SYSTEM_INTERFACE_KR4 	= 6,
    332 	PHY_SYSTEM_INTERFACE_SR4 	= 7,
    333 	PHY_SYSTEM_INTERFACE_LR4 	= 8,
    334 	PHY_SYSTEM_INTERFACE_CR4 	= 9,    /* System side as XLAUI-DFE, or system side DAC */
    335 	PHY_SYSTEM_INTERFACE_XFI 	= 10,
    336 	PHY_SYSTEM_INTERFACE_XLAUI	= 11,
    337 	PHY_SYSTEM_INTERFACE_INVALID	/* must be last */
    338 }; 
    339 
    340 soc_port_if_t phy_sys_to_port_if[] = {
    341     0,                                  /* PHY_SYSTEM_INTERFACE_DFLT    */
    342     SOC_PORT_IF_KX,                     /* PHY_SYSTEM_INTERFACE_KX      */
    343     SOC_PORT_IF_KR,                     /* PHY_SYSTEM_INTERFACE_KR      */
    344     SOC_PORT_IF_SR,                     /* PHY_SYSTEM_INTERFACE_SR      */
    345     SOC_PORT_IF_LR,                     /* PHY_SYSTEM_INTERFACE_LR      */
    346     SOC_PORT_IF_CR,                     /* PHY_SYSTEM_INTERFACE_CR      */
    347     SOC_PORT_IF_KR4,                    /* PHY_SYSTEM_INTERFACE_KR4     */
    348     SOC_PORT_IF_SR4,                    /* PHY_SYSTEM_INTERFACE_SR4     */
    349     SOC_PORT_IF_LR4,                    /* PHY_SYSTEM_INTERFACE_LR4     */
    350     SOC_PORT_IF_CR4,                    /* PHY_SYSTEM_INTERFACE_CR4     */
    351     SOC_PORT_IF_XFI,                    /* PHY_SYSTEM_INTERFACE_XFI     */
    352     SOC_PORT_IF_XLAUI,                  /* PHY_SYSTEM_INTERFACE_XLAUI   */
    353 };
    354 
    355 /* interface params */
    356 typedef struct phy84328_intf_cfg {
    357 	int					speed;
    358 	soc_port_if_t		type;
    359 } phy84328_intf_cfg_t;
    360 
    361 typedef	enum {
    362 	PHY84328_DATAPATH_20,
    363 	PHY84328_DATAPATH_4_DEPTH1,
    364 	PHY84328_DATAPATH_4_DEPTH2
    365 } phy84328_datapath_t;
    366 
    367 typedef struct phy84328_counters {
    368 	uint32				intf_updates;
    369 	uint32				link_down;
    370 	uint32				retry_serdes_link;
    371 	uint32				speed_chk_err;
    372 	uint32				intf_chk_err;
    373 	uint32				side_sel_err;
    374 	uint32				no_cdr;
    375 	uint32				micro_nopause;
    376 } phy84328_counters_t;
    377 
    378 /* 
    379  * Software RX LOS (Loss of Signal) WAR
    380  * The workaround handles conditions when loss of signal is not reliably 
    381  * detected. A typical scenario is when the cable is still plugged to a module but
    382  * the link partner has disable its tx, in which case some modules do not correctly
    383  * report loss of signal.
    384  */
    385 typedef enum {
    386     PHY84328_SW_RX_LOS_RESET,
    387     PHY84328_SW_RX_LOS_INITIAL_LINK,
    388     PHY84328_SW_RX_LOS_LINK,
    389     PHY84328_SW_RX_LOS_START_TIMER,
    390     PHY84328_SW_RX_LOS_RX_RESTART,
    391     PHY84328_SW_RX_LOS_IDLE
    392 } phy84328_sw_rx_los_states_t;
    393 
    394 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
    395 const static char *sw_rx_los_state_names[] = {
    396     "RESET",
    397     "INITIAL_LINK",
    398     "LINK",
    399     "START_TIMER",
    400     "RX_RESTART",
    401     "IDLE"
    402 };
    403 #endif /* BROADCOM_DEBUG || DEBUG_PRINT */
    404 
    405 typedef struct {
    406     uint8				cfg_enable;				/* configured with ph control or not */
    407     uint8				cur_enable;				/* currently enabled or not */
    408     uint8				sys_link;
    409 	uint8               link_no_pcs;
    410     uint8				link_status;
    411 	uint8               fault_report_dis;
    412 	uint8				ls_ticks;
    413 	uint32				restarts;	
    414 	mac_driver_t		*macd;
    415     phy84328_sw_rx_los_states_t	state;
    416 } phy84328_sw_rx_los_t;
    417 
    418 #define PHY84328_LINK_DEBOUNCE	20
    419 typedef struct {
    420 	int					cur_enable;
    421 	int					cfg_enable;
    422 	int					debounce;
    423 } phy84328_link_mon_t;
    424 
    425 typedef struct {
    426 	int					enable;
    427 	int					count;					/* resume only if count==0 */
    428 } phy84328_micro_ctrl_t;
    429 
    430 #define PHY84328_NUM_LANES      4
    431 
    432 #define PHY84328_DBG_F_REG      (1 << 0)
    433 #define PHY84328_DBG_F_EYE      (1 << 1)
    434 #define PHY84328_DBG_F_DWLD     (1 << 3)
    435 #define PHY84328_DBG_F_API_SET  (1 << 4)
    436 #define PHY84328_DBG_F_API_GET  (1 << 5)
    437 
    438 typedef struct {
    439 	uint32				devid;
    440 	uint16				devrev;
    441     int                 core_num;
    442 	uint32				dbg_flags;
    443 	int					p2l_map[PHY84328_NUM_LANES];  /* index: physical lane, array element: */
    444 	phy84328_intf_cfg_t line_intf;
    445 	phy84328_intf_cfg_t sys_intf;
    446 	phy84328_sw_rx_los_t sw_rx_los;					  /* sw_rx_los war */
    447     int                 fw_rx_los;                    /* rx LOS handled by firmware */
    448 	phy84328_counters_t counters;
    449 	int					cur_link;
    450 	uint16				pol_tx_cfg;
    451 	uint16				pol_rx_cfg;
    452 	int					mod_auto_detect;			  /* module auto detect enabled */
    453 	phy84328_datapath_t cfg_datapath;
    454 	phy84328_datapath_t cur_datapath;
    455 	phy84328_link_mon_t link_mon;
    456 	int					sys_forced_cl72;
    457 	int					an_en;
    458 	int					force_20bit;
    459 	int					sync_init;
    460 	int					int_phy_re_en;
    461 	soc_timeout_t       sync_to;
    462 	uint16				logical_lane0;
    463 	int					update_config;
    464 	int					bypass_ss_tuning;
    465 	phy84328_micro_ctrl_t micro_ctrl;
    466 	int					cfg_sys_intf;
    467 	int					port_enable_delay;
    468 } phy84328_dev_desc_t;
    469 
    470 #define DEVID(_pc)				(((phy84328_dev_desc_t *)((_pc) + 1))->devid)
    471 #define DEVREV(_pc)				(((phy84328_dev_desc_t *)((_pc) + 1))->devrev)
    472 #define CORE_NUM(_pc)           (((phy84328_dev_desc_t *)((_pc) + 1))->core_num)
    473 #define DBG_FLAGS(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->dbg_flags)
    474 #define P2L_MAP(_pc,_ix)		(((phy84328_dev_desc_t *)((_pc) + 1))->p2l_map[(_ix)])
    475 #define LINE_INTF(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->line_intf)
    476 #define SYS_INTF(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->sys_intf)
    477 #define SW_RX_LOS(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->sw_rx_los)
    478 #define FW_RX_LOS(_pc)          (((phy84328_dev_desc_t *)((_pc) + 1))->fw_rx_los)
    479 #define COUNTERS(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->counters)
    480 #define CUR_LINK(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->cur_link)
    481 #define POL_TX_CFG(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->pol_tx_cfg)
    482 #define POL_RX_CFG(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->pol_rx_cfg)
    483 #define MOD_AUTO_DETECT(_pc)	(((phy84328_dev_desc_t *)((_pc) + 1))->mod_auto_detect)
    484 #define CFG_DATAPATH(_pc)		(((phy84328_dev_desc_t *)((_pc) + 1))->cfg_datapath)
    485 #define CUR_DATAPATH(_pc)		(((phy84328_dev_desc_t *)((_pc) + 1))->cur_datapath)
    486 #define SYS_FORCED_CL72(_pc)	(((phy84328_dev_desc_t *)((_pc) + 1))->sys_forced_cl72)
    487 #define AN_EN(_pc)				(((phy84328_dev_desc_t *)((_pc) + 1))->an_en)
    488 #define FORCE_20BIT(_pc)        (((phy84328_dev_desc_t *)((_pc) + 1))->force_20bit)
    489 #define FORCE_20BIT_LB          (1 << 0)
    490 #define FORCE_20BIT_AN          (1 << 1)
    491 
    492 #define LINK_MON(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->link_mon)
    493 #define SYNC_INIT(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->sync_init)
    494 #define SYNC_TO(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->sync_to)
    495 #define INT_PHY_RE_EN(_pc)		(((phy84328_dev_desc_t *)((_pc) + 1))->int_phy_re_en)
    496 #define LOGICAL_LANE0(_pc)		(((phy84328_dev_desc_t *)((_pc) + 1))->logical_lane0)
    497 #define BYPASS_SS_TUNING(_pc)	(((phy84328_dev_desc_t *)((_pc) + 1))->bypass_ss_tuning)
    498 #define MICRO_CTRL(_pc)			(((phy84328_dev_desc_t *)((_pc) + 1))->micro_ctrl)
    499 #define CFG_SYS_INTF(_pc)		(((phy84328_dev_desc_t *)((_pc) + 1))->cfg_sys_intf)
    500 #define PORT_ENABLE_DELAY(_pc)	(((phy84328_dev_desc_t *)((_pc) + 1))->port_enable_delay)
    501 
    502 /* Polarity config */
    503 #define POL_CONFIG_ALL_LANES			1
    504 #define POL_CONFIG_LANE_WIDTH			0x4
    505 #define POL_CONFIG_LANE_MASK(_ln)		(0xf << ((_ln) * POL_CONFIG_LANE_WIDTH))
    506 /*
    507  * When a port is being flexed between 40G->10G, 
    508  * the polarity config syntax can be in
    509  * 40G syntax for first lane, so there is a need to parse 
    510  * both 10G and 40G polarity config syntax in 10G.
    511  */
    512 #define PHY84328_LN(_pc)         ((_pc)->phy_id & 0x3)
    513 #define PHY84328_POL_MASK(_pc)   POL_CONFIG_LANE_MASK(PHY84328_LN(_pc))
    514 #define PHY84328_10G_POL_CFG_GET(_pc, _pol) \
    515 (((_pol) == POL_CONFIG_ALL_LANES) ||  \
    516 (((_pol) & PHY84328_POL_MASK(_pc)) ==  PHY84328_POL_MASK(_pc)))
    517 
    518 
    519 typedef enum {
    520 	PHY84328_INTF_SIDE_LINE,
    521 	PHY84328_INTF_SIDE_SYS
    522 } phy84328_intf_side_t;
    523 
    524 
    525 STATIC int _phy_84328_chip_id_get(int unit, soc_port_t port, phy_ctrl_t *pc, uint32 *chip_id);
    526 /* interface primitives */
    527 STATIC int _phy_84328_intf_is_single_port(soc_port_if_t intf_type);
    528 STATIC int _phy_84328_intf_is_quad_port(soc_port_if_t intf_type);
    529 STATIC int _phy_84328_intf_type_reg_get(int unit, soc_port_t port, soc_port_if_t intf_type,
    530 										 phy84328_intf_side_t side, uint16 *reg_data, uint16 *reg_mask);
    531 STATIC int _phy_84328_intf_update(int unit, soc_port_t port, uint16 reg_data, uint16 reg_mask);
    532 STATIC int _phy_84328_intf_line_sys_params_get(int unit, soc_port_t port);
    533 STATIC int _phy_84328_intf_line_sys_update(int unit, soc_port_t port);
    534 STATIC int _phy_84328_intf_line_sys_init(int unit, soc_port_t port);
    535 STATIC int _phy_84328_intf_datapath_update(int unit,  soc_port_t port);
    536 STATIC int _phy_84328_intf_speed_reg_get(int unit, soc_port_t port, int speed,
    537 										 uint16 *reg_data, uint16 *reg_mask);
    538 
    539 STATIC int _phy_84328_intf_link_get(int unit, soc_port_t port, uint16 *link);
    540 STATIC int _phy_84328_intf_print(int unit, soc_port_t port, const char *msg);
    541 STATIC void _phy_84328_intf_side_regs_select(int unit, soc_port_t port, phy84328_intf_side_t side);
    542 STATIC phy84328_intf_side_t _phy_84328_intf_side_regs_get(int unit, soc_port_t);
    543 STATIC int _phy_84328_intf_datapath_reg_get(int unit, soc_port_t port, phy84328_datapath_t datapath, 
    544 											uint16 *reg_data, uint16 *reg_mask);
    545 STATIC int _phy_84328_intf_line_forced(int unit, soc_port_t port, soc_port_if_t intf_type);
    546 STATIC int _phy_84328_config_devid(int unit,soc_port_t port, phy_ctrl_t *pc, uint32 *devid);
    547 STATIC int _phy_84328_speed_set(int unit, soc_port_t port, int speed);
    548 STATIC int _phy_84328_polarity_flip(int unit, soc_port_t port, uint16 cfg_tx_pol, uint16 cfg_rx_pol);
    549 STATIC int _phy_84328_intf_type_set(int unit, soc_port_t port, soc_port_if_t pif, int must_update);
    550 STATIC int _phy_84328_txmode_manual_set(int unit, soc_port_t port, phy84328_intf_side_t side, int set);
    551 STATIC int _phy_84328_tx_config(int unit, soc_port_t port);
    552 STATIC int _phy_84328_tx_enable(int unit, soc_port_t port, phy84328_intf_side_t side, int enable);
    553 STATIC int _phy_84328_sw_rx_los_pause(int unit, soc_port_t, int enable);
    554 STATIC int _phy_84328_link_mon_pause(int unit, soc_port_t, int enable);
    555 STATIC int _phy_84328_control_tx_driver_set(int unit, soc_port_t port, soc_phy_control_t type,
    556                                             phy84328_intf_side_t side, uint32 value);
    557 STATIC int phy_84328_control_port_set(int unit, soc_port_t port, soc_phy_control_t type, uint32 value);
    558 STATIC int phy_84328_control_port_get(int unit, soc_port_t port, soc_phy_control_t type, uint32 *value);
    559 
    560 /* Debug support for selective tracing mdio by this driver */
    561 /* #define PHY84328_MDIO_TRACING 1 */
    562 #ifdef PHY84328_MDIO_TRACING
    563 STATIC int _phy_84328_dbg_read(int unit, phy_ctrl_t *pc, uint32 addr, uint16 *data);
    564 STATIC int _phy_84328_dbg_write(int unit, phy_ctrl_t *pc, uint32 addr, uint16 data);
    565 STATIC int _phy_84328_dbg_modify(int unit, phy_ctrl_t *pc, uint32 addr, uint16 data, uint16 mask);
    566 
    567 #undef  READ_PHY_REG
    568 #define READ_PHY_REG(_unit, _pc,  _addr, _value) \
    569             ((_phy_84328_dbg_read)((_pc->unit), _pc, (_addr), (_value)))
    570 #undef  WRITE_PHY_REG
    571 #define WRITE_PHY_REG(_unit, _pc, _addr, _value) \
    572             ((_phy_84328_dbg_write)((_pc->unit), _pc, (_addr), (_value)))
    573 #undef  MODIFY_PHY_REG
    574 #define MODIFY_PHY_REG(_unit, _pc, _addr, _data, _mask) \
    575 			(_phy_84328_dbg_modify((_unit), (_pc), (_addr), (_data), (_mask)))
    576 #endif /* PHY84328_MDIO_TRACING */
    577 
    578 extern unsigned char phy84328_ucode_bin[];
    579 extern unsigned int phy84328_ucode_bin_len;
    580 extern unsigned char phy84328B0_ucode_bin[];
    581 extern unsigned int phy84328B0_ucode_bin_len;
    582 static char *dev_name_84328_a0 = "BCM84328_A0";
    583 static char *dev_name_84328 = "BCM84328";
    584 static char *dev_name_84324 = "BCM84324";
    585 static char *dev_name_84088 = "BCM84088";
    586 static char *dev_name_84024 = "BCM84024";
    587 
    588 static const char *phy84328_intf_names[] = SOC_PORT_IF_NAMES_INITIALIZER;
    589 
    590 /* callback to deliever the firmware by application 
    591  * return value: TRUE  successfully delivered
    592  *               FALSE fail to deliver
    593  *
    594  * Example:
    595  *
    596  * int user_firmware_send (int unit,int port,int flag,unsigned char **data,int *len)
    597  * {
    598  *     *data = phy84328_ucode_bin;
    599  *     *len  = phy84328_ucode_bin_len;
    600  *     return TRUE;
    601  * }
    602  * Then initialize the function pointer before the BCM port initialization: 
    603  * phy_84328_uc_firmware_hook = user_firmware_send;
    604  */
    605 int (*phy_84328_uc_firmware_hook)(
    606        int unit, /* switch number */
    607        int port, /* port number */
    608        int flag, /* any information need to ba passed. Not used for now*/
    609        unsigned char **addr,  /* starting address of delivered firmware */
    610        int *len               /* length of the firmware */
    611        ) = NULL;          
    612 
    613 STATIC int
    614 _phy_84328_chip_id_get(int unit, soc_port_t port, phy_ctrl_t *pc, uint32 *chip_id)
    615 {
    616 	int rv = SOC_E_NONE;
    617 
    618     uint16 chip_id_lsb = 0, chip_id_msb = 0;
    619 
    620     *chip_id = 0;
    621 
    622     SOC_IF_ERROR_RETURN(
    623             READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_CHIP_ID0_REGISTER, &chip_id_lsb));
    624     SOC_IF_ERROR_RETURN(
    625             READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_CHIP_ID1_REGISTER, &chip_id_msb));
    626 
    627     if (chip_id_msb == 0x8) {
    628         if (chip_id_lsb == 0x4328) {
    629             *chip_id = PHY84328_ID_84328;
    630         } else if (chip_id_lsb == 0x4324) {
    631             *chip_id = PHY84328_ID_84324;
    632         } else if (chip_id_lsb == 0x4088) {
    633             *chip_id = PHY84328_ID_84088;
    634         } else if(chip_id_lsb == 0x4024) {
    635             *chip_id = PHY84328_ID_84024;
    636         } else {
    637 			LOG_ERROR(BSL_LS_SOC_PHY,
    638                                   (BSL_META_U(unit,
    639                                               "PHY84328  bad chip id: u=%d p=%d chipid %x%x\n"),
    640                                               unit, port, chip_id_msb, chip_id_lsb));
    641 			rv = SOC_E_BADID;
    642 		}
    643     }  
    644     return rv;
    645 }
    646 
    647 STATIC void
    648 _phy_84328_intf_side_regs_select(int unit, soc_port_t port, phy84328_intf_side_t side)
    649 {
    650 	int rv;
    651 	uint16 data, mask;
    652 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
    653 
    654 	assert((side == PHY84328_INTF_SIDE_SYS) || (side == PHY84328_INTF_SIDE_LINE));
    655 	data = (side == PHY84328_INTF_SIDE_SYS) ? (1 << PHY84328_DEV1_XPMD_REGS_SEL_SELECT_SYS_REGISTERS_SHIFT) : 0;
    656 	mask = PHY84328_DEV1_XPMD_REGS_SEL_SELECT_SYS_REGISTERS_MASK;
    657  
    658     /* configure all  ports  */
    659 	    rv = MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_XPMD_REGS_SEL, data, mask);
    660 	    if (SOC_FAILURE(rv)) {
    661 		    phy84328_counters_t *counters = &(COUNTERS(pc));
    662 		    counters->side_sel_err++;
    663 	    }
    664 }
    665 
    666 STATIC phy84328_intf_side_t
    667 _phy_84328_intf_side_regs_get(int unit, soc_port_t port)
    668 {
    669 	int rv;
    670 	uint16 data;
    671 	phy84328_intf_side_t side = PHY84328_INTF_SIDE_LINE;
    672 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
    673 
    674 	rv = READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_XPMD_REGS_SEL, &data);
    675 	if (rv == SOC_E_NONE) {
    676 		side = ((data & PHY84328_DEV1_XPMD_REGS_SEL_SELECT_SYS_REGISTERS_MASK) ==
    677 				(1 << PHY84328_DEV1_XPMD_REGS_SEL_SELECT_SYS_REGISTERS_SHIFT)) ?
    678 			PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE;
    679 	}
    680 	return side;
    681 }
    682 
    683 STATIC int
    684 _phy_84328_intf_print(int unit, soc_port_t port, const char *msg)
    685 {
    686 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
    687     phy_ctrl_t  *pc;
    688 	phy84328_intf_cfg_t *line_intf, *sys_intf;
    689 
    690     pc = EXT_PHY_SW_STATE(unit, port);
    691 	line_intf = &(LINE_INTF(pc));
    692 	sys_intf = &(SYS_INTF(pc));
    693 
    694 	LOG_INFO(BSL_LS_SOC_PHY,
    695                  (BSL_META_U(unit,
    696                              "%s: "), msg));
    697 	LOG_INFO(BSL_LS_SOC_PHY,
    698                  (BSL_META_U(unit,
    699                              "[LINE:intf=%s,speed=%d], "), 
    700                              phy84328_intf_names[line_intf->type], line_intf->speed));
    701 	LOG_INFO(BSL_LS_SOC_PHY,
    702                  (BSL_META_U(unit,
    703                              "[SYS :intf=%s,speed=%d]\n"), 
    704                              phy84328_intf_names[sys_intf->type], sys_intf->speed));
    705 #endif /* BROADCOM_DEBUG || DEBUG_PRINT */
    706 	
    707 	return SOC_E_NONE;
    708 }
    709 
    710 STATIC int
    711 _phy_84328_intf_is_single_port(soc_port_if_t intf_type)
    712 {
    713 	int rv;
    714 
    715 	switch (intf_type) {
    716 	case SOC_PORT_IF_CR4:
    717 	case SOC_PORT_IF_KR4:
    718 	case SOC_PORT_IF_XLAUI:
    719     case SOC_PORT_IF_LR4:
    720     case SOC_PORT_IF_SR4:
    721     case SOC_PORT_IF_CAUI:
    722 /*****CR10 TBD ****
    723     case SOC_PORT_IF_CR10:
    724  *****CR10 TBD ****/
    725 		rv = TRUE;
    726 		break;
    727 	default:
    728 		rv = FALSE;
    729 	}
    730 	return rv;
    731 }
    732 
    733 STATIC int
    734 _phy_84328_intf_is_quad_port(soc_port_if_t intf_type)
    735 {
    736 	int rv;
    737 
    738 	switch (intf_type) {
    739 	case SOC_PORT_IF_SR:
    740 	case SOC_PORT_IF_CR:
    741 	case SOC_PORT_IF_KR:
    742 	case SOC_PORT_IF_XFI:
    743 	case SOC_PORT_IF_SFI:
    744     case SOC_PORT_IF_LR:
    745     case SOC_PORT_IF_ZR:
    746     case SOC_PORT_IF_KX:
    747     case SOC_PORT_IF_GMII:
    748     case SOC_PORT_IF_SGMII:
    749 		rv = TRUE;
    750 		break;
    751 	default:
    752 		rv = FALSE;
    753 	}
    754 	return rv;
    755 }
    756 
    757 STATIC int
    758 _phy_84328_intf_type_10000(soc_port_if_t intf_type)
    759 {
    760 	int rv;
    761 
    762 	switch (intf_type) {
    763 	case SOC_PORT_IF_SR:
    764 	case SOC_PORT_IF_CR:
    765 	case SOC_PORT_IF_KR:
    766 	case SOC_PORT_IF_ZR:
    767 	case SOC_PORT_IF_XFI:
    768 	case SOC_PORT_IF_SFI:
    769     case SOC_PORT_IF_LR:
    770 		rv = TRUE;
    771 		break;
    772 	default:
    773 		rv = FALSE;
    774 	}
    775 	return rv;
    776 }
    777 STATIC int
    778 _phy_84328_intf_type_1000(soc_port_if_t intf_type)
    779 {
    780 	int rv;
    781 
    782 	switch (intf_type) {
    783     case SOC_PORT_IF_KX:
    784     case SOC_PORT_IF_GMII:
    785     case SOC_PORT_IF_SGMII:
    786 		rv = TRUE;
    787 		break;
    788 	default:
    789 		rv = FALSE;
    790 	}
    791 	return rv;
    792 }
    793 
    794 /*
    795  * Return the settings in gp_register_1 for the line inteface type 
    796  *
    797  *    SOC_PORT_IF       SPEED      GP_REGISTER_1           
    798  *    ------------   -----------   -------------------------------------------
    799  *      XFI            10G(1G)     OPTICAL
    800  *      SR             10G(1G)     OPTICAL
    801  *      LR             10G(1G)     OPTICAL+LR
    802  *      CR             10G(1G)     OPTICAL+CU
    803  *      XLAUI          10G(1G)     OPTICAL
    804  *      SR4            40G         OPTICAL
    805  *      LR4            40G(1G)     OPTICAL+LR
    806  *      CR4            40G(1G)     OPTICAL+CU
    807  *      KX             1G          BACKPLANE
    808  *      KR             10G         BACKPLANE
    809  *      KR4            40G         BACKPLANE
    810  *      KR2            20G         BACKPLANE
    811  *      XFI2           20G(1G)     OPTICAL
    812  *      SR2            20G(1G)     OPTICAL
    813  *      CR2            20G         OPTICAL+CU
    814  */
    815 
    816 STATIC int
    817 _phy_84328_intf_type_reg_get(int unit, soc_port_t port, soc_port_if_t intf_type,
    818 							 phy84328_intf_side_t side, uint16 *reg_data, uint16 *reg_mask)
    819 {
    820 	uint16 data = 0;
    821     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
    822 
    823 	assert((side == PHY84328_INTF_SIDE_LINE) || (side == PHY84328_INTF_SIDE_SYS));
    824 	*reg_data = 0;
    825 	*reg_mask = 0;
    826 
    827 	switch (intf_type) {
    828     case SOC_PORT_IF_KX:
    829     case SOC_PORT_IF_KR:
    830     case SOC_PORT_IF_KR4:
    831 		if (side == PHY84328_INTF_SIDE_SYS) {
    832 			data = SYS_FORCED_CL72(pc) ? (1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_SHIFT) :
    833 				(1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_TYPE_SHIFT);
    834 		} else {
    835 			/* line side */
    836 			data = (1 << PHY84328_DEV1_GP_REGISTER_1_LINE_TYPE_SHIFT);
    837 		}
    838         break;
    839     case SOC_PORT_IF_SR:
    840     case SOC_PORT_IF_SR4:
    841     case SOC_PORT_IF_GMII:
    842     case SOC_PORT_IF_SGMII:
    843         data = 0;
    844         break;
    845     case SOC_PORT_IF_ZR:
    846         data = (1 << PHY84328_DEV1_GP_REGISTER_1_LINE_LR_MODE_SHIFT) |
    847             (1 << PHY84328_DEV1_GP_REGISTER_1_LINE_FORCED_CL72_MODE_SHIFT);
    848         break;
    849     case SOC_PORT_IF_CR4:
    850 		/* 
    851 		 * If CR4 line side and autoneg enabled, then CR4, otherwise, DAC/XLAUI_DFE
    852 		 */
    853 		if (side == PHY84328_INTF_SIDE_LINE) {
    854 			/* 
    855 			 * If CR4 line side and autoneg enabled, then CR4, otherwise, DAC/XLAUI_DFE
    856 			 */
    857 			data = (AN_EN(pc)) ? (1 << PHY84328_DEV1_GP_REGISTER_1_LINE_CU_TYPE_SHIFT) :
    858 				((1 << PHY84328_DEV1_GP_REGISTER_1_LINE_FORCED_CL72_MODE_SHIFT) |
    859 				 (1 << PHY84328_DEV1_GP_REGISTER_1_LINE_CU_TYPE_SHIFT));
    860 		} else {
    861 			/* System side set to XLAUI_DFE */
    862 			data = (1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_SHIFT) |
    863 				(1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_CU_TYPE_SHIFT);
    864 		}
    865         break;
    866     case SOC_PORT_IF_CR:
    867         data = (side == PHY84328_INTF_SIDE_SYS) ?
    868 			((1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_SHIFT) |
    869 			 (1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_CU_TYPE_SHIFT)) :
    870 			(1 << PHY84328_DEV1_GP_REGISTER_1_LINE_CU_TYPE_SHIFT);
    871         break;
    872 
    873     case SOC_PORT_IF_XFI:
    874     case SOC_PORT_IF_SFI:
    875     case SOC_PORT_IF_XLAUI:
    876     case SOC_PORT_IF_CAUI:
    877         data = (side == PHY84328_INTF_SIDE_SYS) ?
    878             ((1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_LR_MODE_SHIFT) |
    879              (1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_CU_TYPE_SHIFT)) :
    880             ((1 << PHY84328_DEV1_GP_REGISTER_1_LINE_LR_MODE_SHIFT) |
    881              (1 << PHY84328_DEV1_GP_REGISTER_1_LINE_CU_TYPE_SHIFT));
    882         break;
    883     case SOC_PORT_IF_LR:
    884     case SOC_PORT_IF_LR4:
    885         data = (side == PHY84328_INTF_SIDE_SYS) ?
    886             (1 << PHY84328_DEV1_GP_REGISTER_1_SYSTEM_LR_MODE_SHIFT) :
    887             (1 << PHY84328_DEV1_GP_REGISTER_1_LINE_LR_MODE_SHIFT);
    888         break;
    889     default:
    890         LOG_ERROR(BSL_LS_SOC_PHY,
    891                   (BSL_META_U(unit,
    892                               "84328 Unsupported interface: u=%d p=%d\n"), unit, port));
    893         return SOC_E_UNAVAIL;
    894 	};
    895 
    896     *reg_data |= (data | PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE);
    897 
    898     if (side == PHY84328_INTF_SIDE_LINE) {
    899         *reg_mask |= (PHY84328_DEV1_GP_REGISTER_1_LINE_LR_MODE_MASK |
    900                       PHY84328_DEV1_GP_REGISTER_1_LINE_FORCED_CL72_MODE_MASK |
    901                       PHY84328_DEV1_GP_REGISTER_1_LINE_CU_TYPE_MASK |
    902                       PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE_MASK |
    903                       PHY84328_DEV1_GP_REGISTER_1_LINE_TYPE_MASK);
    904 
    905     } else {
    906         /* System side mask */
    907         *reg_mask |=  (PHY84328_DEV1_GP_REGISTER_1_SYSTEM_LR_MODE_MASK |
    908                        PHY84328_DEV1_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_MASK |
    909                        PHY84328_DEV1_GP_REGISTER_1_SYSTEM_CU_TYPE_MASK |
    910                        PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE_MASK |
    911                        PHY84328_DEV1_GP_REGISTER_1_SYSTEM_TYPE_MASK);
    912     }
    913     LOG_INFO(BSL_LS_SOC_PHY,
    914              (BSL_META_U(unit,
    915                          "84328 intf type register: u=%d, p=%d, reg=%04x/%04x, intf=%d\n"),
    916                          unit, port, *reg_data, *reg_mask, intf_type));
    917 
    918 	return SOC_E_NONE;
    919 }
    920 
    921 
    922 STATIC int
    923 _phy_84328_polarity_redo(int unit, soc_port_t port)
    924 {
    925 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
    926 	return _phy_84328_polarity_flip(unit, port, POL_TX_CFG(pc), POL_RX_CFG(pc));
    927 }
    928 
    929 STATIC void
    930 _phy_84328_micro_pause(int unit, soc_port_t port, const char *loc)
    931 {
    932 	int rv = SOC_E_NONE;
    933     uint16 data, mask;
    934 	int checks;
    935 	uint16 csr;
    936 	uint16 saved_side;
    937     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
    938 	phy84328_micro_ctrl_t *micro_ctrl = &(MICRO_CTRL(pc));
    939 	phy84328_counters_t *counters = &(COUNTERS(pc));
    940 
    941 	if (!micro_ctrl->enable) {
    942 		return;
    943 	}
    944 
    945 	/* Access line side registers */
    946 	saved_side = _phy_84328_intf_side_regs_get(unit, port);
    947 	if (saved_side == PHY84328_INTF_SIDE_SYS) {
    948 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
    949 	}
    950 
    951 	micro_ctrl->count++;
    952     /* Quiet micro */
    953     data = 0;
    954 	mask = 0xff00;
    955     rv = MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0, data, mask);
    956 	if (rv != SOC_E_NONE) {
    957 		goto fail;
    958 	}
    959     sal_udelay(500);
    960 	checks = 0;
    961 	while (checks < 1000) {
    962 		/* Make sure micro really paused */
    963 		rv = READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_2, &data);
    964 		if (rv != SOC_E_NONE) {
    965 			goto fail;
    966 		}
    967 		if ((data & mask) == 0) {
    968 			break;
    969 		}
    970 		sal_udelay(100);
    971 		checks++;
    972 	}
    973 	if (data & mask) {
    974 		rv = READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0, &csr);
    975 		if (rv != SOC_E_NONE) {
    976 			goto fail;
    977 		}
    978 		LOG_INFO(BSL_LS_SOC_PHY,
    979                          (BSL_META_U(unit,
    980                                      "84328 microcode did not pause in %s: "
    981                                      "u=%d p%d 1.ca18/1.ca19=%04x/%04x checks=%d\n"), 
    982                           loc, unit, port, csr, data, checks));
    983         counters->micro_nopause++;
    984 	}
    985 
    986 fail:
    987 	if (saved_side != PHY84328_INTF_SIDE_LINE) {
    988         _phy_84328_intf_side_regs_select(unit, port, saved_side);
    989 	}
    990 	return;
    991 }
    992 
    993 STATIC void
    994 _phy_84328_micro_resume(int unit, soc_port_t port)
    995 {
    996 	phy84328_intf_side_t saved_side;
    997 	int rv = SOC_E_NONE;
    998     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
    999 	phy84328_micro_ctrl_t *micro_ctrl = &(MICRO_CTRL(pc));
   1000 
   1001 	if (!micro_ctrl->enable) {
   1002 		return;
   1003 	}
   1004 
   1005 	/* Access line side registers */
   1006 	saved_side = _phy_84328_intf_side_regs_get(unit, port);
   1007 	if (saved_side == PHY84328_INTF_SIDE_SYS) {
   1008 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   1009 	}
   1010 
   1011 	micro_ctrl->count--;
   1012 	if (micro_ctrl->count <= 0) {
   1013 		rv = MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0, 
   1014 											 0xff00, 0xff00);
   1015 		if (rv != SOC_E_NONE) {
   1016 			goto fail;
   1017 		}
   1018 		if (micro_ctrl->count < 0) {
   1019 			LOG_VERBOSE(BSL_LS_SOC_PHY,
   1020                                     (BSL_META_U(unit,
   1021                                                 "84328 unmatched micro resume\n")));
   1022 			micro_ctrl->count = 0;;
   1023 		}
   1024 	}
   1025 
   1026 fail:
   1027 	if (saved_side != PHY84328_INTF_SIDE_LINE) {
   1028         _phy_84328_intf_side_regs_select(unit, port, saved_side);
   1029 	}
   1030 	return;
   1031 }
   1032 
   1033 STATIC int
   1034 _phy_84328_config_update(int unit, soc_port_t port)
   1035 {
   1036     int rv;
   1037     phy84328_datapath_t save_dp;
   1038     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   1039 
   1040 	PHY_84328_MICRO_PAUSE(unit, port, "config update");
   1041 
   1042 	SOC_IF_ERROR_RETURN(_phy_84328_tx_config(unit, port));
   1043 
   1044     save_dp = CUR_DATAPATH(pc);
   1045     CUR_DATAPATH(pc) = PHY84328_DATAPATH_20;
   1046     rv = _phy_84328_polarity_redo(unit, port);
   1047     if (rv != SOC_E_NONE) {
   1048         LOG_ERROR(BSL_LS_SOC_PHY,
   1049                   (BSL_META_U(unit,
   1050                               "84328  failed updating config: u=%d port=%d\n"), unit, port));
   1051     }
   1052 
   1053 	if (save_dp !=  PHY84328_DATAPATH_20) {
   1054 		CUR_DATAPATH(pc) = PHY84328_DATAPATH_4_DEPTH1;
   1055 		rv = _phy_84328_polarity_redo(unit, port);
   1056 		if (rv != SOC_E_NONE) {
   1057 			LOG_ERROR(BSL_LS_SOC_PHY,
   1058                                   (BSL_META_U(unit,
   1059                                               "84328  failed updating config: u=%d port=%d\n"), unit, port));
   1060 		}
   1061 	}
   1062 
   1063     if (save_dp != CUR_DATAPATH(pc)) {
   1064         CUR_DATAPATH(pc) = save_dp;
   1065     }
   1066 
   1067 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   1068 	/* Bypass steady state tuning */
   1069 	if (BYPASS_SS_TUNING(pc)) {
   1070 		SOC_IF_ERROR_RETURN(
   1071 			MODIFY_PHY84328_MMF_PMA_PMD_REG(
   1072 				unit, pc, PHY84328_DEV1_TUNING_STATE_BYPASS, 
   1073 				PHY84328_DEV1_TUNING_STATE_BYPASS_BYPASS_STEADY_STATE_TUNING_MASK,
   1074 				PHY84328_DEV1_TUNING_STATE_BYPASS_BYPASS_STEADY_STATE_TUNING_MASK));
   1075 	} else {
   1076 		SOC_IF_ERROR_RETURN(
   1077 			MODIFY_PHY84328_MMF_PMA_PMD_REG(
   1078 				unit, pc, PHY84328_DEV1_TUNING_STATE_BYPASS, 
   1079 				0,
   1080 				PHY84328_DEV1_TUNING_STATE_BYPASS_BYPASS_STEADY_STATE_TUNING_MASK));
   1081 	}
   1082 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   1083 
   1084 	PHY_84328_MICRO_RESUME(unit, port);
   1085 
   1086     return SOC_E_NONE;
   1087 }
   1088 
   1089 /* 
   1090  * Updates are done to GP_REGISTER_1 which are line side registers only, ie. no
   1091  * system side instances of these registers
   1092  */
   1093 STATIC int
   1094 _phy_84328_intf_update(int unit, soc_port_t port, uint16 reg_data, uint16 reg_mask)
   1095 {
   1096 	uint16		ucode_csr_bef = 0, ucode_csr = 0, drv_csr = 0;
   1097 	phy84328_intf_side_t saved_side;
   1098 	soc_timeout_t to;
   1099 	int			rv = SOC_E_NONE;
   1100 	uint32		checks;
   1101 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   1102 	phy84328_counters_t *counters = &(COUNTERS(pc));
   1103 
   1104 	/* Access line side registers */
   1105 	saved_side = _phy_84328_intf_side_regs_get(unit, port);
   1106 	if (saved_side == PHY84328_INTF_SIDE_SYS) {
   1107 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   1108 	}
   1109 
   1110 	/* Make sure ucode has acked */
   1111 	rv = READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_3, &ucode_csr_bef);
   1112 	if (SOC_FAILURE(rv)) {
   1113 		LOG_ERROR(BSL_LS_SOC_PHY,
   1114                           (BSL_META_U(unit,
   1115                                       "84328 failed reading ucode csr: u=%d p=%d err=%d\n"),
   1116                                       unit, port, rv));
   1117 						 
   1118 		goto fail;
   1119 	}
   1120 	if ((ucode_csr_bef & PHY84328_DEV1_GP_REGISTER_3_FINISH_CHANGE_MASK) ==
   1121 		PHY84328_DEV1_GP_REGISTER_3_FINISH_CHANGE_MASK) {
   1122 		/* Cmd active and ucode acked, so let ucode know drv saw ack */
   1123 		rv = MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_1,
   1124 											 0,  PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE_MASK);
   1125 		if (SOC_FAILURE(rv)) {
   1126 			LOG_ERROR(BSL_LS_SOC_PHY,
   1127                                   (BSL_META_U(unit,
   1128                                               "84328 failed clearing ack: u=%d p=%d err=%d\n"),
   1129                                               unit, port, rv));
   1130 			goto fail;
   1131 		}
   1132 		/* Wait for ucode to CTS */
   1133 		soc_timeout_init(&to, 1000000, 0);
   1134 		while (!soc_timeout_check(&to)) {
   1135 			rv = READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_3, &ucode_csr);
   1136 			if (SOC_FAILURE(rv)) {
   1137 				LOG_ERROR(BSL_LS_SOC_PHY,
   1138                                           (BSL_META_U(unit,
   1139                                                       "84328 failed reading ucode csr: u=%d p=%d err=%d\n"),
   1140                                                       unit, port, rv));
   1141 				goto fail;
   1142 			}
   1143 			if ((ucode_csr & PHY84328_DEV1_GP_REGISTER_3_FINISH_CHANGE_MASK) == 0) {
   1144 				break;
   1145 			}
   1146 		}
   1147 		if ((ucode_csr & PHY84328_DEV1_GP_REGISTER_3_FINISH_CHANGE_MASK) != 0) {
   1148 			(void) READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_1, &drv_csr);
   1149 			LOG_ERROR(BSL_LS_SOC_PHY,
   1150                                   (BSL_META_U(unit,
   1151                                               "84328 ucode failed to clear to send: u=%d p=%d 1.%04x=%04x 1.%04x=%04x(%04x)\n"), 
   1152                                    unit, port, 
   1153                                    PHY84328_DEV1_GP_REGISTER_1, drv_csr,
   1154                                    PHY84328_DEV1_GP_REGISTER_3, ucode_csr, ucode_csr_bef));
   1155 			rv = SOC_E_TIMEOUT;
   1156 			goto fail;
   1157 		}
   1158 	}
   1159 
   1160     LOG_INFO(BSL_LS_SOC_PHY,
   1161              (BSL_META_U(unit,
   1162                          "84328 intf update register: u=%d, p=%d, 1.%04x=%04x/%04x ucode_csr=%04x\n"),
   1163                          unit, port, PHY84328_DEV1_GP_REGISTER_1, reg_data, reg_mask, ucode_csr));
   1164 
   1165 	counters->intf_updates++;
   1166 
   1167 	/* Send command */
   1168 	rv = MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_1,
   1169 										 reg_data, reg_mask);
   1170 	if (SOC_FAILURE(rv)) {
   1171 		LOG_ERROR(BSL_LS_SOC_PHY,
   1172                           (BSL_META_U(unit,
   1173                                       "84328 failed sending command to ucode: u=%d p=%d err=%d\n"),
   1174                                       unit, port, rv));
   1175 		goto fail;
   1176 	}
   1177 
   1178 	/* Handshake with microcode by waiting for ack before moving on */
   1179 	checks = 0;
   1180 	while (checks < 10000) {
   1181 		rv = READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_3, &ucode_csr);
   1182 		if (SOC_FAILURE(rv)) {
   1183 			LOG_ERROR(BSL_LS_SOC_PHY,
   1184                                   (BSL_META_U(unit,
   1185                                               "84328 failed reading ucode csr: u=%d p=%d err=%d\n"),
   1186                                               unit, port, rv));
   1187 			goto fail;
   1188 		}
   1189 		if ((ucode_csr & PHY84328_DEV1_GP_REGISTER_3_FINISH_CHANGE_MASK) == 
   1190 			PHY84328_DEV1_GP_REGISTER_3_FINISH_CHANGE_MASK) {
   1191 			break;
   1192 		}
   1193 		sal_udelay(100);
   1194 		checks++;
   1195 	}
   1196 	if ((ucode_csr & PHY84328_DEV1_GP_REGISTER_3_FINISH_CHANGE_MASK) != 
   1197 		PHY84328_DEV1_GP_REGISTER_3_FINISH_CHANGE_MASK) {
   1198 		uint16 micro_en;
   1199 		(void) READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_1, &drv_csr);
   1200 		(void) READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0, &micro_en);
   1201 		LOG_ERROR(BSL_LS_SOC_PHY,
   1202                           (BSL_META_U(unit,
   1203                                       "84328: microcode failed to ack: u=%d p=%d 1.%04x=%04x 1.%04x=%04x "
   1204                                       "1.%04x=%04x checks=%d\n"), 
   1205                            unit, port,
   1206                            PHY84328_DEV1_GP_REGISTER_1, drv_csr,
   1207                            PHY84328_DEV1_GP_REGISTER_3, ucode_csr,
   1208                            PHY84328_DEV1_GP_REG_0, micro_en,
   1209                            checks));
   1210 		rv = SOC_E_TIMEOUT;
   1211 		goto fail;
   1212 	}
   1213 
   1214 	/* Cmd active and ucode acked - let ucode know we saw ack */
   1215 	rv = MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_1, 
   1216 										 0,  PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE_MASK);
   1217 	if (rv != SOC_E_NONE) {
   1218 		goto fail;
   1219 	}
   1220     
   1221 fail:
   1222 	if (saved_side == PHY84328_INTF_SIDE_SYS) {
   1223 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   1224 	}
   1225 
   1226 	return rv;
   1227 }
   1228 		
   1229 /*
   1230  *  Populates interface type and speed for line and system side interfaces based on 
   1231  *  line side interface speed and system side interface type
   1232  *
   1233  *  Assumption:
   1234  *     line_intf->speed: must already be set based on port configuration
   1235  *     sys_intf->type: must be set to either the configured _spn_PHY_SYS_INTERFACE value or default
   1236  */
   1237 STATIC int
   1238 _phy_84328_intf_line_sys_params_get(int unit, soc_port_t port)
   1239 {
   1240 	phy84328_intf_cfg_t *line_intf;
   1241 	phy84328_intf_cfg_t *sys_intf;
   1242 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1243 
   1244 	line_intf = &(LINE_INTF(pc));
   1245 	sys_intf = &(SYS_INTF(pc));
   1246 
   1247 	/*
   1248 	 * System side interface was specified so make sure it's compatible with
   1249 	 * line side speed. If not, overwrite with default compatible interface
   1250 	 */
   1251     if (PHY84328_MULTI_CORE_MODE(pc)) {
   1252         sys_intf->speed = 100000;
   1253 		line_intf->type = SOC_PORT_IF_CAUI;
   1254         sys_intf->type = SOC_PORT_IF_CAUI;
   1255     } else if (line_intf->speed == 40000) {
   1256 		sys_intf->speed = 40000;
   1257 		line_intf->type = SOC_PORT_IF_SR4;
   1258 		if (!(_phy_84328_intf_is_single_port(sys_intf->type))) {
   1259 			/* system side interface is not compatible so overwrite with default */
   1260 			LOG_ERROR(BSL_LS_SOC_PHY,
   1261                                   (BSL_META_U(unit,
   1262                                               "PHY84328 incompatible 40G system side interface, "
   1263                                               "using default: u=%d p=%d\n"), unit, port));
   1264 			sys_intf->type = SOC_PORT_IF_XLAUI;
   1265 		}
   1266 	} else { /* 10G/1G */
   1267 		if (_phy_84328_intf_is_quad_port(sys_intf->type)) {
   1268 			if (sys_intf->type == SOC_PORT_IF_KX) {
   1269 				line_intf->speed = 1000;
   1270 				line_intf->type = SOC_PORT_IF_GMII;
   1271 				sys_intf->speed = 1000;
   1272 			} else {
   1273 				/* 10G system side so fix line side to be 10G compatible */
   1274 				line_intf->speed = 10000;
   1275 				line_intf->type = SOC_PORT_IF_SR;
   1276 				sys_intf->speed = 10000;
   1277 			}
   1278 		} else {
   1279 			/* system side interface is not compatible so overwrite with default */
   1280 			LOG_ERROR(BSL_LS_SOC_PHY,
   1281                                   (BSL_META_U(unit,
   1282                                               "PHY84328 incompatible 10G/1G system side interface, "
   1283                                               "using default: u=%d p=%d\n"), unit, port));
   1284 			/* default to 10G interface/speed on both sides */
   1285 			line_intf->speed = 10000;
   1286 			line_intf->type = SOC_PORT_IF_SR;
   1287 			sys_intf->speed = 10000;
   1288 			sys_intf->type =  SOC_PORT_IF_XFI;
   1289 		}
   1290 	}
   1291 	return SOC_E_NONE;
   1292 }
   1293 
   1294 STATIC int
   1295 _phy_84328_intf_line_sys_update(int unit, soc_port_t port)
   1296 {
   1297     phy_ctrl_t  *pc;
   1298 	phy_ctrl_t *int_pc;
   1299     int         int_phy_en = 0;
   1300 	uint16		data = 0, mask = 0;
   1301 	uint16		reg_data = 0, reg_mask = 0;
   1302 	phy84328_intf_cfg_t *line_intf, *sys_intf;
   1303 
   1304     pc = EXT_PHY_SW_STATE(unit, port);
   1305 	int_pc = INT_PHY_SW_STATE(unit, port);
   1306 	line_intf = &(LINE_INTF(pc));
   1307 	sys_intf = &(SYS_INTF(pc));
   1308 	
   1309 	_phy_84328_intf_print(unit, port, "intf update");
   1310 
   1311 	reg_data = 0;
   1312 	reg_mask = 0;
   1313 	SOC_IF_ERROR_RETURN(
   1314 		_phy_84328_intf_type_reg_get(unit, port, line_intf->type, 
   1315 									 PHY84328_INTF_SIDE_LINE, &data, &mask));
   1316 	reg_data |= data;
   1317 	reg_mask |= mask;
   1318 
   1319 	SOC_IF_ERROR_RETURN(
   1320 		_phy_84328_intf_type_reg_get(unit, port, sys_intf->type, 
   1321 									 PHY84328_INTF_SIDE_SYS, &data, &mask));
   1322 	reg_data |= data;
   1323 	reg_mask |= mask;
   1324 
   1325 	SOC_IF_ERROR_RETURN(
   1326 		_phy_84328_intf_speed_reg_get(unit, port, line_intf->speed, &data, &mask));
   1327 	reg_data |= data;	
   1328 	reg_mask |= mask;
   1329 
   1330 	SOC_IF_ERROR_RETURN(
   1331 		_phy_84328_intf_datapath_reg_get(unit, port, CUR_DATAPATH(pc), &data, &mask));
   1332 	reg_data |= data;	
   1333 	reg_mask |= mask;
   1334 
   1335 	LOG_INFO(BSL_LS_SOC_PHY,
   1336                  (BSL_META_U(unit,
   1337                              "84328  intf update: line=%s sys=%s speed=%d (1.%x = %04x/%04x): u=%d p=%d\n"), 
   1338                   phy84328_intf_names[line_intf->type], phy84328_intf_names[sys_intf->type], 
   1339                   line_intf->speed, PHY84328_DEV1_GP_REGISTER_1, reg_data, reg_mask,
   1340                   unit, port));
   1341 
   1342 	if (SYNC_INIT(pc) == 1) {
   1343         SOC_IF_ERROR_RETURN(PHY_ENABLE_GET(int_pc->pd, unit, port, &int_phy_en));
   1344         if (int_phy_en) {
   1345             /* Turn off internal PHY while the mode changes */
   1346             SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 0));
   1347         }
   1348 	}
   1349 	
   1350 	/* GP registers are only on the line side */
   1351 	SOC_IF_ERROR_RETURN(_phy_84328_intf_update(unit, port, reg_data, reg_mask));
   1352 	
   1353     if (SYNC_INIT(pc) == 1) {
   1354         if (int_phy_en) {
   1355             /* If called from PASS2 we skip this and complete in PASS3 */
   1356             if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2)) {
   1357                 INT_PHY_RE_EN(pc) = 1;
   1358                 /* start timer */
   1359                 soc_timeout_init(&SYNC_TO(pc), 10000, 0);
   1360             } else {
   1361                 sal_usleep(10000);
   1362                 /* Turn internal PHY back on now that the mode has been configured */
   1363                 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 1));
   1364             }
   1365         }
   1366     }
   1367 
   1368 	return SOC_E_NONE;
   1369 
   1370 }
   1371 
   1372 /* 
   1373  * Return the settings in gp_reg_1/gp_register_1 for the inteface speed 
   1374  * Register data and mask are returned to modify the register. 
   1375  */
   1376 
   1377 STATIC int
   1378 _phy_84328_intf_speed_reg_get(int unit, soc_port_t port, int speed, uint16 *reg_data, uint16 *reg_mask)
   1379 {
   1380 	*reg_data = 0;
   1381 	*reg_mask = 0;
   1382 	switch (speed) {
   1383 	case 100000:
   1384 		*reg_data = PHY84328_DEV1_GP_REGISTER_1_SPEED_100G;
   1385 		break;
   1386 	case 42000:
   1387 		*reg_data = PHY84328_DEV1_GP_REGISTER_1_SPEED_42G;
   1388 		break;
   1389 	case 40000:
   1390 		*reg_data = PHY84328_DEV1_GP_REGISTER_1_SPEED_40G;
   1391 		break;
   1392 	case 10000:
   1393 		*reg_data = PHY84328_DEV1_GP_REGISTER_1_SPEED_10G;
   1394 		break;
   1395 	case 1000:
   1396     case 100:
   1397     case 10:
   1398 		/* This is a special mode that uses the 10G PLL but runs at 1G */
   1399 		*reg_data = (PHY84328_DEV1_GP_REGISTER_1_SPEED_10G |
   1400 					 PHY84328_DEV1_GP_REGISTER_1_SPEED_1G);
   1401 		break;
   1402 
   1403 	default :
   1404 		LOG_ERROR(BSL_LS_SOC_PHY,
   1405                           (BSL_META_U(unit,
   1406                                       "84328 invalid line speed %d: u=%d p=%d\n"),
   1407                                       speed, unit, port));
   1408 		return SOC_E_CONFIG;
   1409 	}
   1410 			
   1411 	*reg_data |= PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE;
   1412 	*reg_mask |= (PHY84328_DEV1_GP_REGISTER_1_SPEED_1G_MASK |
   1413 				  PHY84328_DEV1_GP_REGISTER_1_SPEED_10G_MASK |
   1414 				  PHY84328_DEV1_GP_REGISTER_1_SPEED_40G_MASK |
   1415 				  PHY84328_DEV1_GP_REGISTER_1_SPEED_100G_MASK |
   1416 				  PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE_MASK);
   1417 
   1418 	LOG_INFO(BSL_LS_SOC_PHY,
   1419                  (BSL_META_U(unit,
   1420                              "84328 speed set register: u=%d, p=%d, reg=%04x/%04x), speed=%d\n"),
   1421                              unit, port, *reg_data, *reg_mask, speed));
   1422 
   1423 	return SOC_E_NONE;
   1424 }
   1425 
   1426 STATIC int
   1427 _phy_84328_intf_datapath_reg_get(int unit, soc_port_t port, phy84328_datapath_t datapath, 
   1428 								 uint16 *reg_data, uint16 *reg_mask)
   1429 {
   1430 	*reg_data = 0;
   1431 	*reg_mask = 0;
   1432 
   1433 	switch (datapath) {
   1434 	case PHY84328_DATAPATH_20:
   1435 		*reg_data = 0;
   1436 		break;
   1437 	case PHY84328_DATAPATH_4_DEPTH1:
   1438 		*reg_data = PHY84328_DEV1_GP_REGISTER_1_DATAPATH_4_DEPTH1;
   1439 		break;
   1440 	case PHY84328_DATAPATH_4_DEPTH2:
   1441 		*reg_data = PHY84328_DEV1_GP_REGISTER_1_DATAPATH_4_DEPTH2;
   1442 		break;
   1443 
   1444 	default :
   1445 		LOG_ERROR(BSL_LS_SOC_PHY,
   1446                           (BSL_META_U(unit,
   1447                                       "84328 invalid datapath: u=%d p=%d datapath=%d\n"),
   1448                                       unit, port, datapath));
   1449 		return SOC_E_CONFIG;
   1450 	}
   1451 	*reg_data |= PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE;	
   1452 	*reg_mask = (PHY84328_DEV1_GP_REGISTER_1_DATAPATH_MASK |
   1453 		PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE_MASK);
   1454 
   1455 	LOG_INFO(BSL_LS_SOC_PHY,
   1456                  (BSL_META_U(unit,
   1457                              "84328 datapath set register: u=%d, p=%d, reg=%04x/%04x, datapath=%d\n"),
   1458                              unit, port, *reg_data, *reg_mask, datapath));
   1459 
   1460 	return SOC_E_NONE;
   1461 }
   1462 
   1463 STATIC int
   1464 _phy_84328_intf_datapath_update(int unit,  soc_port_t port)
   1465 {
   1466 	phy_ctrl_t  *pc;
   1467 	uint16      data = 0, mask = 0;
   1468 
   1469 	pc = EXT_PHY_SW_STATE(unit, port);
   1470 
   1471 	SOC_IF_ERROR_RETURN(
   1472         _phy_84328_intf_datapath_reg_get(unit, port, CUR_DATAPATH(pc), &data, &mask));
   1473 
   1474 	/* GP registers are only on the line side */
   1475 	SOC_IF_ERROR_RETURN(_phy_84328_intf_update(unit, port, data, mask));
   1476 
   1477 	return SOC_E_NONE;
   1478 }
   1479 
   1480 /*
   1481  * Select channel with mapped access based on interface side and lane number
   1482  * For details, see PHY-700
   1483  */
   1484 STATIC int
   1485 _phy_84328_channel_mapped_select(int unit, soc_port_t port, phy84328_intf_side_t side, int lane)
   1486 {
   1487     uint16 lane_sel;
   1488     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1489     /* logical channel number for physical channel, indexed by lane/channel */
   1490     static uint16 log_ch_map[] = { 0xe4, 0xe1, 0xc6, 0x27 }; 
   1491 
   1492     if (lane == PHY84328_ALL_LANES) {
   1493         /* Restore 1:1 channel mappings */
   1494         SOC_IF_ERROR_RETURN(
   1495             MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_LOGAD_CTRL, 0xe4, 0x00ff));
   1496         lane_sel = 
   1497             (LOGICAL_LANE0(pc) << PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT) |
   1498             PHY84328_DEV1_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK |
   1499             PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_MASK;
   1500     } else {
   1501         /* System side interface always use first channel which then is mapped */
   1502         if (side == PHY84328_INTF_SIDE_SYS) {
   1503             lane_sel = 1;
   1504         } else {
   1505             /* Select channel in Single PMD 1.ca86[5:4] and [3..0] that corresponds to lane */
   1506             lane_sel = (lane << PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT) |
   1507                 ((1 << lane) & PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_MASK);
   1508         }
   1509     }
   1510 
   1511     SOC_IF_ERROR_RETURN(
   1512         MODIFY_PHY84328_MMF_PMA_PMD_REG(
   1513             unit, pc, PHY84328_DEV1_SINGLE_PMD_CTRL, lane_sel,
   1514             PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_MASK |
   1515             PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_MASK));
   1516     
   1517     if (side == PHY84328_INTF_SIDE_SYS) {
   1518         /* Map the logical channel from physical channel */
   1519         lane_sel = (lane == PHY84328_ALL_LANES) ? log_ch_map[0] :  log_ch_map[lane];
   1520         SOC_IF_ERROR_RETURN(
   1521             MODIFY_PHY84328_MMF_PMA_PMD_REG(
   1522                 unit, pc, PHY84328_DEV1_LOGAD_CTRL, lane_sel, 0x00ff));
   1523 
   1524         /* Now go to system side to access register */
   1525         _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   1526     }
   1527 
   1528     return SOC_E_NONE;
   1529 }
   1530 
   1531 /*
   1532  * Directly select channel to access based on interface side and lane number.
   1533  */
   1534 STATIC int
   1535 _phy_84328_channel_direct_select(int unit, soc_port_t port, phy84328_intf_side_t side, int lane)
   1536 {
   1537     uint16      lane_sel;
   1538     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1539 
   1540     /*
   1541      * If all lanes, restore single PMD access with lane 0 broadcast to all lanes
   1542      * For single lane, select lane in Single PMD 1.ca86[5:4] and [3..0] that corresponds
   1543      * to the lane with direct lane selection in 1.ca86[8]
   1544      */
   1545     if (lane == PHY84328_ALL_LANES) {
   1546         lane_sel = 
   1547             (LOGICAL_LANE0(pc) << PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT) |
   1548             PHY84328_DEV1_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK |
   1549             PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_MASK;
   1550     } else {
   1551         lane_sel = 0x100 | (lane << PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT) |
   1552             ((1 << lane) & PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_MASK);
   1553     }
   1554 
   1555     SOC_IF_ERROR_RETURN(
   1556         MODIFY_PHY84328_MMF_PMA_PMD_REG(
   1557             unit, pc, PHY84328_DEV1_SINGLE_PMD_CTRL, lane_sel,
   1558             0x100 | PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_MASK |
   1559             PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_BE_DISABLE_IN_SINGLE_PMD_MASK));
   1560 
   1561     if (side == PHY84328_INTF_SIDE_SYS) {
   1562         /* Now go to system side to access register */
   1563         _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   1564     }
   1565     return SOC_E_NONE;
   1566 }
   1567 
   1568 /*
   1569  * Select channel to access based on interface side and lane number.
   1570  * The side is selected before returning.
   1571  */
   1572 STATIC int
   1573 _phy_84328_channel_select(int unit, soc_port_t port, phy84328_intf_side_t side, int lane)
   1574 {
   1575     int rv;
   1576     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1577 
   1578     if (!(PHY84328_SINGLE_PORT_MODE(pc))) {
   1579         return SOC_E_PARAM;
   1580     }
   1581 
   1582     if (!((lane == PHY84328_ALL_LANES) || ((lane >= 0) && (lane <= 3)))) {
   1583         return SOC_E_PARAM;
   1584     }
   1585 
   1586     _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   1587 
   1588     if ((side == PHY84328_INTF_SIDE_LINE) || (DEVREV(pc) != 0x00a0)) {
   1589         rv  = _phy_84328_channel_direct_select(unit, port, side, lane);
   1590     } else {
   1591         rv  = _phy_84328_channel_mapped_select(unit, port, side, lane);
   1592     }
   1593 
   1594     return rv;
   1595 }
   1596 
   1597 /*
   1598  *   20-bit: set txpol in line side 1.c061[5]
   1599  *   4-bit:  set txpol in line side 1.c068[12]
   1600  */
   1601 STATIC int
   1602 _phy_84328_polarity_flip_tx_set(int unit, soc_port_t port, int flip)
   1603 {	
   1604 	uint16		data, mask;
   1605 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1606 
   1607 	/* Clear to flip, set to unflip */
   1608 	if (CUR_DATAPATH(pc) == PHY84328_DATAPATH_20) {
   1609 		data = flip ? 0 : PHY84328_DEV1_ANATXACONTROL_TXPOL_FLIP_MASK;
   1610 		mask = PHY84328_DEV1_ANATXACONTROL_TXPOL_FLIP_MASK;
   1611         SOC_IF_ERROR_RETURN(
   1612 			MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL, data, mask));
   1613 	} else {
   1614 		data = flip ? 0 : PHY84328_DEV1_ANATXACONTROL4_XFI_LOWLATENCY_POLARITY_FLIP_MASK;
   1615 		mask = PHY84328_DEV1_ANATXACONTROL4_XFI_LOWLATENCY_POLARITY_FLIP_MASK;
   1616          SOC_IF_ERROR_RETURN(
   1617 			MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL4, data, mask));
   1618 	}
   1619 	return SOC_E_NONE;
   1620 }
   1621 
   1622 STATIC int
   1623 _phy_84328_polarity_flip_tx(int unit, soc_port_t port, uint16 cfg_pol)
   1624 {
   1625 	int			flip;
   1626 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1627 
   1628     if ((PHY84328_SINGLE_PORT_MODE(pc))) {
   1629 		int	lane;
   1630         for (lane = 0; lane < PHY84328_NUM_LANES; lane++) {
   1631 			/* Check for all lanes or whether this lane has polarity flipped */
   1632 			if ((cfg_pol == POL_CONFIG_ALL_LANES) || 
   1633 				((cfg_pol & POL_CONFIG_LANE_MASK(lane)) == POL_CONFIG_LANE_MASK(lane))) {
   1634 				flip = 1;
   1635 			} else {
   1636 				flip = 0;
   1637 			}
   1638 			LOG_INFO(BSL_LS_SOC_PHY,
   1639                                  (BSL_META_U(unit,
   1640                                              "84328 tx polarity flip=%d: u=%d p=%d lane=%d\n"), flip, unit, port, lane));
   1641 
   1642 			/* Select the lane on the line side */
   1643 			SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, PHY84328_INTF_SIDE_LINE, lane));
   1644 			SOC_IF_ERROR_RETURN(_phy_84328_polarity_flip_tx_set(unit, port, flip));
   1645 		}
   1646 		/* Restore to default single port register access */
   1647 		SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, PHY84328_INTF_SIDE_LINE, PHY84328_ALL_LANES));
   1648 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   1649     }
   1650     else {  /* quad mode */
   1651 		flip = PHY84328_10G_POL_CFG_GET(pc,cfg_pol);
   1652 		SOC_IF_ERROR_RETURN(_phy_84328_polarity_flip_tx_set(unit, port, flip));
   1653 		LOG_INFO(BSL_LS_SOC_PHY,
   1654                          (BSL_META_U(unit,
   1655                                      "84328  polarity flip: u=%d p=%d\n"), unit, port));
   1656 	}
   1657 
   1658 	return SOC_E_NONE;
   1659 }
   1660 
   1661 
   1662 /* RX polarity in 20-bit line side with rx inversion in 1.c0ba[3:2] */
   1663 STATIC int
   1664 _phy_84328_polarity_flip_rx_20bit(int unit, soc_port_t port, int flip)
   1665 {
   1666 	uint16		data, mask;
   1667 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1668 	
   1669 	/* Default is clear, set to flip it */
   1670 	data = flip ? (PHY84328_DEV1_GP_REGISTER_RX_INV_FORCE | PHY84328_DEV1_GP_REGISTER_RX_INV_INVERT) : 0;
   1671 	mask = (PHY84328_DEV1_GP_REGISTER_RX_INV_FORCE | PHY84328_DEV1_GP_REGISTER_RX_INV_INVERT);
   1672  
   1673     SOC_IF_ERROR_RETURN(
   1674             MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_RX_INV, data, mask));
   1675 
   1676     return SOC_E_NONE;
   1677 }
   1678 
   1679 /* RX polarity in 4-bit system side polarity in 1.c068[12] */
   1680 STATIC int
   1681 _phy_84328_polarity_flip_rx_4bit(int unit, soc_port_t port, int flip)
   1682 {
   1683 	uint16		data, mask;
   1684 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1685 
   1686     /* Default is set, clear to flip it */
   1687 	data = flip ? 0 : PHY84328_DEV1_ANATXACONTROL4_XFI_LOWLATENCY_POLARITY_FLIP_MASK;
   1688 	mask = PHY84328_DEV1_ANATXACONTROL4_XFI_LOWLATENCY_POLARITY_FLIP_MASK;
   1689 
   1690     SOC_IF_ERROR_RETURN(
   1691             MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL4, data, mask));
   1692 
   1693     return SOC_E_NONE;
   1694 }
   1695 			
   1696 STATIC int
   1697 _phy_84328_polarity_flip_rx(int unit, soc_port_t port, uint16 cfg_pol)
   1698 {
   1699 	int			flip;
   1700 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1701 
   1702 	/*
   1703 	 * RX polarity flipping in 20-bit done on the line side while 4-bit done on the system side
   1704 	 */
   1705     if ((PHY84328_SINGLE_PORT_MODE(pc))) {
   1706 		int	lane;
   1707 		
   1708 		/* 4-bit polarity handled on system side */
   1709 		if (CUR_DATAPATH(pc) != PHY84328_DATAPATH_20) {
   1710 			PHY_84328_MICRO_PAUSE(unit, port, "polarity rx");
   1711 		}
   1712         for (lane = 0; lane < PHY84328_NUM_LANES; lane++) {
   1713 			flip = 0;
   1714 			if ((cfg_pol == POL_CONFIG_ALL_LANES) || 
   1715 				((cfg_pol & POL_CONFIG_LANE_MASK(lane)) == POL_CONFIG_LANE_MASK(lane))) {
   1716 				flip = 1;
   1717 			}
   1718 			if (CUR_DATAPATH(pc) == PHY84328_DATAPATH_20) {
   1719 				SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, PHY84328_INTF_SIDE_LINE, lane));
   1720 				SOC_IF_ERROR_RETURN(_phy_84328_polarity_flip_rx_20bit(unit, port, flip));
   1721 			} else {
   1722 				SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, PHY84328_INTF_SIDE_SYS, lane));
   1723 				SOC_IF_ERROR_RETURN(_phy_84328_polarity_flip_rx_4bit(unit, port, flip));
   1724 			}
   1725 			LOG_INFO(BSL_LS_SOC_PHY,
   1726                                  (BSL_META_U(unit,
   1727                                              "84328 rx polarity flip: u=%d p=%d lane=%d\n"), unit, port, lane));
   1728 		}
   1729 		/* Restore to default single port register access */
   1730 		SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, PHY84328_INTF_SIDE_LINE, PHY84328_ALL_LANES));
   1731 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   1732 		if (CUR_DATAPATH(pc) != PHY84328_DATAPATH_20) {
   1733 			PHY_84328_MICRO_RESUME(unit, port);
   1734 		}
   1735 
   1736     }
   1737     else {  /* quad mode */
   1738 
   1739 		flip = PHY84328_10G_POL_CFG_GET(pc,cfg_pol);
   1740 		if (CUR_DATAPATH(pc) == PHY84328_DATAPATH_20) {
   1741 			_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   1742 			SOC_IF_ERROR_RETURN(_phy_84328_polarity_flip_rx_20bit(unit, port, flip));
   1743 		} else {
   1744 			_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   1745 			SOC_IF_ERROR_RETURN(_phy_84328_polarity_flip_rx_4bit(unit, port, flip));
   1746 			_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   1747 		}
   1748 		LOG_INFO(BSL_LS_SOC_PHY,
   1749                          (BSL_META_U(unit,
   1750                                      "84328 rx polarity flip: u=%d p=%d\n"), unit, port));
   1751 	}
   1752 
   1753 
   1754 	return SOC_E_NONE;
   1755 }
   1756 
   1757 
   1758 /*                                                                                              
   1759  * Flip configured tx/rx polarities
   1760  *
   1761  * Property values are either 1 for all lanes or
   1762  * lane 0: 000f
   1763  * lane 1: 00f0
   1764  * lane 2: 0f00
   1765  * lane 3: f000
   1766  */
   1767 STATIC int
   1768 _phy_84328_polarity_flip(int unit, soc_port_t port, uint16 cfg_tx_pol, uint16 cfg_rx_pol)
   1769 {
   1770 	LOG_INFO(BSL_LS_SOC_PHY,
   1771                  (BSL_META_U(unit,
   1772                              "84328 polarity flip: u=%d p%d TX=%x RX=%x\n"), unit, port, 
   1773                              cfg_tx_pol, cfg_rx_pol));
   1774 
   1775 	SOC_IF_ERROR_RETURN(_phy_84328_polarity_flip_tx(unit, port, cfg_tx_pol));
   1776 
   1777 	SOC_IF_ERROR_RETURN(_phy_84328_polarity_flip_rx(unit, port, cfg_rx_pol));
   1778 
   1779     return SOC_E_NONE;
   1780 }
   1781 
   1782 
   1783 STATIC int
   1784 _phy_84328_config_devid(int unit,soc_port_t port, phy_ctrl_t *pc, uint32 *devid)
   1785 {
   1786     if (soc_property_port_get(unit, port, "phy_84328", FALSE)) {
   1787         return *devid = PHY84328_ID_84328;
   1788     }
   1789 
   1790 	return _phy_84328_chip_id_get(unit, port, pc, devid);
   1791 }
   1792 
   1793 STATIC int
   1794 _phy_84328_tx_mode_set(int unit, soc_port_t port, phy84328_intf_side_t side, uint16 tx_mode)
   1795 {
   1796     phy_ctrl_t *pc;
   1797 	phy84328_intf_side_t saved_side;
   1798 
   1799     /* Make sure tx_mode has acceptable values */
   1800     if ((tx_mode != 0) && (tx_mode != 1) && (tx_mode != 4)) {
   1801         LOG_ERROR(BSL_LS_SOC_PHY,
   1802                   (BSL_META_U(unit,
   1803                               "PHY84328 invalid tx mode configuration - must be 0, 1, or 4: u%d p%d\n"),
   1804                               unit, port));
   1805         return SOC_E_NONE;
   1806     }
   1807 
   1808     pc = EXT_PHY_SW_STATE(unit, port);
   1809 
   1810     saved_side = _phy_84328_intf_side_regs_get(unit, port);
   1811 	_phy_84328_intf_side_regs_select(unit, port, side);
   1812 
   1813     /* Set manual tx mode updates */
   1814     SOC_IF_ERROR_RETURN(_phy_84328_txmode_manual_set(unit, port, side, TRUE));
   1815         SOC_IF_ERROR_RETURN(
   1816             MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL2,
   1817                                         tx_mode << PHY84328_DEV1_ANATXACONTROL2_TX_MODESELECT_SHIFT,
   1818                                         PHY84328_DEV1_ANATXACONTROL2_TX_MODESELECT_MASK));
   1819 	if (saved_side != side) {
   1820 		_phy_84328_intf_side_regs_select(unit, port, saved_side);
   1821 	}
   1822 
   1823     return SOC_E_NONE;
   1824 }
   1825 
   1826 STATIC int
   1827 _phy_84328_tx_mode_get(int unit, soc_port_t port, phy84328_intf_side_t side, uint16 *tx_mode)
   1828 {
   1829     phy_ctrl_t *pc;
   1830 	uint16 data;
   1831 	phy84328_intf_side_t saved_side;
   1832 
   1833     pc = EXT_PHY_SW_STATE(unit, port);
   1834 
   1835     saved_side = _phy_84328_intf_side_regs_get(unit, port);
   1836 	_phy_84328_intf_side_regs_select(unit, port, side);
   1837 
   1838     SOC_IF_ERROR_RETURN(
   1839         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL2,
   1840 									  &data));
   1841 
   1842 	/* Must exclude bit 13 from tx_mode */
   1843 	*tx_mode = (data >> PHY84328_DEV1_ANATXACONTROL2_TX_MODESELECT_SHIFT) & 0xd;
   1844 
   1845 	if (saved_side != side) {
   1846 		_phy_84328_intf_side_regs_select(unit, port, saved_side);
   1847 	}
   1848 
   1849     return SOC_E_NONE;
   1850 }
   1851 
   1852 STATIC int
   1853 _phy_84328_tx_config(int unit, soc_port_t port)
   1854 {
   1855 	int tx_mode = -1;
   1856 	int tx_idriver = -1;
   1857 
   1858 	/* tx_modeselect: 0, 1, or 4 */
   1859 	tx_mode = soc_property_port_get(unit, port, "phy_line_tx_mode", -1);
   1860 	if (tx_mode != -1) {
   1861 		SOC_IF_ERROR_RETURN(_phy_84328_tx_mode_set(unit, port, PHY84328_INTF_SIDE_LINE,
   1862 												   (uint16) tx_mode));
   1863 	}
   1864 	tx_mode = soc_property_port_get(unit, port, "phy_system_tx_mode", -1);
   1865 	if (tx_mode != -1) {
   1866 		SOC_IF_ERROR_RETURN(_phy_84328_tx_mode_set(unit, port, PHY84328_INTF_SIDE_SYS,
   1867 												   (uint16) tx_mode));
   1868 	}
   1869 
   1870 	/* tx idriver: 0..15 */
   1871 	tx_idriver = soc_property_port_get(unit, port, "phy_line_driver_current", -1);
   1872 	if (tx_idriver != -1) {
   1873 		SOC_IF_ERROR_RETURN(_phy_84328_control_tx_driver_set(unit, port, SOC_PHY_CONTROL_DRIVER_CURRENT,
   1874 															 PHY84328_INTF_SIDE_LINE, tx_idriver));
   1875 	}
   1876 
   1877 	tx_idriver = soc_property_port_get(unit, port, "phy_system_driver_current", -1);
   1878 	if (tx_idriver != -1) {
   1879 		SOC_IF_ERROR_RETURN(_phy_84328_control_tx_driver_set(unit, port, SOC_PHY_CONTROL_DRIVER_CURRENT,
   1880 															 PHY84328_INTF_SIDE_SYS, tx_idriver));
   1881 	}
   1882 
   1883 	return SOC_E_NONE;
   1884 }
   1885 
   1886 STATIC phy84328_datapath_t
   1887 _phy_84328_datapath_get(int unit, soc_port_t port)
   1888 {
   1889 	phy84328_datapath_t dp = PHY84328_DATAPATH_20;
   1890 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1891 
   1892 	switch (DEVREV(pc)) {
   1893 	case 0x00a0:
   1894 		dp = PHY84328_DATAPATH_20;
   1895 		break;
   1896 	case 0x00b0:
   1897 	default:
   1898 		dp = PHY84328_DATAPATH_4_DEPTH1;
   1899 		break;
   1900 	}
   1901 	return dp;
   1902 }
   1903 
   1904 #if 1
   1905 STATIC int
   1906 _phy_84328_intf_sys_default(int unit, soc_port_t port)
   1907 {
   1908 	uint16 if_sys_idx = 0;
   1909 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1910 
   1911     if (PHY84328_MULTI_CORE_MODE(pc)) {
   1912         if_sys_idx = 0;
   1913     } else {
   1914         /* Get configured system interface */
   1915         if_sys_idx = soc_property_port_get(unit, port, spn_PHY_SYS_INTERFACE, 0);
   1916         if (if_sys_idx >= (sizeof(phy_sys_to_port_if) / sizeof(soc_port_if_t))) {
   1917             LOG_ERROR(BSL_LS_SOC_PHY,
   1918                                   (BSL_META_U(unit,
   1919                       "PHY84328 invalid system side interface: u=%d p=%d intf=%d\n"
   1920                       "Using default interface\n"),
   1921                       unit, port, if_sys_idx));
   1922             if_sys_idx = 0;
   1923         }
   1924     }
   1925     return if_sys_idx;
   1926 }
   1927 
   1928 STATIC int
   1929 _phy_84328_intf_line_speed_default(int unit, soc_port_t port)
   1930 {
   1931     int speed;
   1932 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1933 
   1934     if (PHY84328_MULTI_CORE_MODE(pc)) {
   1935         speed = 100000;
   1936     } else if (PHY84328_SINGLE_PORT_MODE(pc)) {
   1937         speed = 40000;
   1938     } else {
   1939         speed = 10000;
   1940     }
   1941     return speed;
   1942 }
   1943 
   1944 STATIC soc_port_if_t
   1945 _phy_84328_intf_type_default(int speed, phy84328_intf_side_t side)
   1946 {
   1947     soc_port_if_t intf;
   1948 
   1949     switch (speed) {
   1950     case 100000:
   1951         /**** SR10 on line side? */
   1952         intf = (side == PHY84328_INTF_SIDE_LINE) ? SOC_PORT_IF_SR4 : SOC_PORT_IF_CAUI;
   1953         break;
   1954     case 40000:
   1955         intf = (side == PHY84328_INTF_SIDE_LINE) ? SOC_PORT_IF_SR4 : SOC_PORT_IF_XLAUI;
   1956         break;
   1957     case 10000:
   1958     default:
   1959         intf = (side == PHY84328_INTF_SIDE_LINE) ? SOC_PORT_IF_SR : SOC_PORT_IF_XFI;
   1960         break;
   1961     }
   1962     return intf;
   1963 }
   1964 
   1965 
   1966 
   1967 STATIC int
   1968 _phy_84328_intf_default(int unit, soc_port_t port)
   1969 {
   1970 	phy84328_intf_cfg_t *line_intf, *sys_intf;
   1971 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   1972 
   1973 	line_intf = &(LINE_INTF(pc));
   1974 	sys_intf  = &(SYS_INTF(pc));
   1975 	sal_memset(line_intf, 0, sizeof(phy84328_intf_cfg_t));
   1976 	sal_memset(sys_intf,  0, sizeof(phy84328_intf_cfg_t));
   1977 
   1978 	/*
   1979 	 * - interfaces are KR4/KR/KX/XAUI/XFI/SR/LR/CR/SR4/LR4/CR4/SR10/CR10
   1980 	 * - Gallardo is capable of being configured symmetrically and can support all 
   1981 	 *   interfaces on both sides
   1982 	 * - system side interfaces cannot be changed dynamically
   1983 	 *   - configured in Gallardo via config variables
   1984 	 * - line side mode can be changed dynamically
   1985 	 *   - configured specifically with interface set and/or by matching speed
   1986 	 *   - automatically when module autodetect is enabled
   1987 	 *
   1988 	 *    port mode            system side                   line side
   1989 	 * ----------------  ------------------------  --------------------------------
   1990      * 100G(multicore)   dflt:CAUI                 dflt:SR10   or user set if/speed
   1991 	 * 40G(singleport)   dflt:XLAUI or configvar   dflt:XLAUI  or user set if/speed
   1992 	 * 1G/10G(quadport)  dflt:XFI or configvar     dflt:SFI    or user set if/speed
   1993 	 */
   1994 
   1995 	/* Get configured system interface */
   1996     sys_intf->type = phy_sys_to_port_if[_phy_84328_intf_sys_default(unit, port)];
   1997 	line_intf->speed = _phy_84328_intf_line_speed_default(unit, port);
   1998 	if (sys_intf->type == 0) {
   1999 		/* use defaults based on current line side */
   2000 		sys_intf->speed = line_intf->speed;
   2001 		line_intf->type = _phy_84328_intf_type_default(line_intf->speed, PHY84328_INTF_SIDE_LINE);
   2002 		sys_intf->type =  _phy_84328_intf_type_default(line_intf->speed, PHY84328_INTF_SIDE_SYS);
   2003 		_phy_84328_intf_print(unit, port, "default sys intf");
   2004 	} else {
   2005 		SOC_IF_ERROR_RETURN(_phy_84328_intf_line_sys_params_get(unit, port));
   2006 		_phy_84328_intf_print(unit, port, "after updating intf based on sys config");
   2007 	}
   2008 	CFG_SYS_INTF(pc) = sys_intf->type;
   2009 
   2010     return SOC_E_NONE;
   2011 }
   2012 
   2013 
   2014 STATIC int
   2015 _phy_84328_polarity_cfg_init(int unit, soc_port_t port)
   2016 {
   2017     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   2018 
   2019     /*
   2020      * The core aware property which specifies the core number must be
   2021      * with multiple core ports
   2022      *
   2023      * Ex:
   2024      *   Assuming port 4 is a 100G port, then if every other lane has tx
   2025      *   polarity flipped:
   2026      *        config add phy_tx_polarity_flip_core0_port4=0x0f0f
   2027      *        config add phy_tx_polarity_flip_core1_port4=0x0f0f
   2028      *        config add phy_tx_polarity_flip_core2_port4=0x000f
   2029      *        
   2030      *   Polarity configuration:
   2031      *    1: all lanes
   2032      *    nibble==0xF: each nibble specifies a lane - up to 4 lanes
   2033      *
   2034      * The polarity configuration is stored in the driver per core control block
   2035  */
   2036     if (PHY84328_MULTI_CORE_MODE(pc)) {
   2037         POL_TX_CFG(pc) = soc_property_port_suffix_num_get(unit, port, CORE_NUM(pc),
   2038                                                           spn_PHY_TX_POLARITY_FLIP,
   2039                                                           "core", 0);
   2040         POL_RX_CFG(pc) = soc_property_port_suffix_num_get(unit, port, CORE_NUM(pc),
   2041                                                           spn_PHY_RX_POLARITY_FLIP,
   2042                                                           "core", 0);
   2043     } else {
   2044         POL_TX_CFG(pc) = soc_property_port_get(unit, port, spn_PHY_TX_POLARITY_FLIP, 0);
   2045         POL_RX_CFG(pc) = soc_property_port_get(unit, port, spn_PHY_RX_POLARITY_FLIP, 0);
   2046     } 
   2047     
   2048     return SOC_E_NONE;
   2049 }	
   2050 
   2051 
   2052 #endif /* 100G */
   2053 
   2054 #ifdef BCM_WARM_BOOT_SUPPORT
   2055 STATIC int
   2056 _phy_84328_intf_speed_from_reg(uint16 mode, int *speed)
   2057 {
   2058     uint16 speed_reg = mode & (PHY84328_DEV1_GP_REGISTER_1_SPEED_1G_MASK |
   2059                                PHY84328_DEV1_GP_REGISTER_1_SPEED_10G_MASK |
   2060                                PHY84328_DEV1_GP_REGISTER_1_SPEED_40G_MASK |
   2061                                PHY84328_DEV1_GP_REGISTER_1_SPEED_100G_MASK);
   2062     *speed = 0;
   2063     switch (speed_reg) {
   2064 
   2065     case PHY84328_DEV1_GP_REGISTER_1_SPEED_100G:
   2066         *speed = 100000;
   2067         break;
   2068 
   2069     case PHY84328_DEV1_GP_REGISTER_1_SPEED_42G:
   2070         *speed = 42000;
   2071         break;
   2072 
   2073     case PHY84328_DEV1_GP_REGISTER_1_SPEED_40G:
   2074         *speed = 40000;
   2075         break;
   2076 
   2077     case PHY84328_DEV1_GP_REGISTER_1_SPEED_10G:
   2078         *speed = 10000;
   2079         break;
   2080 
   2081     case PHY84328_DEV1_GP_REGISTER_1_SPEED_10G | PHY84328_DEV1_GP_REGISTER_1_SPEED_1G:
   2082         /********* 100, 10 not recoverable from PHY ********/
   2083         *speed = 1000;
   2084         break;
   2085     default:
   2086         /* hardware has unexpected value */
   2087         return SOC_E_FAIL;
   2088     }
   2089     return SOC_E_NONE;
   2090 }
   2091 
   2092 STATIC int
   2093 _phy_84328_intf_type_from_reg(uint16 mode, phy84328_intf_side_t side, int speed, int an,
   2094                               soc_port_if_t *intf_type) 
   2095 {
   2096     uint16 intf_reg = mode & ((side == PHY84328_INTF_SIDE_LINE) ? 0x5300 : 0xac00);
   2097 
   2098     if (side == PHY84328_INTF_SIDE_LINE) {
   2099         switch (intf_reg) {
   2100         case 0:
   2101             switch (speed) {
   2102             case 40000:
   2103             case 42000:
   2104             case 100000:
   2105                 *intf_type = SOC_PORT_IF_SR4;
   2106                 break;
   2107             case 10000:
   2108                 *intf_type = SOC_PORT_IF_SR;
   2109                 break;
   2110             case 1000:
   2111                 if (an) {
   2112                     *intf_type = SOC_PORT_IF_GMII;
   2113                 } else {
   2114                     *intf_type = SOC_PORT_IF_SGMII;
   2115                 }
   2116                 break;
   2117             case 100:
   2118             case 10:
   2119                 *intf_type = SOC_PORT_IF_SGMII;
   2120                 break;
   2121             default:
   2122                 return SOC_E_FAIL;
   2123             }
   2124 
   2125             break;
   2126             
   2127         case 0x4200:
   2128             switch (speed) {
   2129             case 100000:
   2130                 *intf_type = SOC_PORT_IF_CAUI;
   2131                 break;
   2132             case 40000:
   2133             case 42000:
   2134                 *intf_type = SOC_PORT_IF_XLAUI;
   2135                 break;
   2136             case 10000:
   2137                 *intf_type = SOC_PORT_IF_SFI;
   2138                 break;
   2139             default:
   2140                 return SOC_E_FAIL;
   2141             }
   2142             break;
   2143 
   2144         case 0x4000:
   2145             switch (speed) {
   2146             case 40000:
   2147             case 42000:
   2148                 *intf_type = SOC_PORT_IF_LR4;
   2149                 break;
   2150             case 10000:
   2151                 *intf_type = SOC_PORT_IF_LR;
   2152                 break;
   2153             default:
   2154                 return SOC_E_FAIL;
   2155             }
   2156             break;
   2157 
   2158         case 0x200:
   2159             switch (speed) {
   2160             case 40000:
   2161             case 42000:
   2162             case 100000:
   2163                 *intf_type = SOC_PORT_IF_CR4;
   2164                 break;
   2165             case 10000:
   2166                 *intf_type = SOC_PORT_IF_CR;
   2167                 break;
   2168             default:
   2169                 return SOC_E_FAIL;
   2170             }
   2171             break;
   2172 
   2173         case 0x100:
   2174             switch (speed) {
   2175             case 40000:
   2176             case 42000:
   2177                 *intf_type = SOC_PORT_IF_KR4;
   2178                 break;
   2179             case 10000:
   2180                 *intf_type = SOC_PORT_IF_KR;
   2181                 break;
   2182             case 1000:
   2183             case 100:
   2184             case 10:
   2185                 *intf_type = SOC_PORT_IF_KX;
   2186                 break;
   2187             default:
   2188                 return SOC_E_FAIL;
   2189             }
   2190             break;
   2191 
   2192         case 0x1200:
   2193             switch (speed) {
   2194             case 40000:
   2195             case 42000:
   2196             case 100000:
   2197                 *intf_type = SOC_PORT_IF_CR4;
   2198                 break;
   2199             case 10000:
   2200                 *intf_type = SOC_PORT_IF_CR;
   2201                 break;
   2202             default:
   2203                 return SOC_E_FAIL;
   2204             }
   2205             break;
   2206 
   2207         case 0x5000:
   2208             switch (speed) {
   2209             case 10000:
   2210                 *intf_type = SOC_PORT_IF_ZR;
   2211                 break;
   2212             default:
   2213                 return SOC_E_FAIL;
   2214             }
   2215             break;
   2216 
   2217         case 0x1000:
   2218         default:
   2219             return SOC_E_FAIL;
   2220             break;
   2221         } /*  switch (intf_reg) */
   2222     } else {
   2223         /* get sys intf type  */
   2224         switch (intf_reg) {
   2225         case 0:
   2226             switch (speed) {
   2227             case 40000:
   2228             case 42000:
   2229                 *intf_type = SOC_PORT_IF_SR4;
   2230                 break;
   2231             case 10000:
   2232                 *intf_type = SOC_PORT_IF_SR;
   2233                 break;
   2234             case 1000:
   2235                 if (an) {
   2236                     *intf_type = SOC_PORT_IF_GMII;
   2237                 } else {
   2238                     *intf_type = SOC_PORT_IF_SGMII;
   2239                 }
   2240                 break;
   2241             case 100:
   2242             case 10:
   2243                 *intf_type = SOC_PORT_IF_SGMII;
   2244                 break;
   2245             default:
   2246                 return SOC_E_FAIL;
   2247             }
   2248 
   2249             break;
   2250             
   2251         case 0x8800:
   2252             switch (speed) {
   2253             case 100000:
   2254                 *intf_type = SOC_PORT_IF_CAUI;
   2255                 break;
   2256             case 40000:
   2257             case 42000:
   2258                 *intf_type = SOC_PORT_IF_XLAUI;
   2259                 break;
   2260             case 10000:
   2261                 *intf_type = SOC_PORT_IF_XFI;
   2262                 break;
   2263             default:
   2264                 return SOC_E_FAIL;
   2265             }
   2266             break;
   2267 
   2268         case 0x800:
   2269             switch (speed) {
   2270             case 40000:
   2271             case 42000:
   2272             case 100000:
   2273                 *intf_type = SOC_PORT_IF_CR4;
   2274                 break;
   2275             case 10000:
   2276                 *intf_type = SOC_PORT_IF_CR;
   2277                 break;
   2278             default:
   2279                 return SOC_E_FAIL;
   2280             }
   2281             break;
   2282 
   2283         case 0x400:
   2284             switch (speed) {
   2285             case 40000:
   2286             case 42000:
   2287                 *intf_type = SOC_PORT_IF_KR4;
   2288                 break;
   2289             case 10000:
   2290                 *intf_type = SOC_PORT_IF_KR;
   2291                 break;
   2292             case 1000:
   2293             case 100:
   2294             case 10:
   2295                 *intf_type = SOC_PORT_IF_KX;
   2296                 break;
   2297             default:
   2298                 return SOC_E_FAIL;
   2299             }
   2300             break;
   2301 
   2302         case 0x2800:
   2303             switch (speed) {
   2304             case 40000:
   2305             case 42000:
   2306             case 100000:
   2307                 *intf_type = SOC_PORT_IF_CR4;
   2308                 break;
   2309             case 10000:
   2310                 *intf_type = SOC_PORT_IF_CR;
   2311                 break;
   2312             default:
   2313                 return SOC_E_FAIL;
   2314             }
   2315             break;
   2316 
   2317         case 0xa000:
   2318         case 0x2000:
   2319         default:
   2320             return SOC_E_FAIL;
   2321             break;
   2322         } /*  switch (intf_reg) */
   2323 
   2324     }
   2325     return SOC_E_NONE;
   2326 }
   2327 
   2328 
   2329 STATIC int
   2330 _phy_84328_reinit_line_intf(int unit, soc_port_t port, int speed, int an, uint16 mode)
   2331 {
   2332     phy_ctrl_t  *pc;
   2333     phy84328_intf_cfg_t *line_intf;
   2334     
   2335     pc = EXT_PHY_SW_STATE(unit, port);
   2336     line_intf = &(LINE_INTF(pc));
   2337 
   2338     line_intf->speed = speed;
   2339     SOC_IF_ERROR_RETURN(_phy_84328_intf_type_from_reg(mode, PHY84328_INTF_SIDE_LINE, speed, an, &(line_intf->type)));
   2340 
   2341     if (AN_EN(pc) && line_intf->type  == SOC_PORT_IF_CR4) {
   2342         if (POL_RX_CFG(pc)) {
   2343             FORCE_20BIT(pc) |= FORCE_20BIT_AN ;
   2344         }
   2345     }
   2346 
   2347     return SOC_E_NONE;
   2348 }
   2349 
   2350 STATIC int
   2351 _phy_84328_reinit_system_intf(int unit, soc_port_t port, int speed, int an, uint16 mode)
   2352 {
   2353     phy_ctrl_t  *pc;
   2354     phy84328_intf_cfg_t *system_intf;
   2355     
   2356     pc = EXT_PHY_SW_STATE(unit, port);
   2357     system_intf = &(SYS_INTF(pc));
   2358 
   2359     system_intf->speed = speed;
   2360     SOC_IF_ERROR_RETURN(_phy_84328_intf_type_from_reg(mode, PHY84328_INTF_SIDE_SYS, speed, an, &(system_intf->type)));
   2361 
   2362     return SOC_E_NONE;
   2363 }
   2364 
   2365 /*
   2366  * For WarmBoot support: preserve SW RxLOS enable/disable status in register 1.0xC01A
   2367  */
   2368 #define PHY84328_NO_PRESERVE_SW_RxLOS           0x100
   2369 #define PHY84328_DEV1_LANECTRL_RSV_SHIFT        12
   2370 STATIC int
   2371 _phy_84328_preserve_sw_rx_los(int unit, soc_port_t port, int enable)
   2372 {
   2373     uint32                offset;
   2374     uint16                sw_rx_los_enable;
   2375     phy_ctrl_t           *pc = EXT_PHY_SW_STATE(unit, port);
   2376 
   2377     /* get the offset of this port/lane */
   2378 	SOC_IF_ERROR_RETURN(
   2379 	    phy_84328_control_port_get(unit, port, SOC_PHY_CONTROL_PORT_OFFSET, &offset) );
   2380 	offset = 1U << (offset + PHY84328_DEV1_LANECTRL_RSV_SHIFT);
   2381     sw_rx_los_enable = (enable) ? offset : 0 ;
   2382 
   2383     /* register 1.0xC01A , use the reserved bits [15:12]                    *\
   2384     \*                     to preserve SW RxLOS status for warmboot support */
   2385     return  MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   2386                     PHY84328_DEV1_LANECTRL, sw_rx_los_enable, (uint16) offset);
   2387 }
   2388 
   2389 STATIC int  _phy_84328_sw_rx_los_control_set(int unit, soc_port_t port, uint32 value);
   2390 /*
   2391  * During WarmBoot: retrieve SW RxLOS enable/disable status from register 1.0xC01A
   2392  */
   2393 STATIC int
   2394 _phy_84328_reinit_sw_rx_los(int unit, soc_port_t port)
   2395 {
   2396     uint32                offset;
   2397     uint16                sw_rx_los_enable;
   2398     phy84328_sw_rx_los_t *sw_rx_los;
   2399     phy_ctrl_t           *pc = EXT_PHY_SW_STATE(unit, port);
   2400     sw_rx_los = &(SW_RX_LOS(pc));
   2401 
   2402     /* get the offset of this port/lane */
   2403 	SOC_IF_ERROR_RETURN(
   2404 	    phy_84328_control_port_get(unit, port, SOC_PHY_CONTROL_PORT_OFFSET, &offset) );
   2405 	offset = 1U << (offset + PHY84328_DEV1_LANECTRL_RSV_SHIFT);
   2406 
   2407     /* register 1.0xC01A , use the reserved bits [15:12]               *\
   2408     \*                     to preserve SW RxLOS status during warmboot */
   2409     SOC_IF_ERROR_RETURN(
   2410         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   2411                                PHY84328_DEV1_LANECTRL, &sw_rx_los_enable) );
   2412     sw_rx_los->cfg_enable = (sw_rx_los_enable & offset) ? TRUE : FALSE;
   2413 
   2414     /* if SW RxLOS was enabled, hardcode the default RxLOS stable state */
   2415     if ( sw_rx_los->cfg_enable ) {
   2416         sw_rx_los->cur_enable       = 1;
   2417         sw_rx_los->sys_link         = 1;
   2418         sw_rx_los->link_no_pcs      = 0;
   2419         sw_rx_los->link_status      = 0;
   2420         sw_rx_los->fault_report_dis = 0;
   2421         sw_rx_los->link_no_pcs      = 0;
   2422         sw_rx_los->restarts         = 1;
   2423         sw_rx_los->state            = PHY84328_SW_RX_LOS_IDLE;
   2424     }
   2425 
   2426     return SOC_E_NONE;
   2427 }
   2428 
   2429 STATIC int
   2430 _phy_84328_reinit_fw_rx_los(int unit, soc_port_t port)
   2431 {
   2432     uint16 fw_rx_los, fw_rx_los_en_mask;
   2433     phy_ctrl_t  *pc;
   2434 
   2435     pc = EXT_PHY_SW_STATE(unit, port);
   2436     fw_rx_los_en_mask = (1 << 15) | (1 << 14);
   2437 
   2438     SOC_IF_ERROR_RETURN(
   2439         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 0xc480, &fw_rx_los));
   2440 
   2441     FW_RX_LOS(pc) = (fw_rx_los & fw_rx_los_en_mask) == fw_rx_los_en_mask;
   2442 
   2443     return SOC_E_NONE;
   2444 }
   2445 
   2446 STATIC int
   2447 _phy_84328_reinit_cur_datapath(int unit, soc_port_t port, uint16 mode)
   2448 {
   2449     uint16 datapath_reg;
   2450     phy_ctrl_t  *pc;
   2451 
   2452     pc = EXT_PHY_SW_STATE(unit, port);
   2453     
   2454     datapath_reg = mode & PHY84328_DEV1_GP_REGISTER_1_DATAPATH_MASK;
   2455     switch (datapath_reg) {
   2456     case 0:
   2457         CUR_DATAPATH(pc) = PHY84328_DATAPATH_20;
   2458         break;
   2459     case PHY84328_DEV1_GP_REGISTER_1_DATAPATH_4_DEPTH1:
   2460         CUR_DATAPATH(pc) = PHY84328_DATAPATH_4_DEPTH1;
   2461         break;
   2462     case PHY84328_DEV1_GP_REGISTER_1_DATAPATH_4_DEPTH2:
   2463         CUR_DATAPATH(pc) = PHY84328_DATAPATH_4_DEPTH2;
   2464         break;
   2465     default:
   2466         return SOC_E_FAIL;
   2467     }
   2468     return SOC_E_NONE;
   2469 }
   2470 
   2471 
   2472 STATIC int
   2473 _phy_84328_reinit_from_mode(int unit, soc_port_t port)
   2474 {
   2475     uint16 mode_reg;
   2476     uint16 side_reg;
   2477     uint16 an_reg;
   2478     int speed;
   2479     int an =0, an_done = 0;
   2480     int int_phy_link = 0;
   2481     phy_ctrl_t  *pc, *int_pc;
   2482 
   2483     pc = EXT_PHY_SW_STATE(unit, port);
   2484     int_pc = INT_PHY_SW_STATE(unit, port);
   2485 
   2486     /* 
   2487      * Make sure line side registers are selected
   2488      * if not, have to bail out since the system is in a bad state
   2489      */
   2490     SOC_IF_ERROR_RETURN(
   2491         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_XPMD_REGS_SEL, &side_reg));
   2492     if (side_reg != 0) {
   2493         return SOC_E_UNAVAIL;
   2494     }
   2495 
   2496     /* Read the current mode */
   2497     SOC_IF_ERROR_RETURN(
   2498         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_1, &mode_reg));
   2499 
   2500     /* Get speed */
   2501     SOC_IF_ERROR_RETURN(_phy_84328_intf_speed_from_reg(mode_reg, &speed));
   2502 
   2503     /* Get an setting */
   2504     if (speed < 10000) {
   2505       if (int_pc != NULL) {
   2506         SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &an, &an_done));
   2507         SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &speed));
   2508       }
   2509     } else {
   2510         SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_AN_REG(unit, pc,
   2511                                                      PHY84328_DEV7_AN_CONTROL_REGISTER, &an_reg));
   2512         an = (an_reg & PHY84328_DEV7_AN_CONTROL_REGISTER_AUTO_NEGOTIATIONENABLE_MASK) ==
   2513             PHY84328_DEV7_AN_CONTROL_REGISTER_AUTO_NEGOTIATIONENABLE_MASK;
   2514     }
   2515     
   2516     AN_EN(pc) = an;
   2517 
   2518     SOC_IF_ERROR_RETURN(
   2519         _phy_84328_reinit_line_intf(unit, port, speed, an, mode_reg));
   2520 
   2521     SOC_IF_ERROR_RETURN(
   2522         _phy_84328_reinit_system_intf(unit, port, speed, an, mode_reg));
   2523     
   2524     SOC_IF_ERROR_RETURN(
   2525         _phy_84328_reinit_cur_datapath(unit, port, mode_reg));
   2526 
   2527     /* 
   2528      * PCS from the internal PHY is used to determine link.
   2529      */
   2530     if (int_pc != NULL) {
   2531         SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &int_phy_link));
   2532         CUR_LINK(pc) = int_phy_link;
   2533     } else {
   2534         CUR_LINK(pc) = 0;
   2535     }
   2536 
   2537     return SOC_E_NONE;
   2538 }
   2539 
   2540 STATIC int
   2541 _phy_84328_reinit(int unit, soc_port_t port)
   2542 {
   2543 	SOC_IF_ERROR_RETURN(
   2544             _phy_84328_reinit_from_mode(unit,port));
   2545 
   2546     /* Reinit Firmware RxLOS */
   2547     SOC_IF_ERROR_RETURN(
   2548         _phy_84328_reinit_fw_rx_los(unit, port));
   2549     /* Reinit Software RxLOS */
   2550     SOC_IF_ERROR_RETURN(
   2551         _phy_84328_reinit_sw_rx_los(unit, port) );
   2552 
   2553     return SOC_E_NONE;
   2554 }
   2555 #endif /*  BCM_WARM_BOOT_SUPPORT */
   2556 
   2557 STATIC int
   2558 _phy_84328_init_pass2(int unit, soc_port_t port)
   2559 {
   2560 	phy_ctrl_t  *pc;
   2561 	phy84328_intf_cfg_t *line_intf, *sys_intf;
   2562 	phy84328_counters_t *counters;
   2563 	phy84328_sw_rx_los_t *sw_rx_los;
   2564 	phy84328_link_mon_t *link_mon;
   2565 	phy84328_micro_ctrl_t *micro_ctrl;
   2566 	uint16	data, mask;
   2567 	uint16  chip_rev;
   2568 	int tx_gpio0 = 0;
   2569 	int link_mon_dflt, port_enable_delay_dflt;
   2570 
   2571 	LOG_INFO(BSL_LS_SOC_PHY,
   2572                  (BSL_META_U(unit,
   2573                              "PHY84328 init pass2: u=%d p=%d\n"), unit, port));
   2574 	pc = EXT_PHY_SW_STATE(unit, port);
   2575 
   2576 	/*
   2577 	 * - interfaces are KR4/KR/KX/XAUI/XFI/SR/LR/CR/SR4/LR4/CR4
   2578 	 * - Gallardo is capable of being configured symmetrically and can support all 
   2579 	 *   interfaces on both sides
   2580 	 * - system side interfaces cannot be changed dynamically
   2581 	 *   - configured in Gallardo via config variables
   2582 	 * - line side mode can be changed dynamically
   2583 	 *   - configured specifically with interface set and/or by matching speed
   2584 	 *   - automatically when module autodetect is enabled
   2585 	 *
   2586 	 *    port mode            system side                   line side
   2587 	 * ----------------  ------------------------  --------------------------------
   2588 	 * 40G(singleport)   dflt:XLAUI or configvar   dflt:XLAUI  or user set if/speed
   2589 	 * 1G/10G(quadport)  dflt:XFI or configvar     dflt:SFI    or user set if/speed
   2590 	 */
   2591 	
   2592 	line_intf = &(LINE_INTF(pc));
   2593 	sys_intf  = &(SYS_INTF(pc));
   2594 	counters  = &(COUNTERS(pc));
   2595 	sw_rx_los = &(SW_RX_LOS(pc));
   2596 	link_mon  = &(LINK_MON(pc));
   2597 	micro_ctrl = &(MICRO_CTRL(pc));
   2598 
   2599 	sal_memset(line_intf, 0, sizeof(phy84328_intf_cfg_t));
   2600 	sal_memset(sys_intf,  0, sizeof(phy84328_intf_cfg_t));
   2601 	sal_memset(counters,  0, sizeof(phy84328_counters_t));
   2602 	sal_memset(sw_rx_los, 0, sizeof(phy84328_sw_rx_los_t));
   2603 	sal_memset(link_mon,  0, sizeof(phy84328_link_mon_t));
   2604 	LOGICAL_LANE0(pc) = 0;
   2605 	AN_EN(pc) = 0;
   2606 	FORCE_20BIT(pc) = 0;
   2607 	CUR_LINK(pc) = 0;
   2608 	SYNC_INIT(pc) = 1;
   2609 	INT_PHY_RE_EN(pc) = 0;
   2610 	DBG_FLAGS(pc) = 0; 
   2611     FW_RX_LOS(pc) = 0;
   2612 	BYPASS_SS_TUNING(pc) = soc_property_port_get(unit, port, "phy_84328_bypass_ss_tuning", 1);
   2613 	SYS_FORCED_CL72(pc) = soc_property_port_get(unit, port, spn_PORT_INIT_CL72, 0);
   2614 	micro_ctrl->enable = 1;
   2615 	micro_ctrl->count = 0;
   2616 
   2617 	SOC_IF_ERROR_RETURN(
   2618 		READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   2619 									  PHY84328_DEV1_CHIP_REV_REGISTER,
   2620 									  &chip_rev));
   2621 	DEVREV(pc) = chip_rev;
   2622 	port_enable_delay_dflt = (DEVREV(pc) == 0x00a0) ? 60 : 0;
   2623 	PORT_ENABLE_DELAY(pc) = soc_property_port_get(unit, port, 
   2624 												  "phy_84328_port_enable_delay",
   2625 												  port_enable_delay_dflt) * 1000;
   2626 	link_mon_dflt = (DEVREV(pc) == 0x00a0) ? 1 : 0;
   2627 	link_mon->cfg_enable = soc_property_port_get(unit, port, 
   2628 												 "phy_84328_link_monitor", 
   2629 												 link_mon_dflt);
   2630 	link_mon->cur_enable =  link_mon->cfg_enable;
   2631 
   2632 	pc->flags |= PHYCTRL_INIT_DONE;
   2633 
   2634 
   2635     SOC_IF_ERROR_RETURN(_phy_84328_intf_default(unit, port));
   2636 	
   2637 	/* Manually power channel down by default from driver - 
   2638 	 * it is upto the user to enable the port through CLI or API or
   2639 	 * by using correct compilation flags to ensure that port is enabled
   2640 	 * as part of initialization by upper layers.
   2641 	 */
   2642      data = (1 << PHY84328_DEV1_OPTICAL_CONFIGURATION_MAN_TXON_EN_SHIFT) |
   2643              (1 << PHY84328_DEV1_OPTICAL_CONFIGURATION_TXOFFT_SHIFT);
   2644      mask = PHY84328_DEV1_OPTICAL_CONFIGURATION_MAN_TXON_EN_MASK |
   2645             PHY84328_DEV1_OPTICAL_CONFIGURATION_TXOFFT_MASK;
   2646 
   2647      SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_OPTICAL_CONFIGURATION,
   2648  	                                    data, mask));
   2649 	/*
   2650 	 * Initialize main firmware control register
   2651 	 * - First quiesce firmware and clear default settings
   2652 	 * - Enable all channels as there are race conditions if not all channels are 
   2653 	 *   enabled when changing to quad-channel mode
   2654 	 * - If tx_gpio0 is set, firmware drives line side tx enable/disable based on
   2655 	 *   the system side cdr state
   2656 	 */
   2657 	data = PHY84328_DEV1_GP_REG_0_ENABLE_LINE_3_0_MASK | 
   2658 		PHY84328_DEV1_GP_REG_0_ENABLE_SYSTEM_3_0_MASK;
   2659 	mask = PHY84328_DEV1_GP_REG_0_ENABLE_LINE_3_0_MASK | 
   2660 		PHY84328_DEV1_GP_REG_0_ENABLE_SYSTEM_3_0_MASK;
   2661 	tx_gpio0 = soc_property_port_get(unit, port, "phy_84328_tx_gpio0", 0);
   2662 	if (tx_gpio0 == 1) {
   2663 		data |= PHY84328_DEV1_GP_REG_0_TX_GPIO;
   2664 		mask |= data;
   2665 	}
   2666     /* Update the core info in bit 6 and 5 */
   2667     mask |= 0x3 << 5;
   2668     if (CORE_NUM(pc)){
   2669         data |= ((CORE_NUM(pc) % 3) + 1) << 5 ;
   2670     }
   2671 	SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0,
   2672 														data, mask));
   2673 	
   2674 	/* Reset does not clear lane control2 */
   2675 	SOC_IF_ERROR_RETURN
   2676 		(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_LANECTRL2, 0,
   2677 										 PHY84328_DEV1_LANECTRL2_RLOOP1G_MASK));
   2678 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   2679 	SOC_IF_ERROR_RETURN
   2680 		(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_LANECTRL2, 0,
   2681 										 PHY84328_DEV1_LANECTRL2_RLOOP1G_MASK));
   2682 	
   2683 	/* Make sure accessing line side registers and 1:1 logical channel mappings */
   2684 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   2685 	SOC_IF_ERROR_RETURN(
   2686 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_LOGAD_CTRL, 0xe4, 0x00ff));
   2687 	
   2688 	CFG_DATAPATH(pc) = _phy_84328_datapath_get(unit, port);
   2689 	CUR_DATAPATH(pc) = CFG_DATAPATH(pc);
   2690 
   2691 	/* Polarity configuration is applied every time interface is configured */
   2692     SOC_IF_ERROR_RETURN(_phy_84328_polarity_cfg_init(unit, port));
   2693 
   2694 
   2695     /* Push configuration to the device */
   2696     SOC_IF_ERROR_RETURN(_phy_84328_config_update(unit, port));
   2697 
   2698 #ifdef BCM_WARM_BOOT_SUPPORT
   2699     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){
   2700         /* Do nothing */
   2701     } else 
   2702 #endif
   2703     {
   2704         /* Initialize system and line side interfaces */
   2705         SOC_IF_ERROR_RETURN(_phy_84328_intf_line_sys_init(unit, port));
   2706     }
   2707 
   2708     if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) {
   2709         /* indicate third  pass of init is needed */
   2710         PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS3);
   2711     }
   2712 
   2713     return SOC_E_NONE;
   2714 }
   2715 
   2716 STATIC int
   2717 _phy_84328_init_pass3(int unit, soc_port_t port)
   2718 {
   2719     int rv;
   2720     phy_ctrl_t  *pc, *int_pc;
   2721     int	regulator_en = 0;
   2722 
   2723     LOG_INFO(BSL_LS_SOC_PHY,
   2724              (BSL_META_U(unit,
   2725                          "PHY84328 init pass3: u=%d p=%d\n"), unit, port));
   2726     pc = EXT_PHY_SW_STATE(unit, port);
   2727     int_pc = INT_PHY_SW_STATE(unit, port);
   2728 
   2729     /* Complete  what we started from PASS2 in PASS3 */
   2730     if (INT_PHY_RE_EN(pc)) {
   2731         /* wait for timer to expire */
   2732         while (!soc_timeout_check(&SYNC_TO(pc))) {
   2733             sal_usleep(100);
   2734         }
   2735 
   2736         /* Turn internal PHY back on now that the mode has been configured */
   2737         SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, 1));
   2738         INT_PHY_RE_EN(pc) = 0;
   2739     }
   2740 
   2741 
   2742     LOG_INFO(BSL_LS_SOC_PHY,
   2743              (BSL_META_U(unit,
   2744                          "PHY84328 init pass3 polarity verified: u=%d p=%d\n"), unit, port));
   2745 
   2746 	regulator_en = soc_property_port_get(unit, port, spn_PHY_AUX_VOLTAGE_ENABLE, 0);
   2747 	if (regulator_en) {
   2748 		/* Clear 1.c850[13] to enable */
   2749 		SOC_IF_ERROR_RETURN
   2750 			(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_REGUALTOR_CTRL, 0,
   2751 											 PHY84328_DEV1_REGUALTOR_CTRL_PWRDN_MASK));
   2752 	}
   2753 	
   2754 	/* Logical lane0 used for auto-negotiation in 40G CR4 */
   2755 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   2756 		uint16 logical_lane0;
   2757 		
   2758 		logical_lane0 = soc_property_port_get(unit, port, spn_PHY_LANE0_L2P_MAP, 0);
   2759 		if (logical_lane0 > PHY84328_NUM_LANES) {
   2760 			LOG_ERROR(BSL_LS_SOC_PHY,
   2761                                   (BSL_META_U(unit,
   2762                                               "PHY84328 bad auto-negotiation lane %d: u=%d p=%d"
   2763                                               " lane must be 0..3\n"), (int)logical_lane0, unit, port));
   2764 		} else {
   2765 			SOC_IF_ERROR_RETURN(
   2766 				MODIFY_PHY84328_MMF_PMA_PMD_REG(
   2767 					unit, pc, PHY84328_DEV1_SINGLE_PMD_CTRL, 
   2768 					logical_lane0 << PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_SHIFT,
   2769 					PHY84328_DEV1_SINGLE_PMD_CTRL_PHY_CH_TO_ACCESS_IN_SINGLE_PMD_MASK));
   2770 			LOGICAL_LANE0(pc) = logical_lane0;
   2771 		}
   2772 	}
   2773 	
   2774 	/* If configured, enable module auto detection */
   2775 	MOD_AUTO_DETECT(pc) = soc_property_port_get(unit, port, spn_PHY_MOD_AUTO_DETECT, 0);
   2776 	if (MOD_AUTO_DETECT(pc)) {
   2777 		uint16 data, mask;
   2778 		
   2779 		LOG_ERROR(BSL_LS_SOC_PHY,
   2780                           (BSL_META_U(unit,
   2781                                       "PHY84328 module auto detect enabled: u=%d p=%d\n"),
   2782                                       unit, port));
   2783 
   2784         /* SFP MOD_DETECT enables both SFP and QSFP module detect */
   2785 		data = PHY84328_DEV1_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK;
   2786 		mask = PHY84328_DEV1_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK;
   2787 		
   2788 		rv = MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0, data, mask);
   2789 		if (SOC_FAILURE(rv)) {
   2790 			MOD_AUTO_DETECT(pc) = 0;
   2791 			LOG_ERROR(BSL_LS_SOC_PHY,
   2792                                   (BSL_META_U(unit,
   2793                                               "PHY84328 setting module auto detect failed: u=%d p%d\n"),
   2794                                               unit, port));
   2795 		} 
   2796 	}
   2797 
   2798     if (soc_property_port_get(unit, port, "phy_84328_port_4_5_control", 0)) {
   2799         rv = MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0, 
   2800                                              PHY84328_DEV1_GP_REG_0_P4_5_CTRL,
   2801                                              PHY84328_DEV1_GP_REG_0_P4_5_CTRL);
   2802 		if (SOC_FAILURE(rv)) {
   2803 			LOG_ERROR(BSL_LS_SOC_PHY,
   2804                                   (BSL_META_U(unit,
   2805                                               "PHY84328 setting p4_5 control failed: u=%d p%d\n"),
   2806                                               unit, port));
   2807 		} 
   2808     }
   2809 
   2810 	
   2811 #ifdef BCM_WARM_BOOT_SUPPORT
   2812     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){
   2813         return _phy_84328_reinit(unit, port);
   2814     }
   2815 #endif
   2816 
   2817     /* Cold boot code only below this  */
   2818 	
   2819 	return SOC_E_NONE;
   2820 }
   2821 
   2822 /*
   2823  * Check if the core has been initialized. This is done by
   2824  * looking at all ports which belong to the same core and see
   2825  * if any one of them have completed initialization.
   2826  * The primary port is used to determine whether the port is
   2827  * on the same core as all ports in a core share the primary port.
   2828  */
   2829 STATIC int
   2830 _phy_84328_core_init_done(int unit, struct phy_driver_s *pd, int primary_port)
   2831 {
   2832 	int rv;
   2833 	soc_port_t port;
   2834 	phy_ctrl_t *pc;
   2835 	uint32 core_primary_port;
   2836 
   2837 	PBMP_ALL_ITER(unit, port) {
   2838 		pc = EXT_PHY_SW_STATE(unit, port);
   2839 		if (pc == NULL) {
   2840 			continue;
   2841 		}
   2842 		/* Make sure this port has a 84328 driver */
   2843 		if (pc->pd != pd) {
   2844 			continue;
   2845 		}
   2846 		rv = phy_84328_control_port_get(unit, port, SOC_PHY_CONTROL_PORT_PRIMARY,
   2847 								   &core_primary_port);
   2848 		if (rv != SOC_E_NONE) {
   2849 			continue;
   2850 		}
   2851 		if ((primary_port == core_primary_port) && (pc->flags & PHYCTRL_INIT_DONE)) {
   2852 			return TRUE;
   2853 		}
   2854 	}
   2855 	return FALSE;
   2856 }
   2857 
   2858 STATIC int
   2859 _phy_84328_init_pass1(int unit, soc_port_t port)
   2860 {
   2861     phy_ctrl_t			*pc;
   2862     int					offset;
   2863     soc_port_t			primary_port;
   2864 		
   2865 	pc = EXT_PHY_SW_STATE(unit, port);
   2866 
   2867 	
   2868 	LOG_INFO(BSL_LS_SOC_PHY,
   2869                  (BSL_META_U(unit,
   2870                              "PHY84328 init pass1: u=%d p=%d\n"), unit, port));
   2871 	
   2872 	/* Set the primary port & offset */
   2873 	if (soc_phy_primary_and_offset_get(unit, port, &primary_port, &offset) != SOC_E_NONE) {
   2874 		/* 
   2875 		 * Derive primary and offset 
   2876 		 * There is an assumption lane 0 on first core on the the MDIO
   2877 		 * bus is a primary port
   2878 		 */
   2879 		if (PHY84328_SINGLE_PORT_MODE(pc)) {
   2880 			primary_port = port;
   2881 			offset = 0;
   2882 		} else {
   2883 			primary_port = port - (pc->phy_id & 0x3);
   2884 			offset = pc->phy_id & 0x3;
   2885 		}
   2886 	}
   2887 	/* set the default values that are valid for many boards */
   2888 	SOC_IF_ERROR_RETURN(phy_84328_control_port_set(unit, port, SOC_PHY_CONTROL_PORT_PRIMARY,
   2889 											  primary_port));
   2890 	
   2891 	SOC_IF_ERROR_RETURN(phy_84328_control_port_set(unit, port,SOC_PHY_CONTROL_PORT_OFFSET,
   2892 											  offset));
   2893 	
   2894 	/*
   2895 	 * Since there is a single micro and therefore a single copy of the firmware
   2896 	 * shared among the 4 channels in a core, do not download firmware if in quad
   2897 	 * channel and the other channels are active.
   2898 	 */
   2899 	if (PHY84328_SINGLE_PORT_MODE(pc) || 
   2900 		(!PHY84328_SINGLE_PORT_MODE(pc) && 
   2901 		 (!_phy_84328_core_init_done(unit, pc->pd, primary_port)))) {
   2902             uint16 csr_c848 = 0;
   2903 
   2904             /* read Ch. 0 1.C848, bit [13] is download done */
   2905             SOC_IF_ERROR_RETURN(
   2906                 READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   2907                                               PHY84328_DEV1_SPA_CONTROL_STATUS_REGISTER,
   2908                                               &csr_c848));
   2909             if ((csr_c848 & (1 << 13)) &&
   2910                !(soc_property_port_get(unit, port,
   2911                            spn_PHY_FORCE_FIRMWARE_LOAD, TRUE))) {
   2912                	uint8 *fw_ptr = NULL;
   2913                 int fw_length = 0;
   2914                 uint16 chip_micro_ver = 0, file_micro_ver = 0;
   2915 
   2916                 SOC_IF_ERROR_RETURN(
   2917                      READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   2918                                          PHY84328_SYS_DEV1_VERSION,
   2919                                          &chip_micro_ver));
   2920 	            if (pc->dev_name == dev_name_84328_a0) {
   2921                     fw_ptr = phy84328_ucode_bin;
   2922                     fw_length = phy84328_ucode_bin_len;
   2923                 } else if (pc->dev_name == dev_name_84328) {
   2924                     fw_ptr = phy84328B0_ucode_bin;
   2925                     fw_length = phy84328B0_ucode_bin_len;
   2926                 } else if (pc->dev_name == dev_name_84088) {
   2927                     fw_ptr = phy84328B0_ucode_bin;
   2928                     fw_length = phy84328B0_ucode_bin_len;
   2929                 } else {
   2930                     /* for other device donot take micro version*/
   2931                     pc->flags &= (~PHYCTRL_MDIO_BCST);
   2932                     if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) {
   2933                         /* indicate second pass of init is needed */
   2934                         PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2);
   2935                     }
   2936                     return SOC_E_NONE;
   2937                 }
   2938                 /* MICRO version is reterived from 4th and 3rd last byte of micro file*/
   2939                 file_micro_ver = (fw_ptr[fw_length-4] << 8) | (fw_ptr[fw_length-3]);
   2940                 if (file_micro_ver != chip_micro_ver) {
   2941                     pc->flags |= PHYCTRL_MDIO_BCST;
   2942                 } else {
   2943                     pc->flags &= (~PHYCTRL_MDIO_BCST);
   2944                 }
   2945                 
   2946                 /*
   2947                 LOG_CLI((BSL_META_U(unit,
   2948                                     "84328 u=%d p=%d skip fw download\n"), unit, port));
   2949                 */
   2950             } else {
   2951                 pc->flags |= PHYCTRL_MDIO_BCST;
   2952             }
   2953 	}
   2954 	
   2955 	LOG_INFO(BSL_LS_SOC_PHY,
   2956                  (BSL_META_U(unit,
   2957                              "phy_84328_init: u=%d p=%d setting primary=%d offset=%d\n"),
   2958                              unit, port, primary_port, offset));
   2959 	
   2960     if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) {
   2961         /* indicate second pass of init is needed */
   2962         PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2);
   2963     }
   2964 
   2965 	return SOC_E_NONE;
   2966 }
   2967 
   2968 /* Function:
   2969  *    phy_84328_init
   2970  * Purpose:    
   2971  *    Initialize 84328 phys
   2972  * Parameters:
   2973  *    unit - StrataSwitch unit #.
   2974  *    port - StrataSwitch port #. 
   2975  * Returns:    
   2976  *    SOC_E_NONE
   2977  */
   2978 
   2979 STATIC int
   2980 _phy_84328_init(int unit, soc_port_t port)
   2981 {
   2982 	int					ix;
   2983 	uint16				data;
   2984 	uint32				devid;
   2985     phy_ctrl_t			*pc;
   2986 
   2987     pc = EXT_PHY_SW_STATE(unit, port);
   2988 
   2989     LOG_INFO(BSL_LS_SOC_PHY,
   2990              (BSL_META_U(unit,
   2991                          "PHY84328 init: u=%d p=%d state=%d\n"), 
   2992                          unit, port,PHYCTRL_INIT_STATE(pc)));
   2993 
   2994 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   2995 
   2996     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) ||
   2997         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   2998 
   2999 		/* Read the chip id to identify the device */
   3000 		SOC_IF_ERROR_RETURN(_phy_84328_config_devid(unit, port, pc, &devid));
   3001 
   3002 		/* Save it in the device description structure for future use */  
   3003 		DEVID(pc) = devid;
   3004 
   3005 		/* initialize default p2l map */
   3006 		for (ix = 0; ix < PHY84328_NUM_LANES; ix++) {
   3007 			P2L_MAP(pc,ix) = ix;
   3008 		}
   3009 
   3010         PHY_FLAGS_SET(unit, port,  PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER);
   3011 		data = (PHY84328_SINGLE_PORT_MODE(pc)) ? 
   3012 			PHY84328_DEV1_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK : 0;
   3013 		SOC_IF_ERROR_RETURN
   3014 			(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   3015 											 PHY84328_DEV1_SINGLE_PMD_CTRL, data,
   3016 											 PHY84328_DEV1_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK));
   3017 
   3018         SOC_IF_ERROR_RETURN(_phy_84328_init_pass1(unit, port));
   3019 
   3020         if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) {
   3021             return SOC_E_NONE;
   3022         }
   3023 
   3024 	}
   3025 
   3026     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) ||
   3027         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   3028 
   3029         SOC_IF_ERROR_RETURN( _phy_84328_init_pass2(unit, port));
   3030 
   3031         LOG_INFO(BSL_LS_SOC_PHY,
   3032                  (BSL_META_U(unit,
   3033                              "PHY84328 init pass2 completed: u=%d p=%d\n"), unit, port));
   3034 
   3035         if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) {
   3036             return SOC_E_NONE;
   3037         }
   3038     }
   3039 
   3040     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS3) ||
   3041         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   3042 
   3043         SOC_IF_ERROR_RETURN( _phy_84328_init_pass3(unit, port));
   3044 
   3045         LOG_INFO(BSL_LS_SOC_PHY,
   3046                  (BSL_META_U(unit,
   3047                              "PHY84328 init pass3 completed: u=%d p=%d\n"), unit, port));
   3048         PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_DEFAULT);
   3049         return SOC_E_NONE;
   3050     }
   3051 
   3052     return SOC_E_NONE;
   3053 }
   3054 
   3055 STATIC int
   3056 _phy_84328_dev_an_get(int unit, soc_port_t port, int *an, int *an_done)
   3057 {
   3058 	uint16 data;
   3059 	uint16 dev_an_done_mask; 
   3060 	phy_ctrl_t  *pc;
   3061 
   3062 	pc = EXT_PHY_SW_STATE(unit, port);
   3063 	*an = 0;
   3064 	*an_done = 0;
   3065 
   3066 	/*
   3067 	 * 7.0000[12] an enabled
   3068 	 * 1.0097[0]  an/training complete. For 40G, per lane status in bits 12,8,4,0
   3069 	 */
   3070 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_AN_REG(unit, pc, 
   3071 												 PHY84328_DEV7_AN_CONTROL_REGISTER, &data));
   3072 	*an = (data & PHY84328_DEV7_AN_CONTROL_REGISTER_AUTO_NEGOTIATIONENABLE_MASK) ==
   3073 		PHY84328_DEV7_AN_CONTROL_REGISTER_AUTO_NEGOTIATIONENABLE_MASK;
   3074 
   3075 	if (*an) {
   3076 		SOC_IF_ERROR_RETURN(
   3077 			READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_BASE_R_PMD_STATUS_REGISTER,
   3078 										  &data));
   3079 		dev_an_done_mask = PHY84328_SINGLE_PORT_MODE(pc) ? 0x1111 : 0x0001;
   3080 		*an_done = (data & dev_an_done_mask) == dev_an_done_mask;
   3081 	}
   3082 
   3083 	return SOC_E_NONE;
   3084 }
   3085 
   3086 /*
   3087  * Function:
   3088  *      phy_84328_an_get
   3089  * Purpose:
   3090  *      Get the current auto-negotiation status (enabled/busy)
   3091  * Parameters:
   3092  *      unit - StrataSwitch unit #.
   3093  *      port - StrataSwitch port #.
   3094  *      an   - (OUT) if true, auto-negotiation is enabled.
   3095  *      an_done - (OUT) if true, auto-negotiation is complete. This
   3096  *              value is undefined if an == false.
   3097  * Returns:
   3098  *      SOC_E_XXX
   3099  */
   3100 
   3101 STATIC int
   3102 phy_84328_an_get(int unit, soc_port_t port, int *an, int *an_done)
   3103 {
   3104 	phy_ctrl_t  *pc, *int_pc;
   3105 	phy84328_intf_cfg_t  *line_intf;
   3106 
   3107 	pc = EXT_PHY_SW_STATE(unit, port);
   3108     int_pc = INT_PHY_SW_STATE(unit, port);
   3109 	line_intf = &(LINE_INTF(pc));
   3110 
   3111 	if ((line_intf->type == SOC_PORT_IF_GMII) || (line_intf->type == SOC_PORT_IF_SGMII)) {
   3112 		SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, an, an_done));
   3113 	} else {
   3114 		switch (line_intf->type) {
   3115 		case SOC_PORT_IF_KX:
   3116 		case SOC_PORT_IF_KR:
   3117 		case SOC_PORT_IF_KR4:
   3118 		case SOC_PORT_IF_CR4:
   3119 			SOC_IF_ERROR_RETURN(_phy_84328_dev_an_get(unit, port, an, an_done));
   3120 			break;
   3121 		default:
   3122 			*an = 0;
   3123 			*an_done = 0;
   3124 			break;
   3125 		}
   3126 	}
   3127 
   3128     LOG_INFO(BSL_LS_SOC_PHY,
   3129              (BSL_META_U(unit,
   3130                          "phy_84328_an_get: u=%d p=%d an=%d\n"), unit, port, *an));
   3131     return SOC_E_NONE;
   3132 }
   3133 
   3134 /*
   3135  * Function:
   3136  *      phy_84328_an_set
   3137  * Purpose:
   3138  *      Enable or disabled auto-negotiation on the specified port.
   3139  * Parameters:
   3140  *      unit - StrataSwitch unit #.
   3141  *      port - StrataSwitch port #.
   3142  *      an   - Boolean, if true, auto-negotiation is enabled
   3143  *              (and/or restarted). If false, autonegotiation is disabled.
   3144  * Returns:
   3145  *      SOC_E_XXX
   3146  */
   3147 STATIC int
   3148 _phy_84328_an_set(int unit, soc_port_t port, int an)
   3149 {
   3150 	int dev_an, dev_an_done;
   3151 	phy_ctrl_t  *pc, *int_pc;
   3152 	phy84328_intf_cfg_t  *line_intf;
   3153 
   3154 	pc = EXT_PHY_SW_STATE(unit, port);
   3155     int_pc = INT_PHY_SW_STATE(unit, port);
   3156 	line_intf = &(LINE_INTF(pc));
   3157 
   3158     LOG_INFO(BSL_LS_SOC_PHY,
   3159              (BSL_META_U(unit,
   3160                          "phy_84328_an_set: u=%d p=%d an=%s\n"),
   3161                          unit, port, an ? "enable" : "disable"));
   3162 
   3163 
   3164 	/*
   3165 	 * Determining line side AN status 
   3166 	 *  SR/LR/SR4/LR4/CR/CR2/SR2: no AN 
   3167 	 *  KR/KR4/KR2: line side: cl73/cl72, system side as forced cl72
   3168 	 *  CR4: if AN disabled, set interface to 40G CR4 DAC(aka XLAUI_DFE), otherwise, CR4
   3169 	 *  GMII: AN handled by internal SerDes
   3170 	 */
   3171 	switch (line_intf->type) {
   3172 	case SOC_PORT_IF_GMII:
   3173     case SOC_PORT_IF_SGMII:
   3174 		AN_EN(pc) = an;
   3175 		SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an));
   3176 		break;
   3177 
   3178 	case SOC_PORT_IF_KX:
   3179 	case SOC_PORT_IF_KR:
   3180 	case SOC_PORT_IF_KR4:
   3181 		AN_EN(pc) = 1;
   3182 		break;
   3183 
   3184 	case SOC_PORT_IF_CR4:
   3185 		AN_EN(pc) = an;
   3186 		break;
   3187 	default:
   3188 		/* Interface does not support AN in the firmware so it's always forced */
   3189 		AN_EN(pc) = FALSE;
   3190 	}
   3191 	SOC_IF_ERROR_RETURN(_phy_84328_intf_type_set(unit, port, line_intf->type, TRUE));
   3192 
   3193     /* If not passtrhu an, make sure firmware has enabled an */
   3194     if (line_intf->speed > 1000) {
   3195         _phy_84328_dev_an_get(unit, port, &dev_an, &dev_an_done);
   3196         if (dev_an != AN_EN(pc)) {
   3197      /*
   3198             LOG_ERROR(BSL_LS_SOC_PHY,
   3199                       (BSL_META_U(unit,
   3200                                   "84328 device autonegotiation mismatch: u=%d p=%d an=%s\n"),
   3201                                   unit, port, AN_EN(pc) ? "en" : "dis"));
   3202      */
   3203         }
   3204     } 
   3205     return SOC_E_NONE;
   3206 }
   3207 
   3208 /*
   3209  * Function:
   3210  *      _phy_84328_ability_advert_get
   3211  * Purpose:
   3212  *      Get the current advertisement for auto-negotiation.
   3213  * Parameters:
   3214  *      unit - StrataSwitch unit #.
   3215  *      port - StrataSwitch port #.
   3216  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   3217  * Returns:
   3218  *      SOC_E_XXX
   3219  * Notes:
   3220  *      The advertisement is retrieved for the ACTIVE medium.
   3221  *      No synchronization performed at this level.
   3222  */
   3223 
   3224 STATIC int
   3225 _phy_84328_ability_advert_get(int unit, soc_port_t port,
   3226                            soc_port_ability_t *ability)
   3227 {
   3228 	phy_ctrl_t  *pc, *int_pc;
   3229     uint16 pause_adv;
   3230 	soc_port_mode_t mode = 0;
   3231 	phy84328_intf_cfg_t  *line_intf;
   3232 
   3233 	if (ability == NULL) {
   3234 		return SOC_E_PARAM;
   3235 	}
   3236 
   3237 	sal_memset(ability, 0, sizeof(soc_port_ability_t));
   3238 
   3239 	pc = EXT_PHY_SW_STATE(unit, port);
   3240 	line_intf = &(LINE_INTF(pc));
   3241     if (_phy_84328_intf_line_forced(unit, port, line_intf->type)) {
   3242         return SOC_E_NONE;
   3243     }
   3244 
   3245     if ((line_intf->type == SOC_PORT_IF_KX) || (line_intf->type == SOC_PORT_IF_GMII)) {
   3246         int_pc = INT_PHY_SW_STATE(unit, port);
   3247         if (int_pc) {
   3248             SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_GET(int_pc->pd, unit, port, ability));
   3249         }
   3250         return SOC_E_NONE;
   3251     }
   3252      
   3253     if(PHY84328_SINGLE_PORT_MODE(pc)) {
   3254         ability->speed_full_duplex = SOC_PA_SPEED_40GB;
   3255     }
   3256     else {
   3257         ability->speed_full_duplex = SOC_PA_SPEED_10GB;
   3258     }
   3259     SOC_IF_ERROR_RETURN
   3260         (READ_PHY84328_MMF_AN_REG(unit, pc, PHY84328_DEV7_AN_ADVERTISEMENT_1_REGISTER, &pause_adv));
   3261     
   3262     mode = 0;
   3263     switch (pause_adv & (CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE)) {
   3264     case CL73_AN_ADV_PAUSE:
   3265         mode = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   3266         break;
   3267     case CL73_AN_ADV_ASYM_PAUSE:
   3268         mode = SOC_PA_PAUSE_TX;
   3269         break;
   3270     case CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE:
   3271         mode = SOC_PA_PAUSE_RX;
   3272         break;
   3273     default:
   3274         mode = 0;
   3275         break;
   3276     }
   3277     ability->pause = mode;
   3278 
   3279     LOG_INFO(BSL_LS_SOC_PHY,
   3280              (BSL_META_U(unit,
   3281                          "phy_84328_ability_advert_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"),
   3282               unit, port, ability->speed_full_duplex, ability->pause));
   3283     return SOC_E_NONE;
   3284 }
   3285 
   3286 /*
   3287 * Function:
   3288 *      _phy_84328_ability_remote_get
   3289 * Purpose:
   3290 *      Get the device's complete abilities.
   3291 * Parameters:
   3292 *      unit - StrataSwitch unit #.
   3293 *      port - StrataSwitch port #.
   3294 *      ability - return device's abilities.
   3295 * Returns:
   3296 *      SOC_E_XXX
   3297 */
   3298 
   3299 STATIC int
   3300 _phy_84328_ability_remote_get(int unit, soc_port_t port, 
   3301                             soc_port_ability_t *ability)
   3302 {
   3303     int an, an_done;
   3304     uint16      pause_adv;
   3305     soc_port_mode_t mode;
   3306     phy_ctrl_t *pc, *int_pc;
   3307 	phy84328_intf_cfg_t  *line_intf;
   3308 
   3309     if (ability == NULL) {
   3310         return SOC_E_PARAM;
   3311     }
   3312 
   3313 	/* Only firmware has visibility into remote ability */
   3314 	sal_memset(ability, 0, sizeof(soc_port_ability_t));
   3315 
   3316     pc = EXT_PHY_SW_STATE(unit, port);
   3317 	line_intf = &(LINE_INTF(pc));
   3318 
   3319     if (_phy_84328_intf_line_forced(unit, port, line_intf->type)) {
   3320         return SOC_E_NONE;
   3321     }
   3322 
   3323     if ((line_intf->type == SOC_PORT_IF_KX) || (line_intf->type == SOC_PORT_IF_GMII)) {
   3324         int_pc = INT_PHY_SW_STATE(unit, port);
   3325         if (int_pc) {
   3326             SOC_IF_ERROR_RETURN(PHY_ABILITY_REMOTE_GET(int_pc->pd, unit, port, ability));
   3327         }
   3328         return SOC_E_NONE;
   3329     }
   3330 
   3331     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   3332 
   3333     mode = 0;
   3334 	/* Return what the firmware is setting */
   3335     /* If an done, then return the speed for the port */
   3336     SOC_IF_ERROR_RETURN(phy_84328_an_get(unit, port, &an, &an_done));
   3337     if (an && an_done) {
   3338         if(PHY84328_SINGLE_PORT_MODE(pc)) {
   3339             ability->speed_full_duplex = SOC_PA_SPEED_40GB;
   3340         }
   3341         else {
   3342             ability->speed_full_duplex = SOC_PA_SPEED_10GB;
   3343         }
   3344 
   3345         mode = 0;
   3346         SOC_IF_ERROR_RETURN
   3347             (READ_PHY84328_MMF_AN_REG(unit, pc, PHY84328_DEV7_AN_LP_BASE_PAGE_ABILITY_1_REG, &pause_adv));
   3348         switch (pause_adv & (CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE)) {
   3349         case CL73_AN_ADV_PAUSE:
   3350             mode = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   3351             break;
   3352         case CL73_AN_ADV_ASYM_PAUSE:
   3353             mode = SOC_PA_PAUSE_TX;
   3354             break;
   3355         case CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE:
   3356             mode = SOC_PA_PAUSE_RX;
   3357         break;
   3358         }
   3359         ability->pause = mode;
   3360     }
   3361     LOG_INFO(BSL_LS_SOC_PHY,
   3362              (BSL_META_U(unit,
   3363                          "phy_84328_ability_remote_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"),
   3364               unit, port, ability->speed_full_duplex, ability->pause));
   3365     return SOC_E_NONE;
   3366 }
   3367 
   3368 /*
   3369  * Function:
   3370  *      _phy_84328_ability_advert_set
   3371  * Purpose:
   3372  *      Set the current advertisement for auto-negotiation.
   3373  * Parameters:
   3374  *      unit - StrataSwitch unit #.
   3375  *      port - StrataSwitch port #.
   3376  *      mode - Port mode mask indicating supported options/speeds.
   3377  * Returns:
   3378  *      SOC_E_XXX
   3379  * Notes:
   3380  *      The advertisement is set only for the ACTIVE medium.
   3381  *      No synchronization performed at this level.
   3382  */
   3383 
   3384 STATIC int
   3385 _phy_84328_ability_advert_set(int unit, soc_port_t port,
   3386 							 soc_port_ability_t *ability)
   3387 {
   3388     uint16 pause;
   3389 	phy_ctrl_t  *pc, *int_pc;
   3390 	phy84328_intf_cfg_t  *line_intf;
   3391 
   3392     if (ability == NULL) {
   3393         return SOC_E_PARAM;
   3394     }
   3395    
   3396 	pc = EXT_PHY_SW_STATE(unit, port);
   3397 	line_intf = &(LINE_INTF(pc));
   3398     if ((line_intf->type == SOC_PORT_IF_KX) || (line_intf->type == SOC_PORT_IF_GMII)) {
   3399         int_pc = INT_PHY_SW_STATE(unit, port);
   3400         if (int_pc) {
   3401             SOC_IF_ERROR_RETURN(PHY_ABILITY_ADVERT_SET(int_pc->pd, unit, port, ability));
   3402         }
   3403         return SOC_E_NONE;
   3404     }
   3405 
   3406     /*
   3407      * Advertisement mostly handled by firmware depending on the mode 
   3408      * However, the firmware will honor the pause advertisement set by the driver
   3409      */
   3410     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   3411     case SOC_PA_PAUSE_TX:
   3412         pause = CL73_AN_ADV_ASYM_PAUSE;
   3413         break;
   3414     case SOC_PA_PAUSE_RX:
   3415         pause = CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE;
   3416         break;
   3417     case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   3418         pause = CL73_AN_ADV_PAUSE;
   3419         break;
   3420     default:
   3421         pause = 0;
   3422         break;
   3423     }
   3424 
   3425     SOC_IF_ERROR_RETURN
   3426         (MODIFY_PHY84328_MMF_AN_REG(unit, pc, PHY84328_DEV7_AN_ADVERTISEMENT_1_REGISTER,
   3427                                     pause, (CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE)));
   3428 
   3429     LOG_INFO(BSL_LS_SOC_PHY,
   3430              (BSL_META_U(unit,
   3431                          "phy_84328_ability_advert_set: u=%d p=%d speed(FD)=%x pause=0x%x\n"),
   3432               unit, port, ability->speed_full_duplex, ability->pause));
   3433     return SOC_E_NONE;
   3434 }
   3435 
   3436 /*
   3437  * Function:
   3438  *      phy_84328_ability_local_get
   3439  * Purpose:
   3440  *      Get the device's complete abilities.
   3441  * Parameters:
   3442  *      unit - StrataSwitch unit #.
   3443  *      port - StrataSwitch port #.
   3444  *      ability - return device's abilities.
   3445  * Returns:
   3446  *      SOC_E_XXX
   3447  */
   3448 
   3449 STATIC int
   3450 phy_84328_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   3451 {
   3452 	uint32		pa_speed = 0;
   3453     phy_ctrl_t  *pc;
   3454 
   3455     pc = EXT_PHY_SW_STATE(unit, port);
   3456 	
   3457     if (ability == NULL) {
   3458         return SOC_E_PARAM;
   3459     }
   3460 	sal_memset(ability, 0, sizeof(soc_port_ability_t));
   3461 
   3462     if (PHY84328_MULTI_CORE_MODE(pc)) {
   3463 	    pa_speed = SOC_PA_SPEED_100GB;
   3464     } else {
   3465 	pa_speed = PHY84328_SINGLE_PORT_MODE(pc) ?
   3466         (SOC_PA_SPEED_40GB | SOC_PA_SPEED_42GB) :
   3467 		(SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB);
   3468     }
   3469         
   3470 	ability->speed_full_duplex = pa_speed;
   3471 	ability->speed_half_duplex = SOC_PA_ABILITY_NONE;
   3472     ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   3473     ability->interface = SOC_PA_INTF_XGMII;
   3474     ability->medium    = SOC_PA_MEDIUM_FIBER;
   3475     ability->loopback  = SOC_PA_LB_PHY;
   3476     ability->flags     = SOC_PA_AUTONEG; 
   3477 
   3478     LOG_INFO(BSL_LS_SOC_PHY,
   3479              (BSL_META_U(unit,
   3480                          "phy_84328_ability_local_get: u=%d p=%d speed=0x%x\n"),
   3481               unit, port, ability->speed_full_duplex));
   3482                                                                                
   3483     return SOC_E_NONE;
   3484 }
   3485 
   3486 STATIC int
   3487 _phy_84328_mod_auto_detect_speed_check(int unit, soc_port_t port, uint16 csr)
   3488 {
   3489 	uint16 csr_speed;
   3490 	phy_ctrl_t *pc;
   3491 	phy84328_intf_cfg_t *line_intf;
   3492 	static int speed_tbl[] = {	0, 1000, 10000, 1000, 40000, 0, 0 ,0, 10000 };
   3493 
   3494 	pc = EXT_PHY_SW_STATE(unit, port);
   3495 	line_intf = &(LINE_INTF(pc));
   3496 
   3497 	csr_speed = csr & (PHY84328_DEV1_GP_REGISTER_1_SPEED_100G_MASK | 
   3498 					   PHY84328_DEV1_GP_REGISTER_1_SPEED_40G_MASK |
   3499 					   PHY84328_DEV1_GP_REGISTER_1_SPEED_10G_MASK |
   3500 					   PHY84328_DEV1_GP_REGISTER_1_SPEED_1G_MASK);
   3501 	if (line_intf->speed != speed_tbl[csr_speed]) {
   3502 		LOG_ERROR(BSL_LS_SOC_PHY,
   3503                           (BSL_META_U(unit,
   3504                                       "84328 module auto detection unexpected: u=%d p=%d csr=0x%x "
   3505                                       "csr table speed=%d line speed=%d\n"),
   3506                            unit, port, csr, speed_tbl[csr_speed], line_intf->speed));
   3507 	}
   3508 	return (line_intf->speed == speed_tbl[csr_speed]);
   3509 }
   3510 
   3511 STATIC int
   3512 _phy_84328_mod_auto_detect_intf_process(int unit, soc_port_t port, uint16 csr)
   3513 {
   3514 	int copper_mod = 0;
   3515 	int lr_mod = 0;
   3516 	phy_ctrl_t *pc;
   3517 	phy84328_intf_cfg_t *line_intf;
   3518 	int intf_update = 1;
   3519 
   3520 	pc = EXT_PHY_SW_STATE(unit, port);
   3521 	line_intf = &(LINE_INTF(pc));
   3522 
   3523 	copper_mod = (csr & PHY84328_DEV1_GP_REGISTER_1_LINE_CU_TYPE_MASK) ==
   3524 		PHY84328_DEV1_GP_REGISTER_1_LINE_CU_TYPE_MASK;
   3525 
   3526 	lr_mod = (csr & PHY84328_DEV1_GP_REGISTER_1_LINE_LR_MODE_MASK) ==
   3527 		PHY84328_DEV1_GP_REGISTER_1_LINE_LR_MODE_MASK;
   3528 
   3529 	/* Change interface if going from optical to copper */ 
   3530 	if (copper_mod) {
   3531 		switch (line_intf->type) {
   3532 		case SOC_PORT_IF_SR:
   3533 		case SOC_PORT_IF_SFI:
   3534 		case SOC_PORT_IF_XFI:
   3535 			line_intf->type = SOC_PORT_IF_CR;
   3536 			break;
   3537 		case SOC_PORT_IF_SR4:
   3538 		case SOC_PORT_IF_XLAUI:
   3539 			line_intf->type = SOC_PORT_IF_CR4;
   3540 			break;
   3541 		default:
   3542 			/* No interface change if not currently an optical interface */
   3543 			intf_update = 0;
   3544 			break;
   3545 		}
   3546 	} else {
   3547 		/* Change interface if going from optical SR to LR */
   3548 		if (lr_mod) {
   3549 			switch (line_intf->type) {
   3550 			case SOC_PORT_IF_SR:
   3551 			case SOC_PORT_IF_SFI:
   3552 			case SOC_PORT_IF_XFI:
   3553 				line_intf->type = SOC_PORT_IF_LR;
   3554 				break;
   3555 			case SOC_PORT_IF_SR4:
   3556 			case SOC_PORT_IF_XLAUI:
   3557 				line_intf->type = SOC_PORT_IF_LR4;
   3558 				break;
   3559 			default:
   3560 				/* No interface change */
   3561 				intf_update = 0;
   3562 				break;
   3563 			}
   3564 		}
   3565 		/* Change interface if going from copper to optical */
   3566 		switch (line_intf->type) {
   3567 		case SOC_PORT_IF_CR:
   3568 			line_intf->type = lr_mod ? SOC_PORT_IF_LR : SOC_PORT_IF_SR;
   3569 			break;
   3570 		case SOC_PORT_IF_CR4:
   3571 			line_intf->type = lr_mod ? SOC_PORT_IF_LR4 : SOC_PORT_IF_SR4;
   3572 			break;
   3573 		default:
   3574 			intf_update = 0;
   3575 			break;
   3576 		}
   3577 	}
   3578 	if (intf_update) {
   3579 		SOC_IF_ERROR_RETURN(_phy_84328_intf_line_sys_update(unit, port));
   3580 	}
   3581 	return SOC_E_NONE;
   3582 }
   3583 
   3584 STATIC int
   3585 _phy_84328_mod_auto_detect_process(int unit, soc_port_t port, uint16 csr) 
   3586 {
   3587 
   3588 	LOG_ERROR(BSL_LS_SOC_PHY,
   3589                   (BSL_META_U(unit,
   3590                               "PHY84328 module detected: u=%d p=%d csr=%x\n"), 
   3591                               unit, port, csr));
   3592 
   3593 	/*
   3594 	 *  Speed cannot change with module detection so it must match the
   3595 	 *  currently configured speed
   3596 	 */
   3597 	if (!_phy_84328_mod_auto_detect_speed_check(unit, port, csr)) {
   3598 		return SOC_E_FAIL;
   3599 	}
   3600 		
   3601 	/*
   3602 	 * Get the line side interface based on the current interface and the 
   3603 	 * detected module
   3604 	 */
   3605 	SOC_IF_ERROR_RETURN(_phy_84328_mod_auto_detect_intf_process(unit, port, csr));
   3606 
   3607 	return SOC_E_NONE;
   3608 }
   3609 
   3610 
   3611 
   3612 STATIC int 
   3613 _phy_84328_mod_auto_detect_update(int unit, soc_port_t port) 
   3614 {
   3615 	phy_ctrl_t *pc;
   3616 	uint16 ucode_csr;
   3617 	uint16 drv_csr;
   3618 
   3619     pc = EXT_PHY_SW_STATE(unit, port);
   3620 
   3621 	/* 
   3622 	 * New module insertion when 1.c843[4] == 1 and 1.c841[4] == 0
   3623 	 */ 
   3624 	SOC_IF_ERROR_RETURN
   3625 		(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_3, &ucode_csr));
   3626 	if (ucode_csr & PHY84328_CSR_REG_MODULE_AUTO_DETECT) {
   3627 
   3628 		SOC_IF_ERROR_RETURN
   3629 			(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_1, &drv_csr));
   3630 		if (!(drv_csr & PHY84328_CSR_REG_MODULE_AUTO_DETECT)) {
   3631 			SOC_IF_ERROR_RETURN(_phy_84328_mod_auto_detect_process(unit, port, ucode_csr));
   3632 			
   3633 			/* 
   3634 			 * Ack firmware that the module insertion has been updated 
   3635 			 * 1.c841[4] = 1, 1.c841[7] = 0
   3636 			 */
   3637 			SOC_IF_ERROR_RETURN
   3638 				(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_1, 
   3639 												 PHY84328_CSR_REG_MODULE_AUTO_DETECT,
   3640 												 PHY84328_CSR_REG_MODULE_AUTO_DETECT |
   3641 												 PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE_MASK));
   3642 		}
   3643 	} else {
   3644 		/* 
   3645 		 * New module removal when 1.c843[4] == 0 and 1.c841[4] == 1
   3646 		 */
   3647 		SOC_IF_ERROR_RETURN
   3648 			(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_1, &drv_csr));
   3649 		if (drv_csr & PHY84328_CSR_REG_MODULE_AUTO_DETECT) {
   3650 
   3651 			/* 
   3652 			 * Ack firmware new module removal 1.c841[4] = 0 
   3653 			 */
   3654 			SOC_IF_ERROR_RETURN
   3655 				(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_1, 
   3656 												 0, PHY84328_CSR_REG_MODULE_AUTO_DETECT));
   3657 			
   3658 			LOG_ERROR(BSL_LS_SOC_PHY,
   3659                                   (BSL_META_U(unit,
   3660                                               "PHY84328 module removed u=%d p=%d\n"), unit, port));
   3661 		}
   3662 	}
   3663 
   3664 	return SOC_E_NONE;
   3665 }
   3666 
   3667 STATIC int
   3668 _phy_84328_do_rxseq_restart(int unit, soc_port_t port,phy84328_intf_side_t side)
   3669 {
   3670 	uint16 data;
   3671 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   3672 
   3673 	PHY_84328_MICRO_PAUSE(unit, port, "rxseq restart1");
   3674     if (side == PHY84328_INTF_SIDE_SYS) {
   3675 	    _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   3676     }
   3677         SOC_IF_ERROR_RETURN
   3678 		    (MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_DSC_MISC_CTRL0,
   3679 										 PHY84328_DEV1_DSC_MISC_CTRL0_RXSEQSTART_MASK,
   3680 										 PHY84328_DEV1_DSC_MISC_CTRL0_RXSEQSTART_MASK));
   3681     if (side == PHY84328_INTF_SIDE_SYS) {
   3682 	    _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   3683     }
   3684 	PHY_84328_MICRO_RESUME(unit, port);
   3685 
   3686 	sal_udelay(800);
   3687 	
   3688 	PHY_84328_MICRO_PAUSE(unit, port, "rxseq restart 2");
   3689     if (side == PHY84328_INTF_SIDE_SYS) {
   3690 	    _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   3691     }
   3692 	    SOC_IF_ERROR_RETURN
   3693 		    (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_DSC_MISC_CTRL0,
   3694 			    						   &data));
   3695 	    if (data & PHY84328_DEV1_DSC_MISC_CTRL0_RXSEQSTART_MASK) {
   3696 		    /*
   3697 		     * Usually 1.c21e[15] rx seq start is cleared by the microcode but there are cases when 
   3698 		     * them micro won't clear it. 
   3699 		     */
   3700 		    SOC_IF_ERROR_RETURN
   3701 			    (MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   3702 											 PHY84328_SYS_DEV1_DSC_MISC_CTRL0, 0,
   3703 											 PHY84328_DEV1_DSC_MISC_CTRL0_RXSEQSTART_MASK));
   3704 	    }
   3705     if (side == PHY84328_INTF_SIDE_SYS) {
   3706 	    _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   3707     }
   3708 	PHY_84328_MICRO_RESUME(unit, port);
   3709 
   3710 	return SOC_E_NONE;
   3711 }
   3712 
   3713 /* 
   3714  * Restart rx sequencer 
   3715  *   no_cdr_lanes == 0: all lanes have cdr - rxseq being restarted because pcs not up
   3716  *                != 0: bitmap of lanes which do not have cdr so restart only those lanes
   3717  */
   3718 STATIC int
   3719 _phy_84328_rxseq_restart(int unit, soc_port_t port, int no_cdr_lanes)
   3720 {
   3721 	int lane;
   3722 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   3723 	phy84328_counters_t *counters =  &(COUNTERS(pc));
   3724 
   3725 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   3726 		if (no_cdr_lanes) {
   3727 			for (lane=0; lane < 4; lane++) {
   3728 				if (no_cdr_lanes & (1<<lane)) {
   3729 					counters->no_cdr++;
   3730 					/* Select the lane on the line side */
   3731 					SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, 
   3732 																  PHY84328_INTF_SIDE_LINE, lane));
   3733 					_phy_84328_do_rxseq_restart(unit, port,
   3734                                                 PHY84328_INTF_SIDE_LINE);
   3735 				}
   3736 			}
   3737 			SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, PHY84328_INTF_SIDE_LINE, 
   3738 														  PHY84328_ALL_LANES));
   3739 		}
   3740 	} 
   3741 
   3742 	if (!no_cdr_lanes) {
   3743 		SOC_IF_ERROR_RETURN(_phy_84328_do_rxseq_restart(unit, port,
   3744                                                     PHY84328_INTF_SIDE_LINE));
   3745 	}
   3746 	return SOC_E_NONE;
   3747 }
   3748 
   3749 
   3750 /*
   3751  * Gets rx seq done status
   3752  * Returns rx_seq_done status and  a lane bitmask for lanes which have sigdet but no rx seq done/cdr locked
   3753  */
   3754 STATIC int
   3755 _phy_84328_rx_seq_done_cdr_lanes_get(int unit, soc_port_t port, phy84328_intf_side_t side,
   3756 									 uint32 *rx_seq_done, uint32 *no_cdr_lanes)
   3757 {
   3758 	uint16 data;
   3759 	int lane_end, lane;
   3760 	uint16  cdr_locked;
   3761 	phy_ctrl_t *pc;
   3762 	pc = EXT_PHY_SW_STATE(unit, port);
   3763 	cdr_locked = 0;
   3764 	*no_cdr_lanes = 0;
   3765 
   3766     if (side == PHY84328_INTF_SIDE_SYS) {
   3767         PHY_84328_MICRO_PAUSE(unit, port, "cdr lanes get");
   3768     }
   3769 
   3770 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   3771 		lane_end = PHY84328_NUM_LANES;
   3772 	}
   3773     else {
   3774 		lane_end = 1;
   3775 		_phy_84328_intf_side_regs_select(unit, port, side);
   3776 	}
   3777 
   3778 	for (lane = 0; lane < lane_end; lane++) {
   3779 		if (PHY84328_SINGLE_PORT_MODE(pc)) {
   3780 			/* Select the lane on the line side */
   3781             SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, lane));
   3782 		}
   3783 		/* Select SigDet/CDR lock status to be read in anaRxStatus */
   3784 		SOC_IF_ERROR_RETURN(
   3785 			READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_ANARXCONTROL, &data));
   3786 		
   3787 		if ((data & PHY84328_SYS_DEV1_ANARXCONTROL_STATUS_SEL_MASK) != 0) {
   3788 			SOC_IF_ERROR_RETURN(
   3789 				MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   3790 												PHY84328_SYS_DEV1_ANARXCONTROL, 0, 
   3791 												PHY84328_SYS_DEV1_ANARXCONTROL_STATUS_SEL_MASK)); 
   3792 		}
   3793 
   3794 		SOC_IF_ERROR_RETURN(
   3795 			READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANARXSTATUS, &data));
   3796 
   3797 		/* CDR==RxSeqDone */
   3798 		if ((data & PHY84328_DEV1_ANARXSTATUS_RXSTATUS_CDR) ==
   3799 			PHY84328_DEV1_ANARXSTATUS_RXSTATUS_CDR) {
   3800 			cdr_locked++;
   3801 		} else if (data & 0x8000) {
   3802 			/* Sigdet but no cdr lock */
   3803 			*no_cdr_lanes |= 1 << lane;
   3804 		}
   3805     }
   3806 	/* Restore to default single port register access */
   3807 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   3808 		SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, PHY84328_INTF_SIDE_LINE, 
   3809 													  PHY84328_ALL_LANES));
   3810 	}
   3811 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   3812     if (side == PHY84328_INTF_SIDE_SYS) {
   3813         PHY_84328_MICRO_RESUME(unit, port);
   3814     }
   3815 
   3816 	*rx_seq_done = (cdr_locked == lane_end);
   3817 	return SOC_E_NONE;
   3818 }
   3819 
   3820 STATIC int
   3821 _phy_84328_rx_seq_done_get(int unit, soc_port_t port, phy84328_intf_side_t side, uint32 *rx_seq_done)
   3822 {
   3823 	uint32 no_cdr_lanes;
   3824 
   3825 	return _phy_84328_rx_seq_done_cdr_lanes_get(unit, port, side, rx_seq_done, &no_cdr_lanes);
   3826 }
   3827 
   3828 STATIC int
   3829 _phy_84328_sw_rx_los_check(int unit, soc_port_t port, uint16 link, uint16 *new_link)
   3830 {
   3831 	int pcs_link;
   3832 	uint8  sys_link;
   3833 	phy_ctrl_t *pc;
   3834 	phy84328_sw_rx_los_states_t rx_los_state;
   3835 	phy84328_sw_rx_los_t *sw_rx_los;
   3836 	uint32 no_cdr_lanes = 0;
   3837 	uint32 rx_seq_done = 0;
   3838 
   3839 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   3840 	int dbg_flag = 1;
   3841 #endif
   3842 
   3843 	pc = EXT_PHY_SW_STATE(unit, port);
   3844 	sw_rx_los = &(SW_RX_LOS(pc));
   3845 
   3846 #ifdef BCM_WARM_BOOT_SUPPORT
   3847     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   3848         *new_link = sw_rx_los->sys_link;
   3849         return SOC_E_NONE;
   3850     }
   3851 #endif
   3852 
   3853 	pcs_link = link; 
   3854 	sys_link = sw_rx_los->sys_link;
   3855 	rx_los_state = sw_rx_los->state;
   3856 	sw_rx_los->link_status = 0;
   3857 	no_cdr_lanes = 0;
   3858 	rx_seq_done = 0;
   3859 
   3860 	SOC_IF_ERROR_RETURN(
   3861 		_phy_84328_rx_seq_done_cdr_lanes_get(unit, port, PHY84328_INTF_SIDE_LINE,  
   3862 											 &rx_seq_done, &no_cdr_lanes));
   3863 
   3864 	if (rx_los_state != PHY84328_SW_RX_LOS_IDLE) {
   3865 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   3866 		LOG_VERBOSE(BSL_LS_SOC_PHY,
   3867                             (BSL_META_U(unit,
   3868                                         "84328 SRL_IN: u=%d p=%d state=%s pcs_link=%d sys_link=%d link_status=%d "
   3869                                         "rx_seq_done=%d no_cdr_lanes=%x\n"), 
   3870                              unit, port, sw_rx_los_state_names[rx_los_state], pcs_link, sys_link, 
   3871                              sw_rx_los->link_status, rx_seq_done, no_cdr_lanes));
   3872 #endif				 
   3873 	}
   3874 
   3875 	/* 
   3876 	 * Current State: Don't Care
   3877 	 * Next State: IDLE
   3878 	 * If link was previously TRUE and is still true, 
   3879 	 * set the state to IDLE
   3880 	 */
   3881 	if ((sys_link == TRUE) && (pcs_link == TRUE)) {
   3882 		rx_los_state = PHY84328_SW_RX_LOS_IDLE;
   3883 	}
   3884 
   3885 	/* 
   3886 	 * Current State: IDLE
   3887 	 * Next State: RESET
   3888 	 * If the state was IDLE(link up) but now link is down, 
   3889 	 * enter the RESET state 
   3890 	 */
   3891 	if ((rx_los_state == PHY84328_SW_RX_LOS_IDLE) && (pcs_link == FALSE)) {
   3892 		rx_los_state = PHY84328_SW_RX_LOS_RESET;
   3893 		sys_link = FALSE;
   3894 	} 
   3895 
   3896 	/* 
   3897 	 * Current State: RESET
   3898 	 * Next State: INITIAL_LINK or START_TIMER
   3899 	 * If state is RESET, it's next state could be INITIAL LINK
   3900 	 * or START_TIMER depending upon the pcs_link state
   3901 	 */
   3902 	if (rx_los_state == PHY84328_SW_RX_LOS_RESET) {
   3903 		if ((pcs_link == TRUE) && rx_seq_done) {
   3904 			rx_los_state = PHY84328_SW_RX_LOS_INITIAL_LINK;
   3905 		} else if (rx_seq_done) {
   3906 			rx_los_state = PHY84328_SW_RX_LOS_START_TIMER;
   3907 			sw_rx_los->ls_ticks = 0;
   3908 		}
   3909 	}
   3910 	if (rx_los_state != PHY84328_SW_RX_LOS_IDLE) {
   3911 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)	
   3912         if (dbg_flag == 1) {
   3913             LOG_VERBOSE(BSL_LS_SOC_PHY,
   3914                         (BSL_META_U(unit,
   3915                                     "84328 SRL_UPD: u=%d p=%d state=%s pcs_link=%d sys_link=%d link_status=%d "
   3916                                     "rx_seq_done=%d\n====\n"), 
   3917                          unit, port, sw_rx_los_state_names[rx_los_state], pcs_link, sys_link, 
   3918                          sw_rx_los->link_status, rx_seq_done));
   3919         }
   3920 #endif		
   3921 	}
   3922 
   3923 	/* Take action depending upon the current state */
   3924 	switch (rx_los_state) {
   3925 	case PHY84328_SW_RX_LOS_IDLE:
   3926 		/* Do nothing */
   3927 		/* Link ON condition */
   3928 		break;
   3929 		
   3930 	case PHY84328_SW_RX_LOS_RESET:
   3931 #ifdef SW_RX_LOS_FLAP_CHECK
   3932 		if (sw_rx_los->fault_report_dis) {
   3933                     SOC_IF_ERROR_RETURN
   3934                         (MAC_CONTROL_SET(sw_rx_los->macd, unit, port,
   3935                                          SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE, TRUE));
   3936                     sw_rx_los->fault_report_dis = 0;
   3937 		}
   3938 #endif
   3939 		sys_link = FALSE;
   3940 		break;
   3941 		
   3942 	case PHY84328_SW_RX_LOS_INITIAL_LINK:
   3943 #ifdef SW_RX_LOS_FLAP_CHECK
   3944 		/* Disable local fault reporting to avoid link flaps untill
   3945 		 *  link stablizes                                                                              
   3946 		 */
   3947 		SOC_IF_ERROR_RETURN
   3948 			(MAC_CONTROL_SET(sw_rx_los->macd, unit, port,
   3949 							 SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE, FALSE));
   3950 		sw_rx_los->fault_report_dis = 1;
   3951 #endif
   3952 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   3953         if (dbg_flag == 1) {
   3954             LOG_VERBOSE(BSL_LS_SOC_PHY,
   3955                         (BSL_META_U(unit,
   3956                                     "84328 sw rx los: u=%d p=%d state=%s: restarting RxSeq\n"), 
   3957                          unit, port, sw_rx_los_state_names[rx_los_state]));
   3958         }
   3959 #endif
   3960 		sw_rx_los->restarts++;
   3961 		SOC_IF_ERROR_RETURN(_phy_84328_rxseq_restart(unit, port, no_cdr_lanes));
   3962 
   3963 		/* Skip the link transition for this rx reset */
   3964 		sw_rx_los->link_status = 1;
   3965 		rx_los_state = PHY84328_SW_RX_LOS_LINK;
   3966 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)		
   3967         if (dbg_flag == 1) {
   3968             LOG_VERBOSE(BSL_LS_SOC_PHY,
   3969                         (BSL_META_U(unit,
   3970                                     "84328 sw rx los: u=%d p=%d state:%s \n"), 
   3971                          unit, port, sw_rx_los_state_names[rx_los_state]));
   3972         }
   3973 #endif
   3974 		break;
   3975 
   3976 	case PHY84328_SW_RX_LOS_LINK:
   3977 
   3978 		if( pcs_link == TRUE) {
   3979 			sys_link = TRUE;
   3980 			sw_rx_los->link_no_pcs = 0;
   3981 			rx_los_state = PHY84328_SW_RX_LOS_IDLE;
   3982 		} else {
   3983 			sw_rx_los->link_no_pcs++;
   3984 			if (sw_rx_los->link_no_pcs > 20) {
   3985 				rx_los_state = PHY84328_SW_RX_LOS_RESET;
   3986 				sw_rx_los->link_no_pcs = 0;
   3987 			}
   3988 		}
   3989 #ifdef SW_RX_LOS_FLAP_CHECK
   3990 		/* Enable local fault reporting disabled earlier */
   3991 		SOC_IF_ERROR_RETURN
   3992 			(MAC_CONTROL_SET(sw_rx_los->macd, unit, port,
   3993 							 SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE, TRUE));
   3994 		sw_rx_los->fault_report_dis = 0;
   3995 #endif
   3996 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   3997         if (dbg_flag == 1) {
   3998             LOG_VERBOSE(BSL_LS_SOC_PHY,
   3999                         (BSL_META_U(unit,
   4000                                     "84328 sw rx los: u=%d p=%d state:%s \n"), 
   4001                          unit, port, sw_rx_los_state_names[rx_los_state]));
   4002         }
   4003 #endif		
   4004 		break;
   4005 
   4006 	case PHY84328_SW_RX_LOS_START_TIMER:
   4007 		sw_rx_los->ls_ticks++;
   4008 		if (pcs_link || (sw_rx_los->ls_ticks > 24)) {
   4009 			rx_los_state = PHY84328_SW_RX_LOS_RX_RESTART;  
   4010 			sw_rx_los->ls_ticks = 0;
   4011 		}
   4012 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)		
   4013         if (dbg_flag == 1) {
   4014             LOG_VERBOSE(BSL_LS_SOC_PHY,
   4015                         (BSL_META_U(unit,
   4016                                     "84328 sw rx los: u=%d p=%d state:%s \n"), 
   4017                          unit, port, sw_rx_los_state_names[rx_los_state]));
   4018         }
   4019 #endif		
   4020 		break;
   4021 
   4022 	case PHY84328_SW_RX_LOS_RX_RESTART:
   4023 #ifdef SW_RX_LOS_FLAP_CHECK
   4024 		/* 
   4025 		 * Disable local fault reporting to avoid link flaps until link stablizes
   4026 		 */
   4027 		SOC_IF_ERROR_RETURN
   4028 			(MAC_CONTROL_SET(sw_rx_los->macd, unit, port,
   4029 							 SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE, FALSE));
   4030 		sw_rx_los->fault_report_dis = 1;
   4031 #endif
   4032 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   4033 	    if (dbg_flag == 1) {
   4034             LOG_VERBOSE(BSL_LS_SOC_PHY,
   4035                         (BSL_META_U(unit,
   4036                                     "84328 sw rx los: u=%d p=%d state:%s -> restarting RxSeq\n"), 
   4037                          unit, port, sw_rx_los_state_names[rx_los_state]));
   4038         }
   4039 #endif
   4040 		sw_rx_los->restarts++;
   4041 		SOC_IF_ERROR_RETURN(_phy_84328_rxseq_restart(unit, port, no_cdr_lanes));
   4042 
   4043 		if( pcs_link == FALSE) {
   4044 			rx_los_state = PHY84328_SW_RX_LOS_RESET;
   4045 		} else {
   4046 			rx_los_state = PHY84328_SW_RX_LOS_LINK;
   4047 		}
   4048 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)		
   4049 	    if (dbg_flag == 1) {
   4050             LOG_VERBOSE(BSL_LS_SOC_PHY,
   4051                         (BSL_META_U(unit,
   4052                                     "84328 sw rx los : u=%d p=%d state:%s \n"), 
   4053                          unit, port, sw_rx_los_state_names[rx_los_state]));
   4054         }
   4055 #endif
   4056 		/* Skip the link transition for this rx reset */
   4057 		sw_rx_los->link_status = 1;
   4058 		break;
   4059 
   4060 	default:
   4061 		break;
   4062 	}
   4063 
   4064 	sw_rx_los->sys_link = sys_link;;
   4065 	sw_rx_los->state = rx_los_state;
   4066 	*new_link = sys_link;
   4067 
   4068 	return SOC_E_NONE;
   4069 }
   4070 
   4071 /* Return contents of ANARXSTATUS */
   4072 STATIC int
   4073 _phy_84328_intf_link_get(int unit, soc_port_t port, uint16 *link)
   4074 {
   4075 	int			lane, max_lane;
   4076 	uint16		data;
   4077     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4078 	*link = 0;
   4079     if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4080         max_lane = PHY84328_NUM_LANES;
   4081     } 
   4082     else {
   4083         max_lane = 1;
   4084     }
   4085 	for (lane = 0; lane < max_lane; lane++) {
   4086 		if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4087             /* Select the lane on the line side */
   4088             SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, PHY84328_INTF_SIDE_LINE, lane));
   4089         }
   4090 		/* Select SigDet/CDR lock status to be read in anaRxStatus */
   4091 		SOC_IF_ERROR_RETURN(
   4092 			READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_ANARXCONTROL, &data));
   4093 		if ((data & PHY84328_SYS_DEV1_ANARXCONTROL_STATUS_SEL_MASK) != 0) {
   4094 			SOC_IF_ERROR_RETURN(
   4095 				MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_ANARXCONTROL,
   4096 												0, PHY84328_SYS_DEV1_ANARXCONTROL_STATUS_SEL_MASK)); 
   4097 		}
   4098 
   4099 		/* Check if rxSeq Done in any lane */
   4100 		SOC_IF_ERROR_RETURN(
   4101 			READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANARXSTATUS, &data));
   4102 		if ((data & PHY84328_DEV1_ANARXSTATUS_RXSTATUS_CDR) ==
   4103             PHY84328_DEV1_ANARXSTATUS_RXSTATUS_CDR) {
   4104 			*link = 1;
   4105 			break;
   4106 		}
   4107 	}
   4108     /* Restore to default single port register access */
   4109     if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4110         SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, PHY84328_INTF_SIDE_LINE,
   4111                                                       PHY84328_ALL_LANES));
   4112     }
   4113     _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   4114 
   4115 	return SOC_E_NONE;
   4116 }
   4117 
   4118 /* 
   4119  * Called when there is no link so check different link components and attempt to 
   4120  * recover by restarting interface if appropriate
   4121  */
   4122 STATIC int
   4123 _phy_84328_link_recover(int unit, soc_port_t port, int line_link, int int_phy_link)
   4124 {
   4125 	phy_ctrl_t  *pc;
   4126 	phy84328_counters_t *counters;
   4127 	phy84328_link_mon_t *link_mon;
   4128 
   4129     pc = EXT_PHY_SW_STATE(unit, port);
   4130 	counters = &(COUNTERS(pc));
   4131 	link_mon = &(LINK_MON(pc));
   4132 
   4133 	if (line_link && !int_phy_link) {
   4134 		if (link_mon->debounce > PHY84328_LINK_DEBOUNCE) {
   4135 			counters->retry_serdes_link++;
   4136 			LOG_INFO(BSL_LS_SOC_PHY,
   4137                                  (BSL_META_U(unit,
   4138                                              "84328 restarting intf: u=%d p=%d line=%04x internal=%04x debounce=%d\n"), 
   4139                                   unit, port, line_link, int_phy_link, link_mon->debounce));
   4140 			SOC_IF_ERROR_RETURN(_phy_84328_intf_line_sys_update(unit, port));
   4141 			link_mon->debounce = 0;
   4142 		} else {
   4143 			link_mon->debounce++;
   4144 		}
   4145 	} else {
   4146 		link_mon->debounce = 0;
   4147 	}
   4148 
   4149 	return SOC_E_NONE;
   4150 }
   4151 
   4152 /*
   4153  * Function:
   4154  *    phy_84328_link_get
   4155  * Purpose:
   4156  *    Get layer2 connection status.
   4157  * Parameters:
   4158  *    unit - StrataSwitch unit #.
   4159  *    port - StrataSwitch port #. 
   4160  *      link - address of memory to store link up/down state.
   4161  * Returns:    
   4162  *    SOC_E_NONE
   4163  */
   4164 
   4165 STATIC int
   4166 _phy_84328_link_get(int unit, soc_port_t port, int *link)
   4167 {
   4168     phy_ctrl_t  *pc;
   4169     phy_ctrl_t  *int_pc;
   4170 	uint16 line_link;
   4171 	int int_phy_link;
   4172 	phy84328_sw_rx_los_t *sw_rx_los;
   4173 	phy84328_link_mon_t *link_mon;
   4174 	phy84328_counters_t *counters;
   4175 
   4176     if (link == NULL) {
   4177         return SOC_E_NONE;
   4178     }
   4179 
   4180     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   4181         *link = 0;
   4182         return SOC_E_NONE;
   4183     }
   4184 
   4185     pc = EXT_PHY_SW_STATE(unit, port);
   4186     int_pc = INT_PHY_SW_STATE(unit, port);
   4187 	counters = &(COUNTERS(pc));
   4188 
   4189 	/* 
   4190 	 * PCS from the internal PHY is used to determine link.
   4191 	 */
   4192     if (int_pc != NULL) {
   4193 		SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &int_phy_link));
   4194 		*link = int_phy_link;
   4195     } else {
   4196 		*link = 0;
   4197 	}
   4198 
   4199 	sw_rx_los = &(SW_RX_LOS(pc));
   4200 	if (sw_rx_los->cur_enable) {
   4201 		uint16 new_link = 0;
   4202 		if (_phy_84328_sw_rx_los_check(unit, port, *link, &new_link) != SOC_E_NONE) {
   4203 			LOG_ERROR(BSL_LS_SOC_PHY,
   4204                                   (BSL_META_U(unit,
   4205                                               "84328  rx los check failed: u=%d port=%d\n"), 
   4206                                               unit, port));
   4207 		}
   4208 		*link = new_link;
   4209 	}
   4210 
   4211 	if (CUR_LINK(pc) && (*link == 0)) {
   4212 		counters->link_down++;
   4213 	}
   4214 	CUR_LINK(pc) = *link;
   4215 
   4216 	link_mon = &(LINK_MON(pc));
   4217 	if (link_mon->cur_enable) {
   4218 		if (*link) {
   4219 			link_mon->debounce = 0;
   4220 		} else {
   4221 			SOC_IF_ERROR_RETURN(_phy_84328_intf_link_get(unit, port, &line_link));
   4222 			if (line_link) {
   4223 				_phy_84328_link_recover(unit, port, line_link, *link);
   4224 			} else {
   4225 				link_mon->debounce = 0;
   4226 			}
   4227 		}
   4228 	}
   4229 
   4230 	if (MOD_AUTO_DETECT(pc)) {
   4231 		_phy_84328_mod_auto_detect_update(unit, port);
   4232 	}
   4233 
   4234     return SOC_E_NONE;
   4235 }
   4236 
   4237 /*
   4238  * Function:
   4239  *    phy_84328_enable_set
   4240  * Purpose:
   4241  *    Enable/Disable phy 
   4242  * Parameters:
   4243  *    unit - StrataSwitch unit #.
   4244  *    port - StrataSwitch port #. 
   4245  *      enable - on/off state to set
   4246  * Returns:    
   4247  *    SOC_E_NONE
   4248  */
   4249 
   4250 STATIC int
   4251 _phy_84328_enable_set(int unit, soc_port_t port, int enable)
   4252 {
   4253 	uint16 chan_data, chan_mask;
   4254 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4255 
   4256 	/* Manually power channel up/down */
   4257     chan_data = enable ? 0 :
   4258                 (1 << PHY84328_DEV1_OPTICAL_CONFIGURATION_MAN_TXON_EN_SHIFT) |
   4259                 (1 << PHY84328_DEV1_OPTICAL_CONFIGURATION_TXOFFT_SHIFT);
   4260     chan_mask = PHY84328_DEV1_OPTICAL_CONFIGURATION_MAN_TXON_EN_MASK |
   4261                 PHY84328_DEV1_OPTICAL_CONFIGURATION_TXOFFT_MASK;
   4262         SOC_IF_ERROR_RETURN(
   4263                 MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_OPTICAL_CONFIGURATION,
   4264                   chan_data, chan_mask));
   4265 	if (enable) {
   4266         /* Let the micro settle down after powering back up */
   4267         if (PORT_ENABLE_DELAY(pc)) {
   4268             sal_udelay(PORT_ENABLE_DELAY(pc));
   4269         }
   4270         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
   4271 	} else {
   4272         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
   4273     }
   4274 
   4275     return SOC_E_NONE;
   4276 }
   4277 
   4278 /*
   4279  * The microcode automatically squelches tx in 1.c066[10] when  opposite side has 
   4280  * no link. Setting 1.ca18[7] disables the microcode from squelching
   4281  */
   4282 STATIC int
   4283 _phy_84328_micro_tx_squelch_enable(int unit, soc_port_t port, int enable)
   4284 {
   4285 	uint16 data;
   4286 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4287         /* 1.ca18[7] 0=micro squelching enabled, 1=micro squelching disabled */
   4288         data = enable ? 0 : 0x80;
   4289 	    SOC_IF_ERROR_RETURN(
   4290                 MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0, data, 0x80));
   4291     return SOC_E_NONE;
   4292 
   4293 }
   4294 
   4295 /*
   4296  * Squelch/unsquelch tx in 1.c066[8]
   4297  */
   4298 STATIC int
   4299 _phy_84328_tx_squelch(int unit, soc_port_t port, phy84328_intf_side_t side, int squelch)
   4300 {
   4301 	uint16      data;
   4302     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4303 
   4304 	_phy_84328_intf_side_regs_select(unit, port, side);
   4305 
   4306     /* 1.c066[8] 0=unsquelch, 1=squelch - electrical idle */
   4307 	data = squelch ? PHY84328_DEV1_ANATXACONTROL2_TX_ELECTRAL_IDLE : 0;
   4308 
   4309         SOC_IF_ERROR_RETURN(
   4310 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL2,
   4311 										data,
   4312 										PHY84328_DEV1_ANATXACONTROL2_TX_ELECTRAL_IDLE));
   4313 	if (side != PHY84328_INTF_SIDE_LINE) {
   4314 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   4315 	}
   4316 	return SOC_E_NONE;
   4317 }
   4318 
   4319 /*
   4320  * Enable/disable transmitter
   4321  */
   4322 STATIC int
   4323 _phy_84328_tx_enable(int unit, soc_port_t port, phy84328_intf_side_t side, int enable)
   4324 {
   4325 	uint16      data;
   4326     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4327 	_phy_84328_intf_side_regs_select(unit, port, side);		
   4328 
   4329 	if (CUR_DATAPATH(pc) == PHY84328_DATAPATH_20) {
   4330 		/* 1.c06a[0] 0=tx enabled, 1=tx disabled */	
   4331 		data = enable ? 0 :
   4332 			(1 << PHY84328_DEV1_ANATXACONTROL6_DISABLE_TRANSMIT_SHIFT);
   4333            
   4334 		    SOC_IF_ERROR_RETURN(
   4335 			    MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   4336 					PHY84328_DEV1_ANATXACONTROL6, 
   4337                     data, PHY84328_DEV1_ANATXACONTROL6_DISABLE_TRANSMIT_MASK));
   4338 	} else {
   4339 		/* 1.c068[13] 0=tx enabled, 1=tx disabled */
   4340 		data = enable ? 0 :  (1 << PHY84328_DEV1_ANATXACONTROL4_XFI_LOWLATENCY_FIFO_ZERO_OUT_SHIFT);
   4341             SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(
   4342                       unit, pc, PHY84328_DEV1_ANATXACONTROL4, data,
   4343                       PHY84328_DEV1_ANATXACONTROL4_XFI_LOWLATENCY_FIFO_ZERO_OUT_MASK));
   4344 	}
   4345 	if (side != PHY84328_INTF_SIDE_LINE) {
   4346 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   4347 	}
   4348 	return SOC_E_NONE;
   4349 }
   4350 
   4351 STATIC int
   4352 _phy_84328_data_path_check(int unit, soc_port_t port)
   4353 {
   4354     phy_ctrl_t  *pc;
   4355     phy84328_intf_cfg_t  *sys_intf;
   4356 
   4357     pc = EXT_PHY_SW_STATE(unit, port);
   4358     sys_intf = &(SYS_INTF(pc));
   4359 
   4360     if (sys_intf->speed < 10000) {
   4361         /* Speeds below 10G requires  20-bit datapath */
   4362         if (CUR_DATAPATH(pc) != PHY84328_DATAPATH_20) {
   4363             CUR_DATAPATH(pc) =  PHY84328_DATAPATH_20;
   4364             SOC_IF_ERROR_RETURN(_phy_84328_intf_datapath_update(unit, port));
   4365         }
   4366     } else {
   4367         /* Speeds 10G and above can use configured dpath, if !forced 20-bit */
   4368         if (FORCE_20BIT(pc) != 0) {
   4369             if (CUR_DATAPATH(pc) != PHY84328_DATAPATH_20) {
   4370                 CUR_DATAPATH(pc) =  PHY84328_DATAPATH_20;
   4371                 SOC_IF_ERROR_RETURN(_phy_84328_intf_datapath_update(unit, port));
   4372             }
   4373         } else {
   4374             if (CUR_DATAPATH(pc) != CFG_DATAPATH(pc)) {
   4375                 CUR_DATAPATH(pc) =  CFG_DATAPATH(pc);
   4376                 SOC_IF_ERROR_RETURN(_phy_84328_intf_datapath_update(unit, port));
   4377             }
   4378         }
   4379     }
   4380     return SOC_E_NONE;
   4381 }
   4382 
   4383 /*
   4384  * Function:
   4385  *    phy_84328_lb_set
   4386  * Purpose:
   4387  *    Put 84328 in PHY PMA/PMD loopback
   4388  * Parameters:
   4389  *    unit - StrataSwitch unit #.
   4390  *    port - StrataSwitch port #. 
   4391  *      enable - binary value for on/off (1/0)
   4392  * Returns:    
   4393  *    SOC_E_NONE
   4394  */
   4395 
   4396 STATIC int
   4397 _phy_84328_lb_set(int unit, soc_port_t port, int enable)
   4398 {
   4399 	int			rv = SOC_E_NONE;
   4400 	uint16		data, mask;
   4401 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4402 	SOC_IF_ERROR_RETURN(_phy_84328_sw_rx_los_pause(unit, port, enable));
   4403 	SOC_IF_ERROR_RETURN(_phy_84328_link_mon_pause(unit, port, enable));
   4404 
   4405     /* 
   4406      * If enabling loopback
   4407      *    disable tx line
   4408      */
   4409     if (enable) {
   4410         SOC_IF_ERROR_RETURN(_phy_84328_tx_enable(unit, port, PHY84328_INTF_SIDE_LINE, FALSE  ));
   4411     }
   4412 
   4413 	/* Loopback requires 20-bit datapath */
   4414     FORCE_20BIT(pc) &= ~(FORCE_20BIT_LB);
   4415     FORCE_20BIT(pc) |= enable ? FORCE_20BIT_LB : 0;
   4416     SOC_IF_ERROR_RETURN(_phy_84328_data_path_check(unit, port));
   4417 
   4418     /* 
   4419      * If disabling loopback
   4420      *    enable tx line
   4421      */
   4422     if (!enable) {
   4423         SOC_IF_ERROR_RETURN(_phy_84328_tx_enable(unit, port, PHY84328_INTF_SIDE_LINE, TRUE   ));
   4424     }
   4425 
   4426 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   4427 	data = enable ? (1 << PHY84328_SYS_DEV1_ANATXACONTROL6_RLOOP_SHIFT) : 
   4428 		(1 << PHY84328_DEV1_ANATXACONTROL6_LOWLATENCY_PATH_SELECT_SHIFT);
   4429 	mask = PHY84328_SYS_DEV1_ANATXACONTROL6_RLOOP_MASK | 
   4430 		PHY84328_DEV1_ANATXACONTROL6_LOWLATENCY_PATH_SELECT_MASK;
   4431         rv = MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_ANATXACONTROL6, data, mask);
   4432         if (SOC_FAILURE(rv)) {
   4433 		    	LOG_ERROR(BSL_LS_SOC_PHY,
   4434                                   (BSL_META_U(unit,
   4435                                               "84328  failed setting loopback: u=%d port=%d\n"), unit, port));
   4436 	    } 
   4437 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   4438 
   4439  	return rv;
   4440 }
   4441 
   4442 /*
   4443  * Function:
   4444  *    phy_84328_lb_get
   4445  * Purpose:
   4446  *    Get 84328 PHY loopback state
   4447  * Parameters:
   4448  *    unit - StrataSwitch unit #.
   4449  *    port - StrataSwitch port #. 
   4450  *      enable - address of location to store binary value for on/off (1/0)
   4451  * Returns:    
   4452  *    SOC_E_NONE
   4453  */
   4454 
   4455 STATIC int
   4456 _phy_84328_lb_get(int unit, soc_port_t port, int *enable)
   4457 {
   4458 	int			rv = SOC_E_NONE;
   4459 	uint16		data;
   4460 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4461 	if (NULL == enable) {
   4462 		return SOC_E_PARAM;
   4463 	}
   4464     *enable = 0xFFFF;
   4465 	/* Check if rloop in system side */
   4466 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   4467     
   4468         rv = READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_ANATXACONTROL6, &data);
   4469         *enable &= ((data & PHY84328_SYS_DEV1_ANATXACONTROL6_RLOOP_MASK) == 
   4470                   (1 << PHY84328_SYS_DEV1_ANATXACONTROL6_RLOOP_SHIFT));
   4471 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   4472 
   4473 	return rv;
   4474 }
   4475 
   4476 STATIC int
   4477 _phy_84328_control_preemphasis_lane_get(soc_phy_control_t type)
   4478 {
   4479 	int lane;
   4480 
   4481 	switch (type) {
   4482 	case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   4483 		lane = 0;
   4484 		break;
   4485 	case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   4486 		lane = 1;
   4487 		break;
   4488 	case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   4489 		lane = 2;
   4490 		break;
   4491 	case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   4492 		lane = 3;
   4493 		break;
   4494 	default:
   4495 		lane = PHY84328_ALL_LANES;
   4496 		break;
   4497 	}
   4498 	return lane;
   4499 }
   4500 
   4501 STATIC int
   4502 _phy_84328_control_preemphasis_set(int unit, soc_port_t port, 
   4503 								   soc_phy_control_t type, 
   4504 								   phy84328_intf_side_t side,
   4505 								   uint32 value)
   4506 {
   4507 	uint16		preemph_value;
   4508 	int         lane, lane_idx, lane_start, lane_end;
   4509 	uint16		tx_fir_sel, tx_fir_mask;
   4510 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4511 	lane = _phy_84328_control_preemphasis_lane_get(type);
   4512 	if (!PHY84328_SINGLE_PORT_MODE(pc) && (lane != PHY84328_ALL_LANES)) {
   4513             if (lane != (pc->phy_id & 0x03)) {
   4514 			    return SOC_E_PARAM;
   4515 		    }
   4516 	}
   4517     preemph_value = (uint16) (value & 0xffff);
   4518 	/*
   4519 	 * Value format:
   4520 	 * bit 15: if set, enable forced preemphasis control, otherwise, auto configured - see 1.c192[3:0] 
   4521 	 * bit 13:10: postcursor_tap   - see 1.c067[7:4]
   4522 	 * bit 08:04: main_tap         - see 1.c066[15:11]
   4523 	 * bit 02:00: precursor_tap    - see 1.c067[2:0]
   4524 	 */ 
   4525 
   4526 	/*
   4527 	 * Single mode: if lane specified, enable only that lane, otherwise enable all lanes
   4528 	 * Quad mode: if specified lane matches lane for the channel, set the lane
   4529 	 */
   4530 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4531 		tx_fir_sel = (lane == PHY84328_ALL_LANES) ? 0xf : (1 << lane);
   4532 		tx_fir_mask = (lane == PHY84328_ALL_LANES) ?  PHY84328_DEV1_XFI_AFE_CTL2_TX_FIR_SEL_MASK :
   4533 			(1 << lane);
   4534 	} else {
   4535 		tx_fir_sel = 1 << (pc->phy_id & 0x03);
   4536 		tx_fir_mask = 1 << (pc->phy_id & 0x03);
   4537 	} 
   4538 
   4539 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4540 		lane_start = (lane == PHY84328_ALL_LANES) ? 0 : lane;
   4541 		lane_end   = (lane == PHY84328_ALL_LANES) ? PHY84328_NUM_LANES : lane + 1;
   4542 	}
   4543     else {
   4544 		/* Make sure specified lane matches lane for the channel */
   4545 		if (lane != PHY84328_ALL_LANES) {
   4546 			if (lane != (pc->phy_id & 0x03)) {
   4547 				return SOC_E_PARAM;
   4548 			}
   4549 		}
   4550 		lane_start = 0;
   4551 		lane_end   = 1;
   4552 	}
   4553 
   4554 	if (side == PHY84328_INTF_SIDE_SYS) {
   4555 		PHY_84328_MICRO_PAUSE(unit, port, "preemphasis set");
   4556 	}
   4557 
   4558 	if (!PHY84328_SINGLE_PORT_MODE(pc)) {
   4559 		_phy_84328_intf_side_regs_select(unit, port, side);
   4560 	}
   4561 	/* Update all requested lanes */
   4562 	for (lane_idx = lane_start; lane_idx < lane_end; lane_idx++) {
   4563 		if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4564 			/* Select the lane and side to write */
   4565 			SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, lane_idx));
   4566 		} 
   4567 		/* Enable manual preemphasis */
   4568 		SOC_IF_ERROR_RETURN(
   4569 			MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_XFI_AFE_CTL2,
   4570 											tx_fir_sel, tx_fir_mask));
   4571 
   4572 		/* Main tap */
   4573 		SOC_IF_ERROR_RETURN(
   4574 			MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL2,
   4575 											PHY84328_PREEMPH_MAIN_TAP_GET(preemph_value) << 
   4576 											PHY84328_DEV1_ANATXACONTROL2_MAIN_TAP_SHIFT,
   4577 											PHY84328_DEV1_ANATXACONTROL2_MAIN_TAP_MASK));
   4578 		
   4579 		/* Pre and post cursor */
   4580 		SOC_IF_ERROR_RETURN(
   4581 			MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL3,
   4582 											(PHY84328_PREEMPH_POST_TAP_GET(preemph_value) << 
   4583 											 PHY84328_DEV1_ANATXACONTROL3_POSTCURSOR_TAP_SHIFT) |
   4584 											(PHY84328_PREEMPH_PRE_TAP_GET(preemph_value) << 
   4585 											 PHY84328_DEV1_ANATXACONTROL3_PRECURSOR_TAP_SHIFT),
   4586 											(PHY84328_DEV1_ANATXACONTROL3_POSTCURSOR_TAP_MASK | 
   4587 											 PHY84328_DEV1_ANATXACONTROL3_PRECURSOR_TAP_MASK)));
   4588 	}
   4589 
   4590 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4591 		SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, PHY84328_ALL_LANES));
   4592 	}
   4593 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   4594 	if (side == PHY84328_INTF_SIDE_SYS) {
   4595 		PHY_84328_MICRO_RESUME(unit, port);
   4596 	}
   4597 
   4598 	return SOC_E_NONE;
   4599 }
   4600 
   4601 STATIC int
   4602 _phy_84328_control_preemphasis_get(int unit, soc_port_t port, soc_phy_control_t type, 
   4603 								   phy84328_intf_side_t side, uint32 *value)
   4604 {
   4605 	int			lane, lane_idx;
   4606 	uint16		forced;
   4607 	uint16		data;
   4608 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4609 
   4610 	lane = _phy_84328_control_preemphasis_lane_get(type);
   4611 	lane_idx = (lane == PHY84328_ALL_LANES) ? 0 : lane;
   4612 
   4613 	if (side == PHY84328_INTF_SIDE_SYS) {
   4614 		PHY_84328_MICRO_PAUSE(unit, port, "preemphasis get");
   4615 	}
   4616 
   4617 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4618 		SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, lane_idx));
   4619 	} else {
   4620 		_phy_84328_intf_side_regs_select(unit, port, side);
   4621 	}
   4622 
   4623 	/*
   4624 	 * Value format:
   4625 	 * bit 15: if set, enable forced preemphasis control, otherwise, auto configured - see 1.c192[3:0] 
   4626 	 * bit 13:10: postcursor_tap   - see 1.c067[7:4]
   4627 	 * bit 08:04: main_tap         - see 1.c066[15:11]
   4628 	 * bit 02:00: precursor_tap    - see 1.c067[2:0]
   4629 	 */ 
   4630 	*value = 0;
   4631 	SOC_IF_ERROR_RETURN(
   4632 		READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_XFI_AFE_CTL2, &data));
   4633 	data &= 0xf;
   4634 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4635 		if (lane == PHY84328_ALL_LANES) {
   4636 			forced = (data == 0xf) ? 1 : 0;
   4637 		} else {
   4638 			forced = (data & (1 << lane)) ? 1 : 0;
   4639 		}
   4640 	} else {
   4641 		forced = (data & (1 << (pc->phy_id & 0x03))) ? 1 : 0;
   4642 	}
   4643 	*value = PHY84328_PREEMPH_FORCE_SET(forced);
   4644     
   4645     SOC_IF_ERROR_RETURN(
   4646 		READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL2, &data));
   4647 	*value |= PHY84328_PREEMPH_MAIN_TAP_SET((data & PHY84328_DEV1_ANATXACONTROL2_MAIN_TAP_MASK) >>
   4648 											PHY84328_DEV1_ANATXACONTROL2_MAIN_TAP_SHIFT);
   4649 	
   4650 	SOC_IF_ERROR_RETURN(
   4651 		READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL3, &data));
   4652 	*value |= PHY84328_PREEMPH_POST_TAP_SET((data & PHY84328_DEV1_ANATXACONTROL3_POSTCURSOR_TAP_MASK) >>
   4653 											PHY84328_DEV1_ANATXACONTROL3_POSTCURSOR_TAP_SHIFT);
   4654 	*value |= PHY84328_PREEMPH_PRE_TAP_SET((data & PHY84328_DEV1_ANATXACONTROL3_PRECURSOR_TAP_MASK) >>
   4655 											PHY84328_DEV1_ANATXACONTROL3_PRECURSOR_TAP_SHIFT);
   4656     if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4657         SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, PHY84328_ALL_LANES));
   4658     }
   4659     _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   4660 	if (side == PHY84328_INTF_SIDE_SYS) {
   4661 		PHY_84328_MICRO_RESUME(unit, port);
   4662 	}
   4663 
   4664     return SOC_E_NONE;
   4665 }
   4666  
   4667 STATIC int
   4668 _phy_84328_txmode_manual_set(int unit, soc_port_t port, phy84328_intf_side_t side, int set)
   4669 {
   4670 	uint16		data, mask;
   4671 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4672 	phy84328_intf_side_t cur_side;
   4673 
   4674 	mask = (side == PHY84328_INTF_SIDE_LINE) ? (1 << 4) : (1 << 3);
   4675 	data = set ? mask : 0;
   4676 
   4677     cur_side = _phy_84328_intf_side_regs_get(unit, port);
   4678     if (cur_side == PHY84328_INTF_SIDE_SYS) {
   4679         _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   4680     }
   4681         SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0,
   4682 														data, mask));
   4683     if (cur_side == PHY84328_INTF_SIDE_SYS) {
   4684 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   4685 	}
   4686 	return SOC_E_NONE;
   4687 }
   4688 
   4689 STATIC int
   4690 _phy_84328_control_tx_driver_set(int unit, soc_port_t port, soc_phy_control_t type, 
   4691 								 phy84328_intf_side_t side, uint32 value)
   4692 {
   4693 	uint16      data, mask;
   4694 	int         lane, lane_idx, lane_start, lane_end;
   4695 	int			idriver = 0;
   4696 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4697 
   4698 	switch (type) {
   4699 	case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   4700 		lane = 0;
   4701 		data = (uint16) (value & 0xf);
   4702 		data = data << PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_SHIFT;
   4703 		mask = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK;
   4704 		idriver = 1;
   4705 		break;
   4706 	case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   4707 		lane = 1;
   4708 		data = (uint16) (value & 0xf);
   4709 		data = data << PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_SHIFT;
   4710 		mask = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK;
   4711 		idriver = 1;
   4712 		break;
   4713 	case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   4714 		lane = 2;
   4715 		data = (uint16) (value & 0xf);
   4716 		data = data << PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_SHIFT;
   4717 		mask = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK;
   4718 		idriver = 1;
   4719 		break;
   4720 	case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   4721 		lane = 3;
   4722 		data = (uint16) (value & 0xf);
   4723 		data = data << PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_SHIFT;
   4724 		mask = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK;
   4725 		idriver = 1;
   4726 		break;
   4727 	case SOC_PHY_CONTROL_DRIVER_CURRENT:
   4728 		lane = PHY84328_ALL_LANES;
   4729 		data = (uint16) (value & 0xf);
   4730 		data = data << PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_SHIFT;
   4731 		mask = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK;
   4732 		idriver = 1;
   4733 		break;
   4734 
   4735 	case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   4736 		lane = 0;
   4737 		data = (uint16) (value & 0xf);
   4738 		data = data << PHY84328_SYS_DEV1_ANATXACONTROL1_IPREDRIVER_SHIFT;
   4739 		mask = PHY84328_DEV1_ANATXACONTROL1_IPREDRIVER_MASK;
   4740 		break;
   4741 	case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   4742 		lane = 1;
   4743 		data = (uint16) (value & 0xf);
   4744 		data = data << PHY84328_SYS_DEV1_ANATXACONTROL1_IPREDRIVER_SHIFT;
   4745 		mask = PHY84328_DEV1_ANATXACONTROL1_IPREDRIVER_MASK;
   4746 		break;
   4747 	case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   4748 		lane = 2;
   4749 		data = (uint16) (value & 0xf);
   4750 		data = data << PHY84328_SYS_DEV1_ANATXACONTROL1_IPREDRIVER_SHIFT;
   4751 		mask = PHY84328_DEV1_ANATXACONTROL1_IPREDRIVER_MASK;
   4752 		break;
   4753 	case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   4754 		lane = 3;
   4755 		data = (uint16) (value & 0xf);
   4756 		data = data << PHY84328_SYS_DEV1_ANATXACONTROL1_IPREDRIVER_SHIFT;
   4757 		mask = PHY84328_DEV1_ANATXACONTROL1_IPREDRIVER_MASK;
   4758 		break;
   4759 	case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   4760 		lane = PHY84328_ALL_LANES;
   4761 		data = (uint16) (value & 0xf);
   4762 		data = data << PHY84328_SYS_DEV1_ANATXACONTROL1_IPREDRIVER_SHIFT;
   4763 		mask = PHY84328_DEV1_ANATXACONTROL1_IPREDRIVER_MASK;
   4764 		break;
   4765 	default:
   4766 		return SOC_E_PARAM;
   4767 	}
   4768 
   4769 	/*                                                                                                
   4770 	 * Qualify lane                                                                                   
   4771 	 * - single mode: if lane specified, enable only that lane in Single_PMD_Ctrl 1.ca86[5:4],
   4772 	 *                otherwise program all lanes        
   4773 	 * - quad mode: make sure the lane corresponds to the channel, and program the lane
   4774      * - 20G mode: if lane specified, enable only that lane, otherwise program all lanes
   4775  	 */
   4776 
   4777 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4778 		lane_start = (lane == PHY84328_ALL_LANES) ? 0 : lane;
   4779 		lane_end   = (lane == PHY84328_ALL_LANES) ? PHY84328_NUM_LANES : lane + 1;
   4780 	}
   4781     else {
   4782 		/* Make sure specified lane matches lane for the channel */
   4783 		if (lane != PHY84328_ALL_LANES) {
   4784 			if (lane != (pc->phy_id & 0x03)) {
   4785 				return SOC_E_PARAM;
   4786 			}
   4787 		}
   4788 		lane_start = 0;
   4789 		lane_end   = 1;
   4790 	}
   4791 
   4792 	/* 
   4793 	 * Driver current (idriver) and tx_mode are updated by the firmware by default.
   4794 	 * If driver current is programmed with value != 0, 
   4795 	 * the firmware will no longer update driver current and tx_mode.
   4796 	 * Setting driver current to 0 (re)enables firmware update of both driver current and
   4797 	 * tx_mode
   4798 	 */
   4799 	if (idriver) {
   4800 		if (data & PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK) {
   4801 			SOC_IF_ERROR_RETURN(_phy_84328_txmode_manual_set(unit, port, side, TRUE));
   4802 		} else {
   4803 			SOC_IF_ERROR_RETURN(_phy_84328_txmode_manual_set(unit, port, side, FALSE));
   4804 		}
   4805 	}
   4806 	if (side == PHY84328_INTF_SIDE_SYS) {
   4807 		PHY_84328_MICRO_PAUSE(unit, port, "tx driver set");
   4808 	}
   4809 
   4810 	if (!PHY84328_SINGLE_PORT_MODE(pc)) {
   4811         _phy_84328_intf_side_regs_select(unit, port, side);
   4812     }
   4813 	/* Update all requested lanes */
   4814 	for (lane_idx = lane_start; lane_idx < lane_end; lane_idx++) {
   4815 		if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4816 			/* Select the lane and side to write */
   4817 			SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, lane));
   4818 		}
   4819 		SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   4820 															PHY84328_DEV1_ANATXACONTROL1,
   4821 															data, mask));
   4822 	}
   4823 
   4824 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4825 		SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, PHY84328_ALL_LANES));
   4826 	}
   4827 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   4828 	if (side == PHY84328_INTF_SIDE_SYS) {
   4829 		PHY_84328_MICRO_RESUME(unit, port);
   4830 	}
   4831 
   4832 	return SOC_E_NONE;
   4833 }
   4834 
   4835 STATIC int
   4836 _phy_84328_control_tx_driver_get(int unit, soc_port_t port, soc_phy_control_t type, 
   4837 								 phy84328_intf_side_t side, uint32 *value)
   4838 {
   4839 	int         rv;
   4840 	int         lane = 0;
   4841 	uint16      data, shift, mask;
   4842 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4843 
   4844 	switch (type) {
   4845 	case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   4846 		lane = 0;
   4847 		shift = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_SHIFT;
   4848 		mask = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK;
   4849 		break;
   4850 	case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   4851 		lane = 1;
   4852 		shift = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_SHIFT;
   4853 		mask = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK;
   4854 		break;
   4855 	case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   4856 		lane = 2;
   4857 		shift = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_SHIFT;
   4858 		mask = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK;
   4859 		break;
   4860 	case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   4861 		lane = 3;
   4862 		shift = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_SHIFT;
   4863 		mask = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK;
   4864 		break;
   4865 	case SOC_PHY_CONTROL_DRIVER_CURRENT:
   4866 		/* Return value for lane 0 */
   4867 		lane = 0;
   4868 		shift = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_SHIFT;
   4869 		mask = PHY84328_SYS_DEV1_ANATXACONTROL1_IDRIVER_MASK;
   4870 		break;
   4871 
   4872 	case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   4873 		lane = 0;
   4874 		shift = PHY84328_SYS_DEV1_ANATXACONTROL1_IPREDRIVER_SHIFT;
   4875 		mask = PHY84328_DEV1_ANATXACONTROL1_IPREDRIVER_MASK;
   4876 		break;
   4877 	case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   4878 		lane = 1;
   4879 		shift = PHY84328_SYS_DEV1_ANATXACONTROL1_IPREDRIVER_SHIFT;
   4880 		mask = PHY84328_DEV1_ANATXACONTROL1_IPREDRIVER_MASK;
   4881 		break;
   4882 	case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   4883 		lane = 2;
   4884 		shift = PHY84328_SYS_DEV1_ANATXACONTROL1_IPREDRIVER_SHIFT;
   4885 		mask = PHY84328_DEV1_ANATXACONTROL1_IPREDRIVER_MASK;
   4886 		break;
   4887 	case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   4888 		lane = 3;
   4889 		shift = PHY84328_SYS_DEV1_ANATXACONTROL1_IPREDRIVER_SHIFT;
   4890 		mask = PHY84328_DEV1_ANATXACONTROL1_IPREDRIVER_MASK;
   4891 		break;
   4892 	case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   4893 		/* Return value for lane 0 */
   4894 		lane = 0;
   4895 		shift = PHY84328_SYS_DEV1_ANATXACONTROL1_IPREDRIVER_SHIFT;
   4896 		mask = PHY84328_DEV1_ANATXACONTROL1_IPREDRIVER_MASK;
   4897 		break;
   4898 	default:
   4899 		return SOC_E_PARAM;
   4900 	}
   4901 
   4902 	if (side == PHY84328_INTF_SIDE_SYS) {	
   4903 		PHY_84328_MICRO_PAUSE(unit, port, "tx driver get");
   4904 	}
   4905 
   4906 	/* Select the lane and side to access */
   4907 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4908 		SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, lane)); 
   4909 	} else {
   4910 		_phy_84328_intf_side_regs_select(unit, port, side);
   4911 	}
   4912 	rv = READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL1, &data);
   4913 	if (SOC_FAILURE(rv)) {
   4914 		LOG_ERROR(BSL_LS_SOC_PHY,
   4915                           (BSL_META_U(unit,
   4916                                       "84328  tx driver get failed: u=%d p=%d\n"), unit, port));
   4917 		*value = 0xff;
   4918 	} else {
   4919 		*value = (data & mask) >> shift;
   4920 	}
   4921 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   4922 		/* Restore back to channel 0 */
   4923 		SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, PHY84328_ALL_LANES));
   4924 	}
   4925 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   4926 
   4927 	if (side == PHY84328_INTF_SIDE_SYS) {
   4928 		PHY_84328_MICRO_RESUME(unit, port);
   4929 	}
   4930     return SOC_E_NONE;
   4931 }
   4932 
   4933 STATIC int
   4934 _phy_84328_control_edc_mode_set(int unit, soc_port_t port, uint32 value)
   4935 {
   4936     return SOC_E_UNAVAIL;
   4937 }
   4938 
   4939 /*
   4940  * enable/disable syncE recoverd clock for 10G/40G modes.
   4941  */
   4942 STATIC int
   4943 _phy_84328_control_recovery_clock_set(int unit, soc_port_t port, int enable)
   4944 {
   4945     return SOC_E_UNAVAIL;
   4946 }
   4947 
   4948 /*
   4949  * set the frequency of the syncE recoverd clock.
   4950  */
   4951 STATIC int
   4952 _phy_84328_control_recovery_clock_freq_set(int unit, soc_port_t port, int freq)
   4953 {
   4954     return SOC_E_UNAVAIL;
   4955 }
   4956 
   4957 STATIC int
   4958 _phy_84328_control_prbs_tx_invert_data_set(int unit, soc_port_t port, int invert)
   4959 {
   4960 	uint16		data;
   4961 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4962 	data = invert ? (1 << PHY84328_SYS_DEV1_ANATXACONTROL7_NEW_PRBS_INV_SHIFT) : 0;
   4963         /* tx prbs invert in anaTxAControl7 1.c06b */
   4964         SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   4965                     PHY84328_DEV1_ANATXACONTROL7,	data,
   4966 					PHY84328_SYS_DEV1_ANATXACONTROL7_NEW_PRBS_INV_MASK));
   4967 
   4968     return SOC_E_NONE;
   4969 }
   4970 
   4971 STATIC int
   4972 _phy_84328_control_prbs_rx_invert_data_set(int unit, soc_port_t port, int invert)
   4973 {
   4974 	uint16		data;
   4975 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4976     
   4977 
   4978 	data = invert ? (1 << PHY84328_SYS_DEV1_ANARXCONTROL2_PRBS_INV_RX_R_SHIFT) : 0;
   4979 	    /* rx prbs invert in anaRxControl2 1.c0b6 */
   4980 	    SOC_IF_ERROR_RETURN(
   4981 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_ANARXCONTROL2, data,
   4982 										PHY84328_SYS_DEV1_ANARXCONTROL2_PRBS_INV_RX_R_MASK));
   4983     return SOC_E_NONE;
   4984 }
   4985 
   4986 STATIC int
   4987 _phy_84328_control_prbs_polynomial_set(int unit, soc_port_t port, int poly_ctrl, int tx) 
   4988 {
   4989 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   4990 
   4991 	LOG_INFO(BSL_LS_SOC_PHY,
   4992                  (BSL_META_U(unit,
   4993                              "84328  prbs polynomial set: u=%d p=%d polynomial=%d\n"),
   4994                              unit, port, poly_ctrl));
   4995 
   4996 	if (poly_ctrl < 0 || poly_ctrl > 3) {
   4997 		LOG_ERROR(BSL_LS_SOC_PHY,
   4998                           (BSL_META_U(unit,
   4999                                       "84328  prbs invalid polynomial: u=%d p=%d polynomial=%d\n"),
   5000                                       unit, port, poly_ctrl));
   5001 		return SOC_E_PARAM;
   5002 	}
   5003 	/* poly_ctrl: 0==prbs7, 1==prbs15, 2==prbs23, 3==prbs=31 */
   5004 	if (tx) {
   5005             /* tx prbs polynomial in anaTxAControl7 1.c06b */
   5006 		    SOC_IF_ERROR_RETURN(
   5007 			    MODIFY_PHY84328_MMF_PMA_PMD_REG(
   5008 				unit, pc, 
   5009 				PHY84328_DEV1_ANATXACONTROL7,
   5010 				(poly_ctrl << PHY84328_DEV1_ANATXACONTROL7_LANE_PRBS_ORDER_NEW_B1_0_SHIFT),
   5011 				PHY84328_SYS_DEV1_ANATXACONTROL7_LANE_PRBS_ORDER_NEW_B1_0_MASK));
   5012 	} else {
   5013             /* rx prbs polynomial in anaRxControl2 1.c0b6 */
   5014 		    SOC_IF_ERROR_RETURN(
   5015 			    MODIFY_PHY84328_MMF_PMA_PMD_REG(
   5016 				unit, pc, 
   5017 				PHY84328_SYS_DEV1_ANARXCONTROL2,
   5018 				(poly_ctrl << PHY84328_DEV1_ANARXCONTROL2_PRBS_ORDER_RX_R_SHIFT),
   5019 				PHY84328_SYS_DEV1_ANARXCONTROL2_PRBS_ORDER_RX_R_MASK));
   5020 	}
   5021     return SOC_E_NONE;
   5022 }
   5023 
   5024 STATIC int
   5025 _phy_84328_sw_rx_los_pause(int unit, soc_port_t port, int enable)
   5026 {
   5027 	phy_ctrl_t *pc;
   5028 	phy84328_sw_rx_los_t *sw_rx_los;
   5029 
   5030 #ifdef BCM_WARM_BOOT_SUPPORT
   5031     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   5032         return SOC_E_NONE;
   5033     }
   5034 #endif
   5035 
   5036 	pc = EXT_PHY_SW_STATE(unit, port);
   5037 	sw_rx_los = &(SW_RX_LOS(pc));
   5038 
   5039 	/* Nothing to do if RX LOS not configured */
   5040 	if (!sw_rx_los->cfg_enable) {
   5041 		return SOC_E_NONE;
   5042 	}
   5043 
   5044 	sw_rx_los->cur_enable = !enable;
   5045 
   5046 	return SOC_E_NONE;
   5047 }
   5048 
   5049 STATIC int
   5050 _phy_84328_link_mon_pause(int unit, soc_port_t port, int enable)
   5051 {
   5052 	phy_ctrl_t *pc;
   5053 	phy84328_link_mon_t *link_mon;
   5054 	
   5055 	pc = EXT_PHY_SW_STATE(unit, port);
   5056 	link_mon = &(LINK_MON(pc));
   5057 
   5058 	/* Nothing to do if LINK_MON not configured */
   5059 	if (!link_mon->cfg_enable) {
   5060 		return SOC_E_NONE;
   5061 	}
   5062 
   5063 	link_mon->cur_enable = !enable;
   5064 	return SOC_E_NONE;
   5065 }
   5066 
   5067 
   5068 STATIC int
   5069 _phy_84328_control_prbs_enable_set(int unit, soc_port_t port, int enable)
   5070 {
   5071 	uint16	    tx_data, rx_data;
   5072 	uint16	    tx_mask, rx_mask;
   5073 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   5074 
   5075 	SOC_IF_ERROR_RETURN(_phy_84328_sw_rx_los_pause(unit, port, enable));
   5076 	SOC_IF_ERROR_RETURN(_phy_84328_link_mon_pause(unit, port, enable));
   5077 
   5078 	/* Mask enable bits */
   5079 	tx_mask = (PHY84328_DEV1_ANATXACONTROL7_SELECT_NEW_PRBS_MASK | 
   5080 			  PHY84328_DEV1_ANATXACONTROL7_NEW_PRBS_EN_MASK);
   5081 	rx_mask = (PHY84328_DEV1_ANARXCONTROL2_PRBS_SEL_RX_R_MASK |
   5082 			  PHY84328_DEV1_ANARXCONTROL2_PRBS_EN_RX_R_MASK);
   5083 
   5084 	/* 
   5085 	 * PRBS done with 20-bit datapath 
   5086 	 */
   5087 	if (enable) {
   5088 		tx_data = (1 << PHY84328_DEV1_ANATXACONTROL7_SELECT_NEW_PRBS_SHIFT) |
   5089 			(1 << PHY84328_DEV1_ANATXACONTROL7_NEW_PRBS_EN_SHIFT);
   5090 		rx_data = (1 << PHY84328_DEV1_ANARXCONTROL2_PRBS_EN_RX_R_SHIFT) |  
   5091 			(1 << PHY84328_DEV1_ANARXCONTROL2_PRBS_SEL_RX_R_SHIFT);
   5092 		if (CFG_DATAPATH(pc) != PHY84328_DATAPATH_20) {
   5093 			CUR_DATAPATH(pc) = PHY84328_DATAPATH_20;
   5094 		}
   5095 	} else {
   5096 		tx_data = 0;
   5097 		rx_data = 0;
   5098 		if (CFG_DATAPATH(pc) != PHY84328_DATAPATH_20) {
   5099 			CUR_DATAPATH(pc) = CFG_DATAPATH(pc);
   5100 		}
   5101 	}
   5102 
   5103     FORCE_20BIT(pc) &= ~(FORCE_20BIT_LB);
   5104     FORCE_20BIT(pc) |= enable ? FORCE_20BIT_LB : 0;
   5105     /* Update datapath */
   5106     SOC_IF_ERROR_RETURN(_phy_84328_intf_datapath_update(unit, port));
   5107     
   5108         /* Enable tx prbs in anaTxAcontrol7 1.c06b[6..5] */
   5109 	    SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5110 														PHY84328_DEV1_ANATXACONTROL7,
   5111 														tx_data, tx_mask));
   5112     	/* Enable rx prbs in anaRxControl2 1.c0b6[6..5] */
   5113         SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5114 														PHY84328_SYS_DEV1_ANARXCONTROL2,
   5115 														rx_data, rx_mask));
   5116 	/* 
   5117 	 * If enabling prbs
   5118 	 *    disable micro tx squelch updates
   5119 	 *    unsquelch tx system
   5120 	 * else
   5121 	 *    enable micro tx squelch updates
   5122 	 */
   5123 	SOC_IF_ERROR_RETURN(_phy_84328_micro_tx_squelch_enable(unit, port, !enable));
   5124 	if (enable) {
   5125 		SOC_IF_ERROR_RETURN(_phy_84328_tx_squelch(unit, port, PHY84328_INTF_SIDE_SYS, 0));
   5126 	}
   5127 
   5128     return SOC_E_NONE;
   5129 }
   5130 
   5131 STATIC int
   5132 _phy_84328_control_prbs_enable_get(int unit, soc_port_t port, uint32 *value)
   5133 {
   5134 	uint16	    tx_data, rx_data;
   5135 	uint16	    tx_en, rx_en;
   5136 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   5137 
   5138 	/* Enable tx prbs in anaTxAcontrol7 1.c06b[6..5] */
   5139 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5140 													  PHY84328_DEV1_ANATXACONTROL7,
   5141 													  &tx_data));
   5142 	/* Enable rx prbs in anaRxControl2 1.c0b6[6..5] */
   5143 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5144 													  PHY84328_SYS_DEV1_ANARXCONTROL2,
   5145 													  &rx_data));
   5146 
   5147 	/* Mask enable bits */
   5148 	tx_data &= (PHY84328_DEV1_ANATXACONTROL7_SELECT_NEW_PRBS_MASK | 
   5149 				PHY84328_DEV1_ANATXACONTROL7_NEW_PRBS_EN_MASK);
   5150 	rx_data &= (PHY84328_DEV1_ANARXCONTROL2_PRBS_SEL_RX_R_MASK |
   5151 				PHY84328_DEV1_ANARXCONTROL2_PRBS_EN_RX_R_MASK);
   5152 
   5153 	tx_en = (tx_data & 
   5154 			 ((1 << PHY84328_DEV1_ANATXACONTROL7_SELECT_NEW_PRBS_SHIFT) |
   5155 			  (1 << PHY84328_DEV1_ANATXACONTROL7_NEW_PRBS_EN_SHIFT))) ==
   5156 		((1 << PHY84328_DEV1_ANATXACONTROL7_SELECT_NEW_PRBS_SHIFT) |
   5157 		 (1 << PHY84328_DEV1_ANATXACONTROL7_NEW_PRBS_EN_SHIFT));
   5158 
   5159 	rx_en = (rx_data & 
   5160 			 ((1 << PHY84328_DEV1_ANARXCONTROL2_PRBS_EN_RX_R_SHIFT) |  
   5161 			  (1 << PHY84328_DEV1_ANARXCONTROL2_PRBS_SEL_RX_R_SHIFT))) ==
   5162 		((1 << PHY84328_DEV1_ANARXCONTROL2_PRBS_EN_RX_R_SHIFT) |  
   5163 		 (1 << PHY84328_DEV1_ANARXCONTROL2_PRBS_SEL_RX_R_SHIFT));
   5164 
   5165 	*value = tx_en && rx_en;
   5166 
   5167     return SOC_E_NONE;
   5168 }
   5169 
   5170 STATIC int
   5171 _phy_84328_control_prbs_polynomial_get(int unit, soc_port_t port, uint32 *value)
   5172 {
   5173 	uint16		data;
   5174 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   5175 
   5176 	*value = 0;
   5177 	/* tx prbs polynomial in anaTxAControl7 1.c06b */
   5178 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5179 													  PHY84328_DEV1_ANATXACONTROL7,
   5180 													  &data));
   5181 	data &= PHY84328_SYS_DEV1_ANATXACONTROL7_LANE_PRBS_ORDER_NEW_B1_0_MASK;
   5182 	*value = data >> PHY84328_DEV1_ANATXACONTROL7_LANE_PRBS_ORDER_NEW_B1_0_SHIFT;
   5183 
   5184     return SOC_E_NONE;
   5185 }
   5186 
   5187 STATIC int
   5188 _phy_84328_control_prbs_tx_invert_data_get(int unit, soc_port_t port, uint32 *value)
   5189 {
   5190 	uint16		data;
   5191 	phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   5192 
   5193 	*value = 0;
   5194 	/* tx invert in anaTxAControl7 1.c06b */
   5195 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5196 													  PHY84328_DEV1_ANATXACONTROL7,	&data));
   5197 	*value = (data & (1 << PHY84328_SYS_DEV1_ANATXACONTROL7_NEW_PRBS_INV_SHIFT)) ==
   5198 		(1 << PHY84328_SYS_DEV1_ANATXACONTROL7_NEW_PRBS_INV_SHIFT);
   5199 
   5200 	return SOC_E_NONE;
   5201 }
   5202 
   5203 STATIC int
   5204 _phy_84328_control_prbs_rx_status_get(int unit, soc_port_t port, phy84328_intf_side_t side, uint32 *value)
   5205 {
   5206     uint16 data, tmp, lane_idx, lanes;
   5207     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   5208     if (PHY84328_SINGLE_PORT_MODE(pc)) {
   5209         lanes = PHY84328_NUM_LANES;
   5210     }
   5211     else {
   5212         lanes = 1;
   5213     }
   5214 
   5215     *value = 0;
   5216 
   5217     for (lane_idx = 0; lane_idx < lanes; lane_idx++) {
   5218         if (PHY84328_SINGLE_PORT_MODE(pc)) {
   5219             /* Select the lane and side to access */
   5220             SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, 
   5221                                            side, lane_idx));
   5222         }
   5223         /* save anaRxControl 1.c0b1 in tmp*/
   5224         SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5225                                  PHY84328_SYS_DEV1_ANARXCONTROL, &tmp));
   5226 
   5227         /* Select PRBS status in anaRxControl 1.c0b1 */	
   5228         SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5229                                    PHY84328_SYS_DEV1_ANARXCONTROL, 7,
   5230                                    PHY84328_DEV1_ANARXCONTROL_STATUS_SEL_MASK));
   5231 
   5232         /* Check for rx PRBS lock in anaRxStatus 1.c0b0 */
   5233         SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5234                                  PHY84328_DEV1_ANARXSTATUS, &data));
   5235 
   5236         /* Restore the old value into  anaRxControl 1.c0b1 */	
   5237         SOC_IF_ERROR_RETURN(WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5238                                    PHY84328_SYS_DEV1_ANARXCONTROL, tmp));
   5239 
   5240         if (data == PHY84328_DEV1_ANARXSTATUS_RXSTATUS_RX_PRBS_LOCK) {
   5241             *value |= 0;		/* locked and no errors */
   5242         } else if ((data & PHY84328_DEV1_ANARXSTATUS_RXSTATUS_RX_PRBS_LOCK) !=
   5243                            PHY84328_DEV1_ANARXSTATUS_RXSTATUS_RX_PRBS_LOCK) {
   5244             *value |= -1;	/* no lock */
   5245         } else {
   5246             /* locked with errors */
   5247             *value |= data & PHY84328_DEV1_ANARXSTATUS_RXSTATUS_RX_PRBS_ERR_MASK;
   5248         }
   5249     }
   5250 
   5251     /* Restore to default single port register access */
   5252     if (PHY84328_SINGLE_PORT_MODE(pc)) {
   5253         SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port,
   5254                              PHY84328_INTF_SIDE_LINE, PHY84328_ALL_LANES));
   5255     }
   5256 
   5257     return SOC_E_NONE;
   5258 }
   5259 
   5260 STATIC int
   5261 _phy_84328_control_edc_mode_get(int unit, soc_port_t port, uint32 *value)
   5262 {
   5263     return SOC_E_UNAVAIL;
   5264 }
   5265 
   5266 STATIC int
   5267 _phy_84328_remote_loopback_set(int unit, soc_port_t port, int intf, uint32 enable)
   5268 {    
   5269 	phy_ctrl_t  *pc;	/* PHY software state */
   5270 	uint16		data, mask;
   5271     pc = EXT_PHY_SW_STATE(unit, port);
   5272 
   5273     /*
   5274      * If enabling remote loopback
   5275      *     disable tx system side
   5276      */
   5277     if (enable) {
   5278         SOC_IF_ERROR_RETURN(_phy_84328_tx_enable(unit, port, PHY84328_INTF_SIDE_SYS, FALSE  ));
   5279     }
   5280 	/* Loopback requires 20-bit datapath */
   5281     FORCE_20BIT(pc) &= ~(FORCE_20BIT_LB);
   5282     FORCE_20BIT(pc) |= enable ? FORCE_20BIT_LB : 0;
   5283     SOC_IF_ERROR_RETURN(_phy_84328_data_path_check(unit, port));
   5284 
   5285     /* 
   5286      * If disabling loopback
   5287      *    enable tx system side
   5288      */
   5289     if (!enable) {
   5290         SOC_IF_ERROR_RETURN(_phy_84328_tx_enable(unit, port, PHY84328_INTF_SIDE_SYS, TRUE   ));
   5291     }
   5292     data = enable ? (1 << PHY84328_SYS_DEV1_ANATXACONTROL6_RLOOP_SHIFT) : 0;
   5293 	mask = PHY84328_SYS_DEV1_ANATXACONTROL6_RLOOP_MASK;
   5294  		SOC_IF_ERROR_RETURN(
   5295                 MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_ANATXACONTROL6, data, mask));
   5296 	return SOC_E_NONE;
   5297 }
   5298 
   5299 STATIC int
   5300 _phy_84328_remote_loopback_get(int unit, soc_port_t port, int intf, uint32 *enable)
   5301 {    
   5302 	int			rv;
   5303 	phy_ctrl_t  *pc;	/* PHY software state */
   5304 	uint16		data;
   5305 
   5306     pc = EXT_PHY_SW_STATE(unit, port);
   5307 
   5308 	rv = READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_ANATXACONTROL6, &data);
   5309 	*enable =  (data & PHY84328_SYS_DEV1_ANATXACONTROL6_RLOOP_MASK) == 
   5310 		PHY84328_SYS_DEV1_ANATXACONTROL6_RLOOP_MASK;
   5311 
   5312 	return rv;
   5313 }
   5314 
   5315 STATIC int
   5316 _phy_84328_debug_info(int unit, soc_port_t port)
   5317 {
   5318 	phy_ctrl_t			*pc;     
   5319 	phy_ctrl_t			*int_pc; 
   5320 	phy84328_intf_cfg_t *intf;
   5321 	phy84328_intf_cfg_t *line_intf;
   5322     phy84328_intf_cfg_t *sys_intf;
   5323 	phy84328_counters_t *counters;
   5324 	phy84328_sw_rx_los_t *sw_rx_los;
   5325 	phy84328_link_mon_t *link_mon;
   5326 	phy84328_intf_side_t side, saved_side;
   5327     char                *rx_los_sts;
   5328 	soc_port_if_t		iif;
   5329 	int					lane;
   5330 	int					ian, ian_done, ilink, ispeed;
   5331 	uint16				link_sts[PHY84328_NUM_LANES];
   5332 	uint16				pol_sts[PHY84328_NUM_LANES];
   5333 	uint16				pol_inv_sts[PHY84328_NUM_LANES];
   5334 	uint16				tx_drv[PHY84328_NUM_LANES];
   5335 	uint16				preemph_main[PHY84328_NUM_LANES];
   5336 	uint16				preemph_pre_post[PHY84328_NUM_LANES];
   5337 	uint16				preemph_manual[PHY84328_NUM_LANES];
   5338 	uint16				data0, data1, data2, data3, data4, data5, data6, data7;
   5339 	uint32				die_temp;
   5340 	uint32				primary_port, offset;
   5341     uint16              i = 0;
   5342 	pc = EXT_PHY_SW_STATE(unit, port);
   5343 	int_pc = INT_PHY_SW_STATE(unit, port);
   5344 	
   5345 	SOC_IF_ERROR_RETURN(phy_84328_control_port_get(unit, port, SOC_PHY_CONTROL_PORT_PRIMARY, 
   5346 											  &primary_port));
   5347 
   5348 	SOC_IF_ERROR_RETURN(phy_84328_control_port_get(unit, port, SOC_PHY_CONTROL_PORT_OFFSET,
   5349 											  &offset));
   5350 
   5351 	/* Access line side registers */
   5352     saved_side = _phy_84328_intf_side_regs_get(unit, port);
   5353     if (saved_side == PHY84328_INTF_SIDE_SYS) {
   5354         _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   5355     }
   5356 
   5357 	/* firware rev: 1.c1f0  */
   5358 	SOC_IF_ERROR_RETURN
   5359 		(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5360 									   PHY84328_DEV1_VERSION, &data0));
   5361 
   5362 	/* micro enabled: 1.ca18 */
   5363 	SOC_IF_ERROR_RETURN
   5364 		(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5365 									   PHY84328_DEV1_GP_REG_0, &data1));
   5366 
   5367 	/* die temperature in 1.c1fd */
   5368 	SOC_IF_ERROR_RETURN
   5369 		(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5370 									   PHY84328_DEV1_TEMPERATURE, &data2));
   5371 	die_temp = 418 - (((data2 & PHY84328_DEV1_TEMPERATURE_TEMPERATURE_MASK) * 5556) / 10000);
   5372 
   5373 	sw_rx_los = &(SW_RX_LOS(pc));
   5374 	link_mon = &(LINK_MON(pc));
   5375     rx_los_sts = "dis";
   5376     if (sw_rx_los->cur_enable) {
   5377         rx_los_sts = "sw";
   5378     } else if (FW_RX_LOS(pc)) {
   5379         rx_los_sts = "fw";
   5380     }
   5381         
   5382 	LOG_CLI((BSL_META_U(unit,
   5383                             "Port %-2d: rev=%d:%d, chiprev=%04x, "
   5384                             "micro ver(1.%04x)=%04x, micro(1.%04x)=%04x, die temp=%d(C)%s\n"
   5385                             "     pri:offs=%d:%d, mdio=0x%x, datapath=%d, "
   5386                             "rxLOS=%s, mod auto=%s, sync=%s, link mon=%s\n"),
   5387                  port, phy84328_maj_rev, phy84328_min_rev,
   5388                  DEVREV(pc),
   5389                  PHY84328_DEV1_VERSION, data0,
   5390                  PHY84328_DEV1_GP_REG_0, data1,
   5391                  die_temp,
   5392                  data2 & PHY84328_DEV1_TEMPERATURE_FORCE_TEMPERATURE_MASK ? 
   5393                  "(forced)" : "",
   5394                  primary_port, offset, pc->phy_id, 
   5395                  CUR_DATAPATH(pc) == PHY84328_DATAPATH_20 ? 20 : 4,
   5396                  rx_los_sts,
   5397                  MOD_AUTO_DETECT(pc) ? "en" : "dis",
   5398                  SYNC_INIT(pc) ? "en" : "dis",
   5399                  link_mon->cur_enable ? "en" : "dis"));
   5400 
   5401 	/* Single PMD control: 1.ca86 */
   5402 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5403 													  PHY84328_DEV1_SINGLE_PMD_CTRL, &data0));
   5404 
   5405 	/* Broadcast control: 1.c8fe */
   5406 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5407 													  PHY84328_DEV1_BROADCAST_CTRL, &data1));
   5408 
   5409 	/* AnaPllStatus 1.c050 */
   5410 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5411 													  PHY84328_DEV1_ANAPLLASTATUS, &data2));
   5412 
   5413 	/* AN 7.0000 */
   5414 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_AN_REG(unit, pc, 
   5415 												 PHY84328_DEV7_AN_CONTROL_REGISTER, &data3));
   5416 
   5417 	/* AN done 1.0097 */
   5418 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5419 													  PHY84328_SYS_DEV1_BASE_R_PMD_STATUS_REGISTER,
   5420 													  &data4));
   5421 
   5422 	/* Regulator control 1.c850 */
   5423 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5424 													  PHY84328_DEV1_REGUALTOR_CTRL, &data5));
   5425 
   5426 	/* Global intf type/speed - driver csr: 1.c841 */
   5427 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5428 													  PHY84328_DEV1_GP_REGISTER_1, &data6));
   5429 
   5430 	/* Micro csr 1.c843 */
   5431 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5432 													  PHY84328_DEV1_GP_REGISTER_3, &data7));
   5433 
   5434 	LOG_CLI((BSL_META_U(unit,
   5435                             "     PMD(1.%04x)=%04x, bcctrl(1.%04x)=%04x, "
   5436                             "pll(1.%04x)=%04x, an(7.%04x/1.%04x)=%04x/%04x\n"
   5437                             "     regulator(1.%04x)=%04x, drvcsr(1.%04x)=%04x, "
   5438                             "ucsr(1.%04x)=%04x\n"),
   5439                  PHY84328_DEV1_SINGLE_PMD_CTRL, data0,
   5440                  PHY84328_DEV1_BROADCAST_CTRL, data1, 
   5441                  PHY84328_DEV1_ANAPLLASTATUS, data2,
   5442                  PHY84328_DEV7_AN_CONTROL_REGISTER, 
   5443                  PHY84328_SYS_DEV1_BASE_R_PMD_STATUS_REGISTER, data3, data4,
   5444                  PHY84328_DEV1_REGUALTOR_CTRL, data5,
   5445                  PHY84328_DEV1_GP_REGISTER_1, data6,
   5446                  PHY84328_DEV1_GP_REGISTER_3, data7));
   5447 
   5448 	counters = &(COUNTERS(pc));
   5449 	LOG_CLI((BSL_META_U(unit,
   5450                             " Counters: link down=%d, intf updates=%d, "
   5451                             "swRxLOS restarts=%d, no cdr=%d, micro nopause=%d\n"
   5452                             "           retry internal=%d, intf chk(speed=%d, "
   5453                             "type=%d, sel=%d)\n"),
   5454                  counters->link_down, counters->intf_updates,
   5455                  sw_rx_los->restarts, 
   5456                  counters->no_cdr, counters->micro_nopause,
   5457                  counters->retry_serdes_link,
   5458                  counters->speed_chk_err, counters->intf_chk_err,
   5459                  counters->side_sel_err));
   5460 
   5461 	/* Interfaces: software, hardware, internal serdes */
   5462 	line_intf = &(LINE_INTF(pc));
   5463     sys_intf = &(SYS_INTF(pc));
   5464 
   5465 	for (side = PHY84328_INTF_SIDE_LINE; side <= PHY84328_INTF_SIDE_SYS; side++) {
   5466 
   5467 		_phy_84328_intf_side_regs_select(unit, port, side);
   5468 
   5469 		/* control: 1.0000 */
   5470 		SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5471 										   PHY84328_DEV1_PMD_CONTROL_REGISTER, &data1));
   5472 		
   5473 		/* PMD type: 1.0007 */
   5474 		SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5475 										  PHY84328_DEV1_PMD_CONTROL_2_REGISTER, &data2));
   5476 
   5477 		/* Loopback 1.c06a */
   5478 		SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5479 														  PHY84328_SYS_DEV1_ANATXACONTROL6, &data3));
   5480 
   5481 		/* Tx disable 1.c066 */
   5482 		SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_ANATXACONTROL2, 
   5483 														  &data4));
   5484 		
   5485 		/* Tx disable 1.c06a */
   5486 		SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5487 														  PHY84328_DEV1_ANATXACONTROL6,
   5488 														  &data5));
   5489 		if (PHY84328_SINGLE_PORT_MODE(pc)) {
   5490 
   5491 			if (side == PHY84328_INTF_SIDE_SYS) {
   5492 				PHY_84328_MICRO_PAUSE(unit, port, "");
   5493 			}
   5494 			for (lane = 0; lane < PHY84328_NUM_LANES; lane++) {
   5495 
   5496 				/* Select the lane and side to write */
   5497                 SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, lane));
   5498 
   5499 				/* Link: 1.c0b0 */
   5500 				SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5501 																  PHY84328_DEV1_ANARXSTATUS, 
   5502 																  &(link_sts[lane])));
   5503 
   5504 				if (CUR_DATAPATH(pc) == PHY84328_DATAPATH_20) {
   5505 					/* Polarity setting: 1.c061 */
   5506 					SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5507 																	  PHY84328_SYS_DEV1_ANATXACONTROL,
   5508 																	  &(pol_sts[lane])));
   5509 				} else {
   5510 					/* Polarity setting: 1.c068 */
   5511 					SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5512 																	  PHY84328_SYS_DEV1_ANATXACONTROL4,
   5513 																	  &(pol_sts[lane])));
   5514 				}
   5515 
   5516 				if (side == PHY84328_INTF_SIDE_LINE) {
   5517 					/* Polarity inversion setting: 1.c0ba[3:2] in the line side */
   5518 					SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5519 																	  PHY84328_DEV1_GP_REGISTER_RX_INV,
   5520 																	  &(pol_inv_sts[lane])));
   5521 				}
   5522 
   5523 				/* TX driver: 1.c065 */
   5524 				SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5525 																  PHY84328_SYS_DEV1_ANATXACONTROL1,
   5526 																  &(tx_drv[lane])));
   5527 				/* Preemphasis manual: 1.c192[15] */
   5528 				SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5529 																  PHY84328_SYS_DEV1_XFI_AFE_CTL2,
   5530 																  &(preemph_manual[lane])));
   5531 
   5532 				/* Preemphasis main: 1.c066[15:11] */
   5533 				SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5534 																  PHY84328_SYS_DEV1_ANATXACONTROL2,
   5535 																  &(preemph_main[lane])));
   5536 
   5537 				/* Preemphasis pre post: 1.c067 */
   5538 				SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5539 																  PHY84328_SYS_DEV1_ANATXACONTROL3,
   5540 																  &(preemph_pre_post[lane])));
   5541 			}
   5542 			/* Back to default channel selection through lane 0 */
   5543 			SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, PHY84328_ALL_LANES));
   5544 			_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   5545 			if (side == PHY84328_INTF_SIDE_SYS) {
   5546 				PHY_84328_MICRO_RESUME(unit, port);
   5547 			}
   5548 
   5549 		} else {
   5550 			    /* Link: 1.c0b0 */
   5551 			    SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5552 															  PHY84328_DEV1_ANARXSTATUS, 
   5553 															  &(link_sts[i])));
   5554 			    if (CUR_DATAPATH(pc) == PHY84328_DATAPATH_20) {
   5555 				    /* Polarity setting: 1.c061 */
   5556 				    SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5557 																  PHY84328_DEV1_ANATXACONTROL, 
   5558 																  &(pol_sts[i])));
   5559 			    } else {
   5560 				    /* Polarity setting: 1.c068 */
   5561 				    SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5562 																  PHY84328_DEV1_ANATXACONTROL4, 
   5563 																  &(pol_sts[i])));
   5564 			    }
   5565 
   5566 			    if (side == PHY84328_INTF_SIDE_LINE) {
   5567 				    /* Polarity inversion setting: 1.c0ba[3:2] in the line side */
   5568 				    SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   5569 																  PHY84328_DEV1_GP_REGISTER_RX_INV,
   5570 																  &(pol_inv_sts[i])));
   5571 			    }
   5572 
   5573 			    /* TX driver: 1.c065 */
   5574 			    SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5575 															  PHY84328_SYS_DEV1_ANATXACONTROL1,
   5576 															  &(tx_drv[i])));
   5577 			    /* Preemphasis manual: 1.c192[15] */
   5578 			    SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5579 															  PHY84328_SYS_DEV1_XFI_AFE_CTL2,
   5580 															  &(preemph_manual[i])));
   5581 			
   5582 			    /* Preemphasis main: 1.c066[15:11] */
   5583 			    SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5584 															  PHY84328_SYS_DEV1_ANATXACONTROL2,
   5585 															  &(preemph_main[i])));
   5586 			
   5587 			    /* Preemphasis pre post: 1.c067 */
   5588 			    SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   5589 															  PHY84328_SYS_DEV1_ANATXACONTROL3,
   5590 															  &(preemph_pre_post[i])));
   5591 		}
   5592 
   5593 		intf = (side == PHY84328_INTF_SIDE_LINE) ? line_intf : sys_intf;			
   5594 
   5595 		if (PHY84328_SINGLE_PORT_MODE(pc)) {
   5596 			LOG_CLI((BSL_META_U(unit,
   5597                                             " %s: type=%s, speed=%d, forced cl72=%d, "
   5598                                             "mode(1.%04x)=%04x\n"
   5599                                             "           pmdtype(1.%04x)=%04x, "
   5600                                             "lb(1.%04x)=%04x, txdis(1.%04x)=%04x/(1.%04x)=%04x\n"
   5601                                             "           link(1.%04x)      : "
   5602                                             "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n"
   5603                                             "           pol(1.%04x)       : "
   5604                                             "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n"),
   5605                                  (side == PHY84328_INTF_SIDE_LINE) ?
   5606                                  "Line    " : "System  ",
   5607                                  phy84328_intf_names[intf->type],
   5608                                  intf->speed, SYS_FORCED_CL72(pc),
   5609                                  PHY84328_DEV1_PMD_CONTROL_REGISTER, data1,
   5610                                  PHY84328_DEV1_PMD_CONTROL_2_REGISTER, data2,
   5611                                  PHY84328_SYS_DEV1_ANATXACONTROL6, data3,
   5612                                  PHY84328_DEV1_ANATXACONTROL2, data4,
   5613                                  PHY84328_DEV1_ANATXACONTROL6, data5,
   5614                                  PHY84328_DEV1_ANARXSTATUS, link_sts[0],
   5615                                  link_sts[1], link_sts[2], link_sts[3],
   5616                                  CUR_DATAPATH(pc) == PHY84328_DATAPATH_20 ?
   5617                                  PHY84328_DEV1_ANATXACONTROL :
   5618                                  PHY84328_DEV1_ANATXACONTROL4,
   5619                                  pol_sts[0], pol_sts[1], pol_sts[2], pol_sts[3]));
   5620 
   5621 			if (side == PHY84328_INTF_SIDE_LINE) {
   5622 				LOG_CLI((BSL_META_U(unit,
   5623                                                     "           pol_inv(1.%04x)   : "
   5624                                                     "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n"),
   5625                                          PHY84328_DEV1_GP_REGISTER_RX_INV,
   5626                                          pol_inv_sts[0], pol_inv_sts[1],
   5627                                          pol_inv_sts[2], pol_inv_sts[3]));
   5628 			}
   5629 			LOG_CLI((BSL_META_U(unit,
   5630                                             "           txdrv(1.%04x)     : "
   5631                                             "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n"
   5632                                             "           preman(1.%04x)    : "
   5633                                             "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n"
   5634                                             "           premain(1.%04x)   : "
   5635                                             "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n"
   5636                                             "           preprepos(1.%04x) : "
   5637                                             "(ln0=%04x, ln1=%04x, ln2=%04x, ln3=%04x)\n"),
   5638                                  PHY84328_DEV1_ANATXACONTROL1, tx_drv[0],
   5639                                  tx_drv[1], tx_drv[2], tx_drv[3],
   5640                                  PHY84328_SYS_DEV1_XFI_AFE_CTL2, preemph_manual[0],
   5641                                  preemph_manual[1], preemph_manual[2], preemph_manual[3],
   5642                                  PHY84328_DEV1_ANATXACONTROL2, preemph_main[0],
   5643                                  preemph_main[1], preemph_main[2], preemph_main[3],
   5644                                  PHY84328_DEV1_ANATXACONTROL3, preemph_pre_post[0],
   5645                                  preemph_pre_post[1], preemph_pre_post[2],
   5646                                  preemph_pre_post[3]));
   5647 		} else {
   5648 			    LOG_CLI((BSL_META_U(unit,
   5649                                                 "Lane:%d: %s: type=%s, speed=%d, "
   5650                                                 "forced cl72=%d, mode(1.%04x)=%04x\n"
   5651                                                 "           pmdtype(1.%04x)=%04x, "
   5652                                                 "lb(1.%04x)=%04x, txdis(1.%04x)=%04x/(1.%04x)=%04x\n"
   5653                                                 "           link(1.%04x)=%04x, "
   5654                                                 "txdrv(1.%04x)=%04x, pol(1.%04x)=%04x"), 
   5655                                      i, (side == PHY84328_INTF_SIDE_LINE) ?
   5656                                      "Line    " : "System  ",
   5657                                      phy84328_intf_names[intf->type],
   5658                                      intf->speed, SYS_FORCED_CL72(pc),
   5659                                      PHY84328_DEV1_PMD_CONTROL_REGISTER, data1,
   5660                                      PHY84328_DEV1_PMD_CONTROL_2_REGISTER, data2,
   5661                                      PHY84328_SYS_DEV1_ANATXACONTROL6, data3,
   5662                                      PHY84328_DEV1_ANATXACONTROL2, data4,
   5663                                      PHY84328_DEV1_ANATXACONTROL6, data5,
   5664                                      PHY84328_DEV1_ANARXSTATUS, link_sts[i],
   5665                                      PHY84328_DEV1_ANATXACONTROL1, tx_drv[i],
   5666                                      CUR_DATAPATH(pc) == PHY84328_DATAPATH_20 ?
   5667                                      PHY84328_DEV1_ANATXACONTROL :
   5668                                      PHY84328_DEV1_ANATXACONTROL4,
   5669                                      pol_sts[i]));
   5670 			    if (side == PHY84328_INTF_SIDE_LINE) {
   5671 				    LOG_CLI((BSL_META_U(unit,
   5672                                                         ", pol_inv(1.%04x)=%04x"),
   5673                                              PHY84328_DEV1_GP_REGISTER_RX_INV,
   5674                                              pol_inv_sts[i]));
   5675 			    }
   5676 			    LOG_CLI((BSL_META_U(unit,
   5677                                                 "\n"
   5678                                      "           preman(1.%04x)=%04x,"
   5679                                                 "premain(1.%04x)=%04x, preprepos(1.%04x)=%04x\n"),
   5680                                      PHY84328_SYS_DEV1_XFI_AFE_CTL2, preemph_manual[i], 
   5681                                      PHY84328_DEV1_ANATXACONTROL2, preemph_main[i],
   5682                                      PHY84328_DEV1_ANATXACONTROL3, preemph_pre_post[i]));
   5683 		}
   5684 	}
   5685 
   5686 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   5687 
   5688 	if (int_pc) {
   5689         int lb;
   5690 		SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET(int_pc->pd, unit, port, &iif));
   5691 		SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &ilink));
   5692         SOC_IF_ERROR_RETURN(_phy_84328_lb_get(unit, port, &lb));
   5693         if (lb) {
   5694             /* Clear the sticky bit if in loopback */
   5695             SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &ilink));
   5696         }
   5697 		SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &ispeed));
   5698 		SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &ian, &ian_done));
   5699 		LOG_CLI((BSL_META_U(unit,
   5700                                     " Internal: type=%s, speed=%d, link=%d, an=%d\n===\n"), 
   5701                          phy84328_intf_names[iif], ispeed, ilink, ian));
   5702 	}
   5703 	if (saved_side == PHY84328_INTF_SIDE_SYS) {
   5704         _phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   5705     }
   5706 
   5707 	return SOC_E_NONE;
   5708 }
   5709 
   5710 STATIC int
   5711 _phy_84328_control_driver_supply_set(int unit, soc_port_t port, phy84328_intf_side_t side,
   5712 									 uint32 value)
   5713 {
   5714     soc_port_phy_control_driver_supply_t ds;
   5715 	uint16 tx_mode = 0;
   5716 
   5717     ds = (soc_port_phy_control_driver_supply_t) value;
   5718 	switch (ds) {
   5719 	case SOC_PHY_CONTROL_DRIVER_SUPPLY_1_5V_1_0V:
   5720 		tx_mode = 4;
   5721 		break;
   5722 	case SOC_PHY_CONTROL_DRIVER_SUPPLY_1_0V_700MV:
   5723 		tx_mode = 0;
   5724 		break;
   5725 	case SOC_PHY_CONTROL_DRIVER_SUPPLY_1_5V_700MV:
   5726 		tx_mode = 1;
   5727 		break;
   5728 	default:
   5729 		return SOC_E_PARAM;
   5730 	}
   5731 
   5732 	return _phy_84328_tx_mode_set(unit, port, side, tx_mode);
   5733 }
   5734 
   5735 STATIC int
   5736 _phy_84328_control_driver_supply_get(int unit, soc_port_t port, phy84328_intf_side_t side,
   5737                                      uint32 *value)
   5738 {
   5739 	uint16 tx_mode = 0;
   5740     soc_port_phy_control_driver_supply_t ds;
   5741 
   5742 	SOC_IF_ERROR_RETURN(_phy_84328_tx_mode_get(unit, port, side, &tx_mode));
   5743 
   5744 	switch (tx_mode) {
   5745 	case 4:
   5746 		ds = SOC_PHY_CONTROL_DRIVER_SUPPLY_1_5V_1_0V;
   5747 		break;
   5748 	case 0:
   5749 		ds = SOC_PHY_CONTROL_DRIVER_SUPPLY_1_0V_700MV;
   5750 		break;
   5751 	case 1:
   5752 		ds = SOC_PHY_CONTROL_DRIVER_SUPPLY_1_5V_700MV;
   5753 		break;
   5754 	default:
   5755 		/* The value is not reliable */
   5756         *value = 0;
   5757 		return SOC_E_UNAVAIL;
   5758 	}
   5759 
   5760     *value = (uint32) ds;
   5761 	return SOC_E_NONE;
   5762 }
   5763 
   5764 STATIC int
   5765 _phy_84328_sw_rx_los_control_set(int unit, soc_port_t port, uint32 value)
   5766 {
   5767     phy_ctrl_t *pc= EXT_PHY_SW_STATE(unit, port);
   5768     phy84328_sw_rx_los_t *sw_rx_los = &(SW_RX_LOS(pc));
   5769 
   5770 #ifdef BCM_WARM_BOOT_SUPPORT
   5771     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   5772         return SOC_E_NONE;
   5773     }
   5774     /* preserve SW RxLOS status in register 1.0xC01A for warmboot support */
   5775     SOC_IF_ERROR_RETURN( _phy_84328_preserve_sw_rx_los(unit, port, value) );
   5776 #endif
   5777 
   5778     sw_rx_los->cfg_enable = value;
   5779     sw_rx_los->cur_enable = value;
   5780     if (value) {
   5781         sw_rx_los->sys_link = 0;
   5782         sw_rx_los->state = PHY84328_SW_RX_LOS_RESET;
   5783         sw_rx_los->link_status = 0;
   5784         sw_rx_los->link_no_pcs = 0;
   5785         sw_rx_los->restarts = 0;
   5786 #ifdef SW_RX_LOS_FLAP_CHECK
   5787         sw_rx_los->fault_report_dis = 0;
   5788         if (sw_rx_los->macd == NULL) {
   5789             SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &(sw_rx_los->macd)));
   5790         }
   5791 #endif
   5792     }
   5793     return SOC_E_NONE;
   5794 }
   5795 
   5796 STATIC int
   5797 _phy_84328_fw_rx_los_control_set(int unit, soc_port_t port, uint32 value)
   5798 {
   5799     int lane_start, lane_end, lane;
   5800     int fw_rx_los_en_data, fw_rx_los_en_mask;
   5801     phy_ctrl_t *pc= EXT_PHY_SW_STATE(unit, port);
   5802     uint32 lane_reg[PHY84328_NUM_LANES] = /* per lane registers timeout */
   5803         { 0xca99, 0xca9b, 0xca9d, 0xca9f };
   5804 
   5805     FW_RX_LOS(pc) = value;
   5806 
   5807     fw_rx_los_en_mask = (1 << 15) | (1 << 14);
   5808     if (value) {
   5809         if (PHY84328_SINGLE_PORT_MODE(pc)) {
   5810             lane_start = 0;
   5811             lane_end = PHY84328_NUM_LANES;
   5812         } 
   5813         else {
   5814             lane_start = pc->phy_id & 0x3;
   5815             lane_end = lane_start + 1;
   5816         }
   5817         for (lane = lane_start; lane < lane_end; lane++) {
   5818             /* Program the timeout value */
   5819             SOC_IF_ERROR_RETURN(               
   5820                 MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, lane_reg[lane], 
   5821                                                 0xffff, 0xffff));
   5822         }
   5823         fw_rx_los_en_data = (1 << 15) | (1 << 14);
   5824     } else {
   5825         fw_rx_los_en_data = 0;
   5826     }
   5827         SOC_IF_ERROR_RETURN(               
   5828             MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 0xc480, fw_rx_los_en_data, 
   5829                                         fw_rx_los_en_mask));
   5830     if (value){
   5831 	    /* Update interface type/speed */
   5832         SOC_IF_ERROR_RETURN(_phy_84328_intf_line_sys_update(unit, port));
   5833     }
   5834 
   5835     return SOC_E_NONE;
   5836 }
   5837 
   5838 STATIC int
   5839 _phy_84328_rx_los_control_set(int unit, soc_port_t port, uint32 value)
   5840 {
   5841     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   5842     int rv  = SOC_E_NONE;
   5843     int rv2 = SOC_E_NONE;
   5844 
   5845     switch (value) {
   5846         case SOC_PHY_CONTROL_RX_LOS_NONE:
   5847             rv  = _phy_84328_sw_rx_los_control_set(unit, port, 0);
   5848             rv2 = _phy_84328_fw_rx_los_control_set(unit, port, 0);
   5849             rv  = (rv == SOC_E_NONE) ? rv2 : rv;
   5850             break;
   5851         case SOC_PHY_CONTROL_RX_LOS_FIRMWARE:
   5852             if (DEVREV(pc) == 0x00a0) {
   5853                 rv  = _phy_84328_sw_rx_los_control_set(unit, port, 1);
   5854             } else {
   5855                 rv  = _phy_84328_sw_rx_los_control_set(unit, port, 0);
   5856                 rv2 = _phy_84328_fw_rx_los_control_set(unit, port, 1);
   5857                 rv  = (rv == SOC_E_NONE) ? rv2 : rv;
   5858             }
   5859             break;
   5860         case SOC_PHY_CONTROL_RX_LOS_SOFTWARE:
   5861         default:
   5862             if (DEVREV(pc) == 0x00a0) {
   5863                 rv  = _phy_84328_sw_rx_los_control_set(unit, port, 1);
   5864             } else {
   5865                 rv  = _phy_84328_fw_rx_los_control_set(unit, port, 0);
   5866                 rv2 = _phy_84328_sw_rx_los_control_set(unit, port, 1);
   5867                 rv  = (rv == SOC_E_NONE) ? rv2 : rv;
   5868             }
   5869             break;
   5870     }
   5871 
   5872     return rv;
   5873 }
   5874 
   5875 STATIC int
   5876 _phy_84328_rx_los_control_get(int unit, soc_port_t port, uint32 *value)
   5877 {
   5878     phy84328_sw_rx_los_t *sw_rx_los;
   5879     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   5880 
   5881     sw_rx_los = &(SW_RX_LOS(pc));
   5882 
   5883     if (sw_rx_los->cur_enable) {
   5884         *value = SOC_PHY_CONTROL_RX_LOS_SOFTWARE;
   5885     } else if (FW_RX_LOS(pc)) {
   5886         *value = SOC_PHY_CONTROL_RX_LOS_FIRMWARE;
   5887     } else {
   5888         *value = SOC_PHY_CONTROL_RX_LOS_NONE;
   5889     }
   5890 
   5891     return SOC_E_NONE;
   5892 }
   5893 
   5894 STATIC int
   5895 _phy_84328_mod_auto_detect_set(int unit, soc_port_t port, uint32 value)
   5896 {
   5897     phy_ctrl_t *pc;
   5898     uint16 data;
   5899     uint16 rddata;
   5900     uint16 count = 0;
   5901     uint16 mask;
   5902 
   5903     pc = EXT_PHY_SW_STATE(unit, port);
   5904     mask = PHY84328_DEV1_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK; 
   5905     data = value ? mask : 0;
   5906 
   5907     SOC_IF_ERROR_RETURN(
   5908         MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0, data, 
   5909                                         mask));
   5910  
   5911     if (!value) {
   5912         /* Request is disabling mod auto detect, need to wait until I2CM FSM  becomes IDLE */
   5913         /* Wait approx for 325 ms */ 
   5914         while (count < I2CM_IDLE_WAIT_COUNT){
   5915             SOC_IF_ERROR_RETURN(
   5916                 READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_I2C_CONTROL_REGISTER, &rddata));
   5917             if ((rddata & 0xC) == 0) {
   5918                 break;
   5919             }
   5920             count ++;
   5921             sal_usleep(I2CM_IDLE_WAIT_CHUNK * 1000);
   5922         }
   5923         if (count >= I2CM_IDLE_WAIT_COUNT) {
   5924             return SOC_E_BUSY;
   5925         }
   5926     }
   5927  
   5928     /* Update the global database */
   5929     MOD_AUTO_DETECT(pc) = value ? 1:0; 
   5930     
   5931     return SOC_E_NONE;
   5932 }
   5933 
   5934 STATIC int
   5935 _phy_84328_mod_auto_detect_get(int unit, soc_port_t port, uint32 *value)
   5936 {
   5937     phy_ctrl_t *pc;
   5938     uint16 data;
   5939  
   5940     pc = EXT_PHY_SW_STATE(unit, port);
   5941 
   5942     SOC_IF_ERROR_RETURN(
   5943         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REG_0, &data));
   5944 
   5945     if( data & PHY84328_DEV1_GP_REG_0_ENABLE_SFP_MOD_DETECT_MASK ) {
   5946         *value = 1;
   5947     } else {
   5948         *value = 0;
   5949     } 
   5950     return SOC_E_NONE;
   5951 }
   5952 
   5953 STATIC int
   5954 _phy_84328_force_cl72_config(int unit, soc_port_t port, uint32 enable)
   5955 {
   5956     uint16 intf_side = 0;
   5957     uint16 data = 0 , mask = 0;
   5958     phy_ctrl_t    *pc;       /* PHY software state */
   5959     pc = EXT_PHY_SW_STATE(unit, port);
   5960 
   5961     intf_side = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   5962                 PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE;
   5963     if (intf_side == PHY84328_INTF_SIDE_SYS) {
   5964         data = enable ? PHY84328_DEV1_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_MASK : 0;
   5965         mask = PHY84328_DEV1_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_MASK;
   5966     } else {
   5967         data = enable ? PHY84328_DEV1_GP_REGISTER_1_LINE_FORCED_CL72_MODE_MASK : 0;
   5968         mask = PHY84328_DEV1_GP_REGISTER_1_LINE_FORCED_CL72_MODE_MASK;
   5969     }
   5970     data |= PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE_MASK;
   5971     mask |= PHY84328_DEV1_GP_REGISTER_1_FINISH_CHANGE_MASK; 
   5972     SOC_IF_ERROR_RETURN(
   5973             _phy_84328_intf_update(unit, port, data, mask));
   5974     return SOC_E_NONE;
   5975 }
   5976 
   5977 STATIC int
   5978 _phy_84328_force_cl72_status(int unit, soc_port_t port, uint32 *value)
   5979 {
   5980     uint16 intf_side = 0, data = 0;
   5981     phy_ctrl_t    *pc;       /* PHY software state */
   5982     pc = EXT_PHY_SW_STATE(unit, port);
   5983 
   5984     intf_side = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   5985                 PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE;
   5986 
   5987     SOC_IF_ERROR_RETURN(
   5988         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GP_REGISTER_3, &data));
   5989     *value = 0;
   5990 
   5991     if (intf_side == PHY84328_INTF_SIDE_SYS) {
   5992         *value = (data & PHY84328_DEV1_GP_REGISTER_1_SYSTEM_FORCED_CL72_MODE_MASK) ? 1 : 0;
   5993     } else {
   5994         *value = (data & PHY84328_DEV1_GP_REGISTER_1_LINE_FORCED_CL72_MODE_MASK) ? 1 : 0;
   5995     }
   5996 
   5997     return SOC_E_NONE;
   5998 }
   5999 
   6000 /*
   6001  * Function:
   6002  *      _phy_84328_control_set
   6003  * Purpose:
   6004  *      Configure PHY device specific control fucntion.
   6005  * Parameters:
   6006  *      unit  - StrataSwitch unit #.
   6007  *      port  - StrataSwitch port #.
   6008  *      type  - Control to update
   6009  *      value - New setting for the control
   6010  * Returns:
   6011  *      SOC_E_NONE
   6012  */
   6013 STATIC int
   6014 _phy_84328_control_set(int unit, soc_port_t port, int intf, int lane,
   6015                      soc_phy_control_t type, uint32 value)
   6016 {
   6017     phy_ctrl_t    *pc;       /* PHY software state */
   6018     int rv;
   6019 
   6020     pc = EXT_PHY_SW_STATE(unit, port);
   6021 
   6022     PHY_CONTROL_TYPE_CHECK(type);
   6023 
   6024     rv = SOC_E_UNAVAIL;
   6025     if (intf == PHY_DIAG_INTF_SYS) {
   6026 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   6027         pc->flags |= PHYCTRL_SYS_SIDE_CTRL ;
   6028     }
   6029     switch (type) {
   6030     case SOC_PHY_CONTROL_PREEMPHASIS:
   6031 		/* fall through */
   6032     case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   6033         /* fall through */
   6034     case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   6035         /* fall through */
   6036     case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   6037         /* fall through */
   6038     case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   6039 		rv = _phy_84328_control_preemphasis_set(unit, port, type, 
   6040 												(pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   6041 												PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE, 
   6042 												value);
   6043 		break;
   6044     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   6045         /* fall through */
   6046     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   6047         /* fall through */
   6048     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   6049         /* fall through */
   6050     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   6051         /* fall through */
   6052     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   6053         /* fall through */
   6054     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   6055         /* fall through */
   6056     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   6057         /* fall through */
   6058     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   6059         /* fall through */
   6060     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   6061         /* fall through */
   6062     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   6063         rv = _phy_84328_control_tx_driver_set(unit, port, type,
   6064 											  (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   6065 											  PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE, 
   6066 											  value);
   6067         break;
   6068     case SOC_PHY_CONTROL_EDC_MODE:
   6069         rv = _phy_84328_control_edc_mode_set(unit,port,value);
   6070         break;
   6071     case SOC_PHY_CONTROL_CLOCK_ENABLE:
   6072         rv = _phy_84328_control_recovery_clock_set(unit,port,value);
   6073         break;
   6074     case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
   6075         rv = _phy_84328_control_recovery_clock_freq_set(unit,port,value);
   6076         break;
   6077     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   6078         rv = _phy_84328_control_prbs_polynomial_set(unit, port, value, TRUE);
   6079 		if (SOC_SUCCESS(rv)) {
   6080 			rv = _phy_84328_control_prbs_polynomial_set(unit, port,value, FALSE);
   6081 		}
   6082         break;
   6083     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   6084         rv = _phy_84328_control_prbs_tx_invert_data_set(unit, port, value);
   6085 		if (SOC_SUCCESS(rv)) {
   6086 			rv = _phy_84328_control_prbs_rx_invert_data_set(unit, port, value);
   6087 		}
   6088         break;
   6089     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   6090         /* fall through */
   6091     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   6092         /* tx/rx is enabled at the same time. no seperate control */
   6093         rv = _phy_84328_control_prbs_enable_set(unit, port, value);
   6094         break;
   6095     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   6096         rv = _phy_84328_remote_loopback_set(unit, port, intf, value);
   6097         break;
   6098     case SOC_PHY_CONTROL_PORT_PRIMARY:
   6099         rv = soc_phyctrl_primary_set(unit, port, (soc_port_t)value);
   6100         break;
   6101     case SOC_PHY_CONTROL_PORT_OFFSET:
   6102 		rv = soc_phyctrl_offset_set(unit, port, (int)value);
   6103         break;
   6104     case SOC_PHY_CONTROL_SOFTWARE_RX_LOS:
   6105 		rv = _phy_84328_rx_los_control_set(unit, port, value);
   6106 		break;
   6107 	case SOC_PHY_CONTROL_DUMP:
   6108 		/* in control set for consistency with other drivers */
   6109 		rv = _phy_84328_debug_info(unit, port);
   6110 		break;
   6111 	case SOC_PHY_CONTROL_DRIVER_SUPPLY:
   6112 		rv = _phy_84328_control_driver_supply_set(unit, port,
   6113 												  (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   6114 												  PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE, 
   6115 												  value);
   6116 		break;
   6117 	case SOC_PHY_CONTROL_RX_SEQ_TOGGLE:
   6118    	    /* value is not used since this is always a toggle ->1->0 */
   6119         rv = _phy_84328_do_rxseq_restart(unit, port,
   6120                             (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   6121                             PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE);
   6122         break;
   6123     case SOC_PHY_CONTROL_MOD_AUTO_DETECT_ENABLE:
   6124         rv = _phy_84328_mod_auto_detect_set(unit,port,value); 
   6125         break;
   6126     case SOC_PHY_CONTROL_CL72:
   6127         rv = _phy_84328_force_cl72_config(unit, port, value);
   6128         break;
   6129     case SOC_PHY_CONTROL_PCS_MODE:
   6130         {
   6131             phy_ctrl_t *int_pc;
   6132             phy84328_intf_cfg_t *line_intf;
   6133             rv = SOC_E_NONE;
   6134             int_pc = INT_PHY_SW_STATE(unit, port);
   6135 	        line_intf = &(LINE_INTF(pc));
   6136             if (int_pc) {
   6137                 SOC_IF_ERROR_RETURN(
   6138                     PHY_CONTROL_SET(int_pc->pd, unit, port, type, value));
   6139 
   6140                 SOC_IF_ERROR_RETURN(PHY_SPEED_SET(int_pc->pd, unit, port, 
   6141                      line_intf->speed));
   6142             } else {
   6143                 rv = SOC_E_INTERNAL;
   6144             }
   6145         }
   6146         break;
   6147     default:
   6148         rv = SOC_E_UNAVAIL;
   6149         break;
   6150     }
   6151     if (intf == PHY_DIAG_INTF_SYS) {
   6152         /* if it is targeted to the system side, switch back */
   6153 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   6154         pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL ;
   6155     }
   6156     return rv;
   6157 }
   6158 
   6159 STATIC int
   6160 phy_84328_control_port_set(int unit, soc_port_t port,
   6161                      soc_phy_control_t type, uint32 value)
   6162 {
   6163     SOC_IF_ERROR_RETURN(_phy_84328_control_set(unit, port, PHY_DIAG_INTF_LINE,
   6164 											   PHY_DIAG_LN_DFLT, type, value));
   6165     return SOC_E_NONE;
   6166 }
   6167 
   6168 /*
   6169  * Function:
   6170  *      phy_84328_control_get
   6171  * Purpose:
   6172  *      Get current control settign of the PHY.
   6173  * Parameters:
   6174  *      unit  - StrataSwitch unit #.
   6175  *      port  - StrataSwitch port #.
   6176  *      type  - Control to update
   6177  *      value - (OUT)Current setting for the control
   6178  * Returns:
   6179  *      SOC_E_NONE
   6180  */
   6181 STATIC int
   6182 _phy_84328_control_get(int unit, soc_port_t port, int intf, int lane,
   6183                      soc_phy_control_t type, uint32 *value)
   6184 {
   6185     phy_ctrl_t    *pc;       /* PHY software state */
   6186     int rv, offset;
   6187     soc_port_t primary;
   6188     pc = EXT_PHY_SW_STATE(unit, port);
   6189 
   6190 
   6191     PHY_CONTROL_TYPE_CHECK(type);
   6192 
   6193     if (intf == PHY_DIAG_INTF_SYS) {
   6194 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   6195         pc->flags |= PHYCTRL_SYS_SIDE_CTRL ;
   6196     }
   6197     rv = SOC_E_UNAVAIL;
   6198     switch(type) {
   6199     case SOC_PHY_CONTROL_PREEMPHASIS:
   6200         /* fall through */
   6201     case SOC_PHY_CONTROL_PREEMPHASIS_LANE0:
   6202         /* fall through */
   6203     case SOC_PHY_CONTROL_PREEMPHASIS_LANE1:
   6204         /* fall through */
   6205     case SOC_PHY_CONTROL_PREEMPHASIS_LANE2:
   6206         /* fall through */
   6207     case SOC_PHY_CONTROL_PREEMPHASIS_LANE3:
   6208 		rv = _phy_84328_control_preemphasis_get(unit, port, type,
   6209 												(pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   6210 												PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE, 
   6211 												value);
   6212 		break;
   6213     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   6214         /* fall through */
   6215     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0:
   6216         /* fall through */
   6217     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1:
   6218         /* fall through */
   6219     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2:
   6220         /* fall through */
   6221     case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3:
   6222         /* fall through */
   6223     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   6224         /* fall through */
   6225     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0:
   6226         /* fall through */
   6227     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1:
   6228         /* fall through */
   6229     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2:
   6230         /* fall through */
   6231     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3:
   6232         rv = _phy_84328_control_tx_driver_get(unit, port, type,
   6233 											  (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   6234 											  PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE, 
   6235 											  value);
   6236         break;
   6237     case SOC_PHY_CONTROL_EDC_MODE:
   6238         rv = _phy_84328_control_edc_mode_get(unit,port,value);
   6239         break;
   6240     case SOC_PHY_CONTROL_CLOCK_ENABLE:
   6241         rv = SOC_E_NONE;
   6242         break;
   6243     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   6244         rv = _phy_84328_control_prbs_polynomial_get(unit, port, value);
   6245         break;
   6246     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   6247         rv = _phy_84328_control_prbs_tx_invert_data_get(unit, port, value);
   6248         break;
   6249     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   6250         /* fall through */
   6251     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   6252         rv = _phy_84328_control_prbs_enable_get(unit, port, value);
   6253         break;
   6254     case SOC_PHY_CONTROL_PRBS_RX_STATUS:
   6255         rv = _phy_84328_control_prbs_rx_status_get(unit, port,
   6256                 (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   6257                 PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE, 
   6258                 value);
   6259         break;
   6260     case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
   6261         break;
   6262     case SOC_PHY_CONTROL_PORT_PRIMARY:
   6263         SOC_IF_ERROR_RETURN
   6264             (soc_phyctrl_primary_get(unit, port, &primary));
   6265         *value = (uint32) primary;
   6266 		rv = SOC_E_NONE;
   6267         break;
   6268     case SOC_PHY_CONTROL_PORT_OFFSET:
   6269         SOC_IF_ERROR_RETURN
   6270             (soc_phyctrl_offset_get(unit, port, &offset));
   6271         *value = (uint32) offset;
   6272 		rv = SOC_E_NONE;
   6273         break;
   6274     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   6275         rv = _phy_84328_remote_loopback_get(unit, port, intf, value);
   6276         break;
   6277     case SOC_PHY_CONTROL_SOFTWARE_RX_LOS:
   6278         rv = _phy_84328_rx_los_control_get(unit, port, value);
   6279 		break;
   6280 	case SOC_PHY_CONTROL_DUMP:
   6281 		*value = 0;
   6282 		rv = SOC_E_NONE;
   6283 		break;
   6284 	case SOC_PHY_CONTROL_DRIVER_SUPPLY:
   6285 		rv = _phy_84328_control_driver_supply_get(unit, port,
   6286 												  (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   6287 												  PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE, 
   6288 												  value);
   6289 		break;
   6290 	case SOC_PHY_CONTROL_RX_SEQ_DONE:
   6291 		rv = _phy_84328_rx_seq_done_get(unit, port, 
   6292 										(pc->flags & PHYCTRL_SYS_SIDE_CTRL) ?
   6293 										PHY84328_INTF_SIDE_SYS : PHY84328_INTF_SIDE_LINE, 
   6294 										value);
   6295 		break;
   6296     case SOC_PHY_CONTROL_MOD_AUTO_DETECT_ENABLE:
   6297         rv = _phy_84328_mod_auto_detect_get(unit, port, value);
   6298         break;
   6299     case SOC_PHY_CONTROL_CL72_STATUS:
   6300         rv = _phy_84328_force_cl72_status(unit, port, value);
   6301         break;
   6302     case SOC_PHY_CONTROL_PCS_MODE:
   6303         {
   6304             phy_ctrl_t *int_pc;
   6305             int_pc = INT_PHY_SW_STATE(unit, port);
   6306             if (int_pc) {
   6307                 rv = PHY_CONTROL_GET(int_pc->pd, unit, port, type, value);
   6308             } else {
   6309                 rv = SOC_E_INTERNAL;
   6310             }
   6311         }
   6312         break;
   6313 
   6314     default:
   6315         rv = SOC_E_UNAVAIL;
   6316         break;
   6317     }
   6318 
   6319     if (intf == PHY_DIAG_INTF_SYS) {
   6320 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   6321         pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL ;
   6322     }
   6323     return rv;
   6324 }
   6325 STATIC int
   6326 phy_84328_control_port_get(int unit, soc_port_t port,
   6327                      soc_phy_control_t type, uint32 *value)
   6328 {
   6329     int intf;
   6330 
   6331     intf = PHY_DIAG_INTF_LINE;
   6332     SOC_IF_ERROR_RETURN
   6333         (_phy_84328_control_get(unit, port, intf, PHY_DIAG_LN_DFLT, type, value));
   6334 
   6335     return SOC_E_NONE;
   6336 }
   6337 
   6338 /* Returns whether interface has cl72 */
   6339 STATIC int
   6340 _phy_84328_cl72_en(int unit, soc_port_t port, phy84328_intf_side_t side)
   6341 {
   6342 	int cl72 = FALSE;
   6343     phy_ctrl_t *pc;
   6344     phy84328_intf_cfg_t *ifc;
   6345 
   6346     pc = EXT_PHY_SW_STATE(unit, port);
   6347     ifc = (side == PHY84328_INTF_SIDE_LINE) ? &(LINE_INTF(pc)) : &(SYS_INTF(pc));
   6348     switch (ifc->type) {
   6349     case SOC_PORT_IF_KR:
   6350     case SOC_PORT_IF_KR4:
   6351         cl72 = TRUE;
   6352         break;
   6353     case SOC_PORT_IF_CR4:
   6354         /* System side is always DAC */
   6355         if (side == PHY84328_INTF_SIDE_SYS) {
   6356             cl72 = FALSE;
   6357         } else {
   6358             /* If no AN, it's really DAC */
   6359             cl72 = AN_EN(pc);
   6360         }
   6361         break;
   6362     default:
   6363         cl72 = FALSE;
   6364         break;
   6365     }
   6366     return cl72;
   6367 }
   6368 
   6369 /* dsc values */
   6370 struct phy84328_dsc_cb {
   6371     int tx_pre_cursor;
   6372     int tx_main;
   6373     int tx_post_cursor;
   6374     char *vga_bias_reduced;
   6375     int postc_metric;
   6376     int pf_ctrl;
   6377     int vga_sum;
   6378     int dfe1_bin;
   6379     int dfe2_bin;
   6380     int dfe3_bin;
   6381     int dfe4_bin;
   6382     int dfe5_bin;
   6383     int integ_reg;
   6384     int integ_reg_xfer;
   6385     int clk90_offset;
   6386     int slicer_target;
   6387     int offset_pe;
   6388     int offset_ze;
   6389     int offset_me;
   6390     int offset_po;
   6391     int offset_zo;
   6392     int offset_mo;
   6393 };
   6394 
   6395 STATIC int
   6396 _phy_84328_diag_dsc(int unit, soc_port_t port, int intf, int lane)
   6397 {
   6398     int	 i, reg, lanes, regval;
   6399     uint16 data16;
   6400     phy_ctrl_t *pc;
   6401 	phy84328_intf_side_t side;
   6402 	struct phy84328_dsc_cb *dsc_cbp;
   6403 	struct phy84328_dsc_cb dsc_cb[PHY84328_NUM_LANES];
   6404 
   6405     pc = EXT_PHY_SW_STATE(unit, port);
   6406 
   6407 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   6408         lanes = PHY84328_NUM_LANES ;
   6409     } 
   6410     else {
   6411         lanes = 1;
   6412     }
   6413 	side =  (intf == PHY_DIAG_INTF_LINE) ? PHY84328_INTF_SIDE_LINE :
   6414 		PHY84328_INTF_SIDE_SYS;
   6415     sal_memset((char *)&dsc_cb[0], 0, (sizeof(dsc_cb)));
   6416 
   6417 	PHY_84328_MICRO_PAUSE(unit, port, "dsc");
   6418 	_phy_84328_intf_side_regs_select(unit, port, side);
   6419     for (i = 0; i < lanes; i++) {
   6420 		if (PHY84328_SINGLE_PORT_MODE(pc)) {
   6421             /* Select the lane and side to access */
   6422             SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, i));
   6423         }
   6424         dsc_cbp = &(dsc_cb[i]);
   6425 
   6426 		/* tx drive pre, main, post cursor taps are read differently for cl72 */
   6427 		if (_phy_84328_cl72_en(unit, port, side)) {
   6428 			uint16 saved_reg;
   6429 
   6430 			/* 1.c063[15:14]=1 to get port cl72 tap values in 1.c060 */
   6431 			reg = 0xc063;
   6432 			SOC_IF_ERROR_RETURN
   6433 				(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6434 			saved_reg = data16;
   6435 			regval = 0x4000 | (data16 & 0x3fff);
   6436 			SOC_IF_ERROR_RETURN
   6437 				(WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, data16));
   6438 			reg = 0xc060;
   6439 			SOC_IF_ERROR_RETURN
   6440 				(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6441 
   6442 			/* tx_pre_cursor */
   6443 			regval = data16 & 0xf;
   6444 			dsc_cbp->tx_pre_cursor = regval;
   6445 
   6446 			/* tx_post_cursor */
   6447 			regval = (data16 >> 10) & 0x1f;
   6448 			dsc_cbp->tx_post_cursor = regval;
   6449 
   6450 			/* tx_main */
   6451 			regval = (data16 >> 4) & 0x3f;
   6452 			dsc_cbp->tx_main = regval;
   6453 
   6454 			/* Restore 1.c063 to original values used to access 1.c060 */
   6455 			SOC_IF_ERROR_RETURN
   6456 				(WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, saved_reg));
   6457 		} else {
   6458 			reg = 0xc067;
   6459 			SOC_IF_ERROR_RETURN
   6460 				(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6461 
   6462 			/* tx_pre_cursor */
   6463 			regval = data16 & 0x7;
   6464 			dsc_cbp->tx_pre_cursor = regval;
   6465 
   6466 			/* tx_post_cursor */
   6467 			regval = (data16 >> 4) & 0x1F;
   6468 			dsc_cbp->tx_post_cursor = regval;
   6469 
   6470 			/* tx_main */
   6471 			reg = 0xc066;
   6472 			SOC_IF_ERROR_RETURN
   6473 				(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6474 			regval = (data16 >> 11) & 0x1F;
   6475 			dsc_cbp->tx_main = regval;
   6476 		}
   6477 
   6478         /* vga_bias_reduced */ 
   6479         reg = 0xc0BD;
   6480         SOC_IF_ERROR_RETURN
   6481             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6482         regval = data16 & (1 << 4);
   6483         if (regval) {
   6484             dsc_cbp->vga_bias_reduced = "88%";
   6485         } else {
   6486             dsc_cbp->vga_bias_reduced = "100%";
   6487         }
   6488 
   6489         /* post2 tap - c068[10:8] */
   6490         reg = 0xc068;
   6491         SOC_IF_ERROR_RETURN
   6492             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6493         regval = (data16 >> 8) & 0x7;
   6494         dsc_cbp->postc_metric = regval;
   6495 
   6496 
   6497         /* pf DSC_3_ADDR=0xc220 + 11 */
   6498         reg = 0xc220 + 11;
   6499         SOC_IF_ERROR_RETURN
   6500             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6501         regval = (data16 & 0xf);
   6502         dsc_cbp->pf_ctrl = regval;
   6503 
   6504         /* vga sum DSC_3_ADDR=0xc220 + 5 */
   6505         reg = 0xc220 + 5;
   6506         SOC_IF_ERROR_RETURN
   6507             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6508         regval = (data16 & 63);
   6509         dsc_cbp->vga_sum = regval;
   6510 
   6511         /* dfe1_bin DSC_3_ADDR=0xc220 + 5 */
   6512 		reg = 0xc220 + 5;
   6513         SOC_IF_ERROR_RETURN
   6514             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6515         regval = data16;
   6516         regval /= 64; 
   6517         regval &= 63;
   6518         dsc_cbp->dfe1_bin = regval;
   6519 
   6520         /* dfe2_bin  DSC_3_ADDR=0xc220 + 6 */
   6521         reg = 0xc220 + 6;
   6522         SOC_IF_ERROR_RETURN
   6523             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6524         regval = data16;
   6525         regval &= 63;
   6526         if (regval >= 32) {
   6527             regval -=64;
   6528         }
   6529         dsc_cbp->dfe2_bin = regval;
   6530         
   6531         /* dfe3_bin DSC_3_ADDR=0xc220 + 6 */
   6532         reg = 0xc220 + 6;
   6533         SOC_IF_ERROR_RETURN
   6534             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6535         regval = data16;
   6536         regval /= 64;
   6537         regval &= 63;
   6538         if (regval >= 32) {
   6539             regval -=64;
   6540         }
   6541         dsc_cbp->dfe3_bin = regval;
   6542         
   6543         /* dfe4_bin DSC_3_ADDR=0xc220 + 7 */
   6544         reg = 0xc220 + 7;
   6545         SOC_IF_ERROR_RETURN
   6546             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6547         regval = data16;
   6548         regval &= 31;
   6549         if (regval >= 16) {
   6550             regval -=32;
   6551         }
   6552         dsc_cbp->dfe4_bin = regval;
   6553   
   6554         /* dfe5_bin DSC_3_ADDR=0xc220 + 7  */
   6555         reg = 0xc220 + 7;
   6556         SOC_IF_ERROR_RETURN
   6557             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6558         regval = data16;
   6559         regval /= 32;
   6560         regval &= 31;
   6561         if (regval >= 16) {
   6562             regval -=32;
   6563         }
   6564         dsc_cbp->dfe5_bin = regval;
   6565 
   6566         /* integ_reg(lane) = rd22_integ_reg (phy, lane) DSC_3_ADDR=0xc220  */
   6567         reg = 0xc220;
   6568         SOC_IF_ERROR_RETURN
   6569             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6570         regval = data16;
   6571         regval &= 65535;
   6572         if (regval >= 32768) {
   6573             regval -=65536;
   6574         }
   6575         regval /= 84;
   6576         dsc_cbp->integ_reg = regval;
   6577 
   6578         /* integ_reg_xfer(lane) = rd22_integ_reg_xfer (phy, lane)   */
   6579         reg = 0xc221;
   6580         SOC_IF_ERROR_RETURN
   6581             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6582         regval = data16;
   6583         regval &= 65535;
   6584         if (regval >= 32768) {
   6585             regval -=65536;
   6586         }
   6587         dsc_cbp->integ_reg_xfer = regval;
   6588 
   6589         /* clk90_offset(lane) = rd22_clk90_phase_offset (phy, lane)   */
   6590         reg = 0xc223;
   6591         SOC_IF_ERROR_RETURN
   6592             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6593         regval = data16;
   6594         regval /= 128;
   6595         regval &= 127;
   6596         dsc_cbp->clk90_offset = regval;
   6597 
   6598         /* slicer_target(lane) = ((25*rd22_rx_thresh_sel (phy, lane)) + 125)   */
   6599         reg = 0xc21c;
   6600         SOC_IF_ERROR_RETURN
   6601             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6602         regval = data16;
   6603         regval /= 32;
   6604         regval &= 3;
   6605         dsc_cbp->slicer_target = regval * 25 + 125;
   6606 
   6607         /* offset_pe(lane) = rd22_slicer_offset_pe (phy, lane)   */
   6608         reg = 0xc22c;
   6609         SOC_IF_ERROR_RETURN
   6610             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6611         regval = data16;
   6612         regval &= 63;
   6613         if (regval >= 32) {
   6614             regval -=64;
   6615         }
   6616         dsc_cbp->offset_pe = regval;
   6617 
   6618         /* offset_ze(lane) = rd22_slicer_offset_ze (phy, lane)   */
   6619         reg = 0xc22d;
   6620         SOC_IF_ERROR_RETURN
   6621             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6622         regval = data16;
   6623         regval &= 63;
   6624         if (regval >= 32) {
   6625             regval -=64;
   6626         }
   6627         dsc_cbp->offset_ze = regval;
   6628 
   6629         /* offset_me(lane) = rd22_slicer_offset_me (phy, lane)   */
   6630         reg = 0xc22e;
   6631         SOC_IF_ERROR_RETURN
   6632             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6633         regval = data16;
   6634         regval &= 63;
   6635         if (regval >= 32) {
   6636             regval -=64;
   6637         }
   6638         dsc_cbp->offset_me = regval;
   6639 
   6640         /* offset_po(lane) = rd22_slicer_offset_po (phy, lane) */
   6641         reg = 0xc22c;
   6642         SOC_IF_ERROR_RETURN
   6643             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6644         regval = data16;
   6645         regval /= 64;
   6646         regval &= 63;
   6647         if (regval >= 32) {
   6648             regval -=64;
   6649         }
   6650         dsc_cbp->offset_po = regval;
   6651 
   6652         /* offset_zo(lane) = rd22_slicer_offset_zo (phy, lane) */
   6653         reg = 0xc22d;
   6654         SOC_IF_ERROR_RETURN
   6655             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6656         regval = data16;
   6657         regval /= 64;
   6658         regval &= 63;
   6659         if (regval >= 32) {
   6660             regval -=64;
   6661         }
   6662         dsc_cbp->offset_zo = regval;
   6663 
   6664         /* offset_mo(lane) = rd22_slicer_offset_mo (phy, lane) */
   6665         reg = 0xc22e;
   6666         SOC_IF_ERROR_RETURN
   6667             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data16));
   6668         regval = data16;
   6669         regval /= 64;
   6670         regval &= 63;
   6671         if (regval >= 32) {
   6672             regval -=64;
   6673         }
   6674         dsc_cbp->offset_mo = regval;
   6675     }
   6676 	/* Restore to default single port register access */
   6677 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   6678 		SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, PHY84328_ALL_LANES));
   6679 	}
   6680 	_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   6681 	PHY_84328_MICRO_RESUME(unit, port);
   6682 
   6683     /* display */
   6684     LOG_CLI((BSL_META_U(unit,
   6685                         "\nDSC parameters for port %d\n"), port));
   6686 
   6687     LOG_CLI((BSL_META_U(unit,
   6688                         "LN  PPM PPM_XFR clk90_ofs PF SL_TRGT VGA BIAS DFE1 DFE2 "
   6689                         "DFE3 DFE4 DFE5 PREC MAIN POSTC MTRC "
   6690                         "PE   ZE   ME  PO  ZO  MO\n")));
   6691     for (i = 0; i < lanes; i++) {
   6692         dsc_cbp = &(dsc_cb[i]);
   6693         LOG_CLI((BSL_META_U(unit,
   6694                             "%02d %04d %07d %09d %04d %04d %04d %4s %04d %04d %04d %04d "
   6695                             "%04d %04d %04d %04d  %04d %04d %04d %2d %3d %3d %2d\n"),
   6696                  i, dsc_cbp->integ_reg,dsc_cbp->integ_reg_xfer,
   6697                  dsc_cbp->clk90_offset,
   6698                  dsc_cbp->pf_ctrl, dsc_cbp->slicer_target,
   6699                  dsc_cbp->vga_sum, dsc_cbp->vga_bias_reduced,
   6700                  dsc_cbp->dfe1_bin, dsc_cbp->dfe2_bin,
   6701                  dsc_cbp->dfe3_bin, dsc_cbp->dfe4_bin,
   6702                  dsc_cbp->dfe5_bin, dsc_cbp->tx_pre_cursor,
   6703                  dsc_cbp->tx_main,dsc_cbp->tx_post_cursor,
   6704                  dsc_cbp->postc_metric, dsc_cbp->offset_pe,
   6705                  dsc_cbp->offset_ze,dsc_cbp->offset_me,
   6706                  dsc_cbp->offset_po, dsc_cbp->offset_zo, dsc_cbp->offset_mo));
   6707 
   6708     }
   6709 
   6710     return SOC_E_NONE;
   6711 }
   6712 
   6713 
   6714 STATIC int
   6715 _phy_84328_diag_eyescan_uc_ready(int unit, soc_port_t port)
   6716 {
   6717 	int rv = SOC_E_NONE;
   6718 	uint16 data;
   6719 	soc_timeout_t to;
   6720 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6721 
   6722 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6723 		LOG_CLI((BSL_META_U(unit,
   6724                                     "    _phy_84328_diag_eyescan_uc_ready\n")));
   6725 	}
   6726 
   6727 	/* Wait for uC ready */
   6728 	soc_timeout_init(&to, 250000, 0);
   6729 	while (!soc_timeout_check(&to)) {
   6730 		rv = READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL, &data);
   6731 		if (rv != SOC_E_NONE) {
   6732 			break;
   6733 		}
   6734 		if (data & PHY84328_DEV1_UC_CTRL_READY_FOR_CMD_MASK) {
   6735 			break;
   6736 		}
   6737 	}
   6738 
   6739 	if ((rv == SOC_E_NONE) &&
   6740 		(data & PHY84328_DEV1_UC_CTRL_READY_FOR_CMD_MASK)) {
   6741 		rv = SOC_E_NONE;
   6742 	} else {
   6743 		LOG_ERROR(BSL_LS_SOC_PHY,
   6744                           (BSL_META_U(unit,
   6745                                       "84328 EYE: uController not ready pass 1!: u=%d, p=%d "
   6746                                       "uc_ctrl(1.%04x)=%04x\n"), unit, port, 
   6747                            PHY84328_SYS_DEV1_UC_CTRL, data));
   6748 		rv = SOC_E_TIMEOUT;
   6749 	}
   6750 
   6751     return rv;
   6752 }
   6753 
   6754 STATIC int
   6755 _phy_84328_diag_eyescan_offset(int unit, soc_port_t port, int16 supp_data, int req)
   6756 {
   6757 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6758 
   6759 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6760 		LOG_CLI((BSL_META_U(unit,
   6761                                     "   _phy_84328_diag_eyescan_offset\n")));
   6762 	}
   6763 
   6764     /* offset 1.c20e */
   6765     SOC_IF_ERROR_RETURN(
   6766 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL,
   6767 										supp_data << PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_SHIFT,
   6768 										PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_MASK));
   6769     SOC_IF_ERROR_RETURN(
   6770 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL,
   6771 										0, PHY84328_SYS_DEV1_UC_CTRL_READY_FOR_CMD_MASK));
   6772     SOC_IF_ERROR_RETURN(
   6773 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL,
   6774 										0, PHY84328_SYS_DEV1_UC_CTRL_ERROR_FOUND_MASK));
   6775     SOC_IF_ERROR_RETURN(
   6776 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL,
   6777 										0, PHY84328_SYS_DEV1_UC_CTRL_CMD_INFO_MASK));
   6778     SOC_IF_ERROR_RETURN(
   6779 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL,
   6780 										(req | 
   6781 										 (supp_data << PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_SHIFT)),
   6782 										PHY84328_SYS_DEV1_UC_CTRL_GP_UC_REQ_MASK |
   6783 										PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_MASK));
   6784 
   6785     /* wait for uC ready for command */
   6786 	return _phy_84328_diag_eyescan_uc_ready(unit, port);
   6787 }
   6788 
   6789 STATIC uint16
   6790 _phy_84328_diag_eyescan_diag_ctrl_get(int unit, soc_port_t port)
   6791 {
   6792 	uint16 data;
   6793 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6794 
   6795 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   6796 													  PHY84328_SYS_DEV1_DSC_DIAG_CTRL0,
   6797 													  &data));
   6798 	return data;
   6799 }
   6800 
   6801 STATIC int
   6802 _phy_84328_diag_eyescan_livelink_en(int unit, soc_port_t port, int en)
   6803 {
   6804 	uint16 data, mask;
   6805 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6806 
   6807 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6808 		LOG_CLI((BSL_META_U(unit,
   6809                                     "_phy_84328_diag_eyescan_livelink_en: en=%d\n"), en));
   6810 	}
   6811 
   6812 	data = 0x2;
   6813 	mask = data;
   6814 	SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   6815 														PHY84328_SYS_DEV1_DSC_DIAG_CTRL0,
   6816 														data, mask));
   6817 
   6818 	data = en ? PHY84328_SYS_DEV1_DSC_DIAG_CTRL0_DIAGNOSTICS_EN_BITS : 0;
   6819 	mask = PHY84328_SYS_DEV1_DSC_DIAG_CTRL0_DIAGNOSTICS_EN_MASK;
   6820 
   6821 	SOC_IF_ERROR_RETURN(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   6822 														PHY84328_SYS_DEV1_DSC_DIAG_CTRL0,
   6823 														data, mask));
   6824 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6825 		LOG_CLI((BSL_META_U(unit,
   6826                                     "_phy_84328_diag_eyescan_livelink_en: en=%d [%04x]\n"), 
   6827                          en, _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   6828 	}
   6829 
   6830     return SOC_E_NONE;
   6831 }
   6832 
   6833 STATIC int
   6834 _phy_84328_diag_eyescan_livelink_clear(int unit, soc_port_t port, int unused)
   6835 {
   6836 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6837 
   6838 	SOC_IF_ERROR_RETURN(_phy_84328_diag_eyescan_offset(unit, port,  0x3, 0x6));
   6839 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6840 		LOG_CLI((BSL_META_U(unit,
   6841                                     "_phy_84328_diag_eyescan_livelink_clear: [%04x]\n"), 
   6842                          _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   6843 	}
   6844     return SOC_E_NONE;
   6845 }
   6846 
   6847 STATIC int
   6848 _phy_84328_diag_eyescan_livelink_start(int unit, soc_port_t port, int unused)
   6849 {
   6850 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6851 
   6852 	SOC_IF_ERROR_RETURN(_phy_84328_diag_eyescan_offset(unit, port,  0x0, 0x6));
   6853 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6854 		LOG_CLI((BSL_META_U(unit,
   6855                                     "_phy_84328_diag_eyescan_livelink_start: [%04x]\n"), 
   6856                          _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   6857 	}
   6858     return SOC_E_NONE;
   6859 }
   6860 
   6861 STATIC int
   6862 _phy_84328_diag_eyescan_livelink_stop(int unit, soc_port_t port, int unused)
   6863 {
   6864 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6865 
   6866 	SOC_IF_ERROR_RETURN(_phy_84328_diag_eyescan_offset(unit, port, 0x1, 0x6));
   6867 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6868 		LOG_CLI((BSL_META_U(unit,
   6869                                     "_phy_84328_diag_eyescan_livelink_stop: [%04x]\n"), 
   6870                          _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   6871 	} 
   6872     return SOC_E_NONE;
   6873 }
   6874 
   6875 STATIC int
   6876 _phy_84328_diag_eyescan_livelink_read(int unit, soc_port_t port, int *err_counter)
   6877 {
   6878 	int i;
   6879 	uint16 data;
   6880 	uint32 counter;
   6881 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6882 
   6883 	counter = 0;
   6884 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6885 		LOG_CLI((BSL_META_U(unit,
   6886                                     "_phy_84328_diag_eyescan_livelink_read: ")));
   6887 	}
   6888 	for (i = 0; i < 4; i++) {
   6889 		SOC_IF_ERROR_RETURN(_phy_84328_diag_eyescan_offset(unit, port, 0x2, 0x6));
   6890 
   6891 		/* read back the maximum offset */
   6892 		SOC_IF_ERROR_RETURN(
   6893 			READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL, &data));
   6894 		data &= PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_MASK;
   6895 		data >>= PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_SHIFT;
   6896 		if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6897 			LOG_CLI((BSL_META_U(unit,
   6898                                             "[%d]=%d "), i, data));
   6899 		}
   6900 		counter += (data << (8 * i));
   6901 	} 
   6902 	*err_counter = counter;
   6903 
   6904 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6905 		LOG_CLI((BSL_META_U(unit,
   6906                                     "\n_phy_84328_diag_eyescan_livelink_read: err_counter=%d\n"),
   6907                          *err_counter));
   6908 	}
   6909     return SOC_E_NONE;
   6910 }
   6911 
   6912 STATIC int
   6913 _phy_84328_diag_eyescan_init_voffset_get(int unit, soc_port_t port, int *voffset)
   6914 {
   6915     uint16 data;
   6916 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6917 
   6918 	*voffset = 0;
   6919 	/* 1.c21c[15:10] */
   6920 	SOC_IF_ERROR_RETURN(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   6921 													  PHY84328_DEV1_DSC_ANA_CTRL3,
   6922 													  &data));
   6923     *voffset = (data & PHY84328_DEV1_DSC_ANA_CTRL3_RSVD_FOR_ECO_MASK) >>
   6924 		PHY84328_DEV1_DSC_ANA_CTRL3_RSVD_FOR_ECO_SHIFT;
   6925 
   6926 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6927 		LOG_CLI((BSL_META_U(unit,
   6928                                     "_phy_84328_diag_eyescan_init_voffset_get: "
   6929                                     "voffset=%x [%04x]\n"), 
   6930                          *voffset,
   6931                          _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   6932 	}
   6933     return SOC_E_NONE;
   6934 }
   6935 
   6936 STATIC int
   6937 _phy_84328_diag_eyescan_hoffset_set(int unit, soc_port_t port, int *hoffset)
   6938 {
   6939 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6940 
   6941 	SOC_IF_ERROR_RETURN(_phy_84328_diag_eyescan_offset(unit, port, *hoffset, 0x2));
   6942 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6943 		LOG_CLI((BSL_META_U(unit,
   6944                                     "_phy_84328_diag_eyescan_hoffset_set: hoffset=%x [%04x]\n"), 
   6945                          *hoffset, _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   6946 	}
   6947     return SOC_E_NONE;
   6948 }
   6949 
   6950 STATIC int
   6951 _phy_84328_diag_eyescan_voffset_set(int unit, soc_port_t port, int *voffset)
   6952 {
   6953 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6954 
   6955 	SOC_IF_ERROR_RETURN(_phy_84328_diag_eyescan_offset(unit, port, *voffset, 0x3));
   6956 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6957 		LOG_CLI((BSL_META_U(unit,
   6958                                     "_phy_84328_diag_eyescan_voffset_set: voffset=%x [%04x]\n"), 
   6959                          *voffset, _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   6960 	}
   6961     return SOC_E_NONE;
   6962 }
   6963 
   6964 STATIC int
   6965 _phy_84328_diag_eyescan_max_left_hoffset_get(int unit, soc_port_t port, int *left_hoffset)
   6966 {
   6967     uint16 data;
   6968 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6969 
   6970 	SOC_IF_ERROR_RETURN(_phy_84328_diag_eyescan_offset(unit, port, 127, 0x2));
   6971     /* read back the maximum offset */
   6972     SOC_IF_ERROR_RETURN(
   6973 		READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL, &data));
   6974     data &= PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_MASK;
   6975     data >>= PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_SHIFT;
   6976 	*left_hoffset = -data;
   6977 
   6978 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   6979 		LOG_CLI((BSL_META_U(unit,
   6980                                     "_phy_84328_diag_eyescan_max_left_hoffset_get: "
   6981                                     "max_left_hoffset=%d [%04x]\n"), 
   6982                          *left_hoffset,
   6983                          _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   6984 	}
   6985 
   6986     return SOC_E_NONE;
   6987 }
   6988 
   6989 STATIC int
   6990 _phy_84328_diag_eyescan_max_right_hoffset_get(int unit, soc_port_t port, int *right_hoffset)
   6991 {
   6992     uint16 data;
   6993 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   6994 
   6995 	SOC_IF_ERROR_RETURN(_phy_84328_diag_eyescan_offset(unit, port, -128, 0x2));
   6996     /* read back the right offset */
   6997     SOC_IF_ERROR_RETURN(
   6998 		READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL, &data));
   6999     data &= PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_MASK;
   7000     data >>= PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_SHIFT;
   7001 	*right_hoffset = data;
   7002 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   7003 		LOG_CLI((BSL_META_U(unit,
   7004                                     "_phy_84328_diag_eyescan_max_right_hoffset_get: "
   7005                                     "max right hoffset=%d [%04x]\n"), 
   7006                          *right_hoffset,
   7007                          _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   7008 	}
   7009 	return SOC_E_NONE;
   7010 }
   7011 
   7012 STATIC int
   7013 _phy_84328_diag_eyescan_min_voffset_get(int unit, soc_port_t port, int *min_voffset)
   7014 {
   7015     uint16 data;
   7016 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   7017 
   7018 	SOC_IF_ERROR_RETURN(_phy_84328_diag_eyescan_offset(unit, port, -128, 0x3));
   7019 
   7020     /* read back the min offset */
   7021     SOC_IF_ERROR_RETURN(
   7022 		READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL, &data));
   7023     data &= PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_MASK;
   7024     data >>= PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_SHIFT;
   7025 	*min_voffset = data - 256;
   7026 
   7027 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   7028 		LOG_CLI((BSL_META_U(unit,
   7029                                     "_phy_84328_diag_eyescan_min_voffset_get: "
   7030                                     "min_voffset=%d [%04x]\n"), 
   7031                          *min_voffset,
   7032                          _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   7033 	}
   7034 	return SOC_E_NONE;
   7035 }
   7036 
   7037 STATIC int
   7038 _phy_84328_diag_eyescan_max_voffset_get(int unit, soc_port_t port, int *max_voffset)
   7039 {
   7040     uint16 data;
   7041 	phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   7042 
   7043 	SOC_IF_ERROR_RETURN(_phy_84328_diag_eyescan_offset(unit, port, 127, 0x3));
   7044     /* read back the max voffset */
   7045     SOC_IF_ERROR_RETURN(
   7046 		READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_SYS_DEV1_UC_CTRL, &data));
   7047     data &= PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_MASK;
   7048     data >>= PHY84328_SYS_DEV1_UC_CTRL_SUPPLEMENT_INFO_SHIFT;
   7049 	*max_voffset = data;
   7050 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_EYE) {
   7051 		LOG_CLI((BSL_META_U(unit,
   7052                                     "_phy_84328_diag_eyescan_max_voffset_get: "
   7053                                     "max_voffset=%d [%04x]\n"), 
   7054                          *max_voffset,
   7055                          _phy_84328_diag_eyescan_diag_ctrl_get(unit, port)));
   7056 	}
   7057 	return SOC_E_NONE;
   7058 }
   7059 
   7060 STATIC int
   7061 _phy_84328_diag_eyescan(int unit, soc_port_t port, uint32 inst, int op_cmd, void *arg)
   7062 {
   7063     int lane;
   7064     int intf;
   7065     phy84328_intf_side_t side;
   7066 	int rv = SOC_E_NONE;
   7067     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   7068 
   7069     intf = PHY_DIAG_INST_INTF(inst);
   7070     if (intf == PHY_DIAG_INTF_SYS) {
   7071         side = PHY84328_INTF_SIDE_SYS;
   7072 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_SYS);
   7073 	} else {
   7074         side = PHY84328_INTF_SIDE_LINE;
   7075     }
   7076     lane = PHY_DIAG_INST_LN(inst);
   7077     if (PHY84328_SINGLE_PORT_MODE(pc) && (lane != 0)) {
   7078         SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, side, lane));
   7079     }
   7080 	switch (op_cmd) {
   7081 	case PHY_DIAG_CTRL_EYE_ENABLE_LIVELINK:
   7082 		rv = _phy_84328_diag_eyescan_livelink_en(unit, port, 1);
   7083 		break;
   7084 	case PHY_DIAG_CTRL_EYE_DISABLE_LIVELINK:
   7085 		rv = _phy_84328_diag_eyescan_livelink_en(unit, port, 0);
   7086 		break;
   7087 	case PHY_DIAG_CTRL_EYE_CLEAR_LIVELINK:
   7088 		rv = _phy_84328_diag_eyescan_livelink_clear(unit, port, 0);
   7089 		break;
   7090 	case PHY_DIAG_CTRL_EYE_START_LIVELINK:
   7091 		rv = _phy_84328_diag_eyescan_livelink_start(unit, port, 0);
   7092 		break;
   7093 	case PHY_DIAG_CTRL_EYE_STOP_LIVELINK:
   7094 		rv = _phy_84328_diag_eyescan_livelink_stop(unit, port, 0);
   7095 		break;
   7096 	case PHY_DIAG_CTRL_EYE_READ_LIVELINK:
   7097 		rv = _phy_84328_diag_eyescan_livelink_read(unit, port, (int *) arg);
   7098 		break;
   7099 	case PHY_DIAG_CTRL_EYE_GET_INIT_VOFFSET:
   7100 		rv = _phy_84328_diag_eyescan_init_voffset_get(unit, port, (int *)arg);
   7101 		break;
   7102 	case PHY_DIAG_CTRL_EYE_SET_HOFFSET:
   7103 		rv = _phy_84328_diag_eyescan_hoffset_set(unit, port, (int *)arg);
   7104 		break;
   7105 	case PHY_DIAG_CTRL_EYE_SET_VOFFSET:
   7106 		rv = _phy_84328_diag_eyescan_voffset_set(unit, port, (int *)arg);
   7107 		break;
   7108 	case PHY_DIAG_CTRL_EYE_GET_MAX_LEFT_HOFFSET:
   7109 		rv = _phy_84328_diag_eyescan_max_left_hoffset_get(unit, port, (int *)arg);
   7110 		break;
   7111 	case PHY_DIAG_CTRL_EYE_GET_MAX_RIGHT_HOFFSET:
   7112 		rv = _phy_84328_diag_eyescan_max_right_hoffset_get(unit, port, (int *)arg);
   7113 		break;
   7114 	case PHY_DIAG_CTRL_EYE_GET_MIN_VOFFSET:
   7115 		rv = _phy_84328_diag_eyescan_min_voffset_get(unit, port, (int *)arg);
   7116 		break;
   7117 	case PHY_DIAG_CTRL_EYE_GET_MAX_VOFFSET:
   7118 		rv = _phy_84328_diag_eyescan_max_voffset_get(unit, port, (int *)arg);
   7119 		break;
   7120 	}
   7121     if (PHY84328_SINGLE_PORT_MODE(pc) && (lane != 0)) {
   7122         SOC_IF_ERROR_RETURN(_phy_84328_channel_select(unit, port, PHY84328_INTF_SIDE_LINE,
   7123                                                       PHY84328_ALL_LANES));
   7124     }
   7125     if (intf == PHY_DIAG_INTF_SYS) {
   7126 		_phy_84328_intf_side_regs_select(unit, port, PHY84328_INTF_SIDE_LINE);
   7127 	}
   7128 
   7129 	return rv;
   7130 }
   7131 
   7132 STATIC int
   7133 _phy_84328_diag_ctrl(int unit, soc_port_t port, uint32 inst, int op_type,  int op_cmd,  
   7134 					void *arg)   
   7135 {
   7136     int lane;
   7137     int intf;
   7138 	int rv = SOC_E_NONE;
   7139 
   7140     LOG_INFO(BSL_LS_SOC_PHY,
   7141              (BSL_META_U(unit,
   7142                          "84328 diag_ctrl: u=%d p=%d ctrl=0x%x\n"), unit, port, op_cmd));
   7143    
   7144     lane = PHY_DIAG_INST_LN(inst);
   7145     intf = PHY_DIAG_INST_INTF(inst);
   7146     if (intf == PHY_DIAG_INTF_DFLT) {
   7147         intf = PHY_DIAG_INTF_LINE;
   7148     }
   7149 
   7150 	switch (op_cmd) {
   7151 	case PHY_DIAG_CTRL_DSC:
   7152 		SOC_IF_ERROR_RETURN(_phy_84328_diag_dsc(unit, port, intf, lane));
   7153 		break;
   7154 	case PHY_DIAG_CTRL_EYE_ENABLE_LIVELINK:
   7155 	case PHY_DIAG_CTRL_EYE_DISABLE_LIVELINK:
   7156 	case PHY_DIAG_CTRL_EYE_CLEAR_LIVELINK:
   7157 	case PHY_DIAG_CTRL_EYE_START_LIVELINK:
   7158 	case PHY_DIAG_CTRL_EYE_STOP_LIVELINK:
   7159 	case PHY_DIAG_CTRL_EYE_READ_LIVELINK:
   7160 	case PHY_DIAG_CTRL_EYE_GET_INIT_VOFFSET:
   7161 	case PHY_DIAG_CTRL_EYE_SET_HOFFSET:
   7162 	case PHY_DIAG_CTRL_EYE_SET_VOFFSET:
   7163 	case PHY_DIAG_CTRL_EYE_GET_MAX_LEFT_HOFFSET:
   7164 	case PHY_DIAG_CTRL_EYE_GET_MAX_RIGHT_HOFFSET:
   7165 	case PHY_DIAG_CTRL_EYE_GET_MIN_VOFFSET:
   7166 	case PHY_DIAG_CTRL_EYE_GET_MAX_VOFFSET:
   7167 		rv = _phy_84328_diag_eyescan(unit, port, inst, op_cmd, arg);
   7168 		break;
   7169 	case PHY_DIAG_CTRL_EYE_MARGIN_VEYE:
   7170 	case PHY_DIAG_CTRL_EYE_MARGIN_HEYE_LEFT:
   7171 	case PHY_DIAG_CTRL_EYE_MARGIN_HEYE_RIGHT:
   7172 		rv = SOC_E_UNAVAIL;
   7173         break;
   7174 
   7175 	default:
   7176 		if (op_type == PHY_DIAG_CTRL_SET) {
   7177 			SOC_IF_ERROR_RETURN
   7178 				(_phy_84328_control_set(unit, port, intf, lane, op_cmd, PTR_TO_INT(arg)));
   7179 		} else if (op_type == PHY_DIAG_CTRL_GET) {
   7180 			SOC_IF_ERROR_RETURN
   7181 				(_phy_84328_control_get(unit, port, intf, lane, op_cmd, (uint32 *)arg));
   7182 		} else {
   7183 			LOG_INFO(BSL_LS_SOC_PHY,
   7184                                  (BSL_META_U(unit,
   7185                                              "84328 diag_ctrl bad operation: u=%d p=%d ctrl=0x%x\n"), 
   7186                                              unit, port, op_cmd));
   7187 			rv = SOC_E_UNAVAIL;
   7188 		}
   7189 		break;
   7190 	}
   7191 
   7192     return rv;
   7193 }
   7194 
   7195 /*
   7196  * Return whether AN is enabled or forced with internal SerDes on the system side
   7197  */
   7198 STATIC int
   7199 _phy_84328_intf_sys_forced(int unit, soc_port_t port, soc_port_if_t intf_type)
   7200 {
   7201     int rv;
   7202     phy_ctrl_t *pc;
   7203 
   7204     pc = EXT_PHY_SW_STATE(unit, port);
   7205 
   7206     switch (intf_type) {
   7207     case SOC_PORT_IF_SR:
   7208     case SOC_PORT_IF_SR4:
   7209     case SOC_PORT_IF_LR:
   7210     case SOC_PORT_IF_LR4:
   7211     case SOC_PORT_IF_XLAUI:
   7212     case SOC_PORT_IF_XFI:
   7213     case SOC_PORT_IF_SFI:
   7214     case SOC_PORT_IF_CR:
   7215     case SOC_PORT_IF_CR4:
   7216     case SOC_PORT_IF_ZR:
   7217     case SOC_PORT_IF_CAUI:
   7218 		rv = TRUE;
   7219 		break;
   7220     case SOC_PORT_IF_GMII:
   7221 		rv = FALSE;
   7222 		break;
   7223 	case SOC_PORT_IF_KR:
   7224 	case SOC_PORT_IF_KR4:
   7225 		rv = SYS_FORCED_CL72(pc) ? TRUE : FALSE;
   7226 		break;
   7227     default:
   7228         rv = FALSE;
   7229     }
   7230     return rv;
   7231 }
   7232 
   7233 STATIC int
   7234 _phy_84328_intf_line_forced(int unit, soc_port_t port, soc_port_if_t intf_type)
   7235 {
   7236 	int rv;
   7237 
   7238     switch (intf_type) {
   7239     case SOC_PORT_IF_SR:
   7240     case SOC_PORT_IF_SR4:
   7241     case SOC_PORT_IF_LR:
   7242     case SOC_PORT_IF_ZR:
   7243     case SOC_PORT_IF_LR4:
   7244     case SOC_PORT_IF_XLAUI:
   7245     case SOC_PORT_IF_XFI:
   7246     case SOC_PORT_IF_SFI:
   7247     case SOC_PORT_IF_CR:
   7248     case SOC_PORT_IF_CAUI:
   7249 		rv = TRUE;
   7250 		break;
   7251 	default:
   7252 		rv = FALSE;
   7253 	}
   7254 	return rv;
   7255 }
   7256 
   7257 STATIC int
   7258 __phy_84328_speed_set(int unit, soc_port_t port, int speed)
   7259 {
   7260 	int rv = SOC_E_NONE;
   7261 	int cur_an, cur_an_done;
   7262     int cur_speed = 0;
   7263     uint32  cur_fw_mode = 0;
   7264 	soc_port_if_t cur_type, new_type;
   7265     phy_ctrl_t  *pc, *int_pc;
   7266 	phy84328_intf_cfg_t  *line_intf;
   7267 	phy84328_intf_cfg_t  *sys_intf;
   7268 
   7269     pc = EXT_PHY_SW_STATE(unit, port);
   7270     int_pc = INT_PHY_SW_STATE(unit, port);
   7271 	line_intf = &(LINE_INTF(pc));
   7272 	sys_intf = &(SYS_INTF(pc));
   7273 
   7274 	line_intf->speed = speed;
   7275 	sys_intf->speed = speed;
   7276 
   7277     /* Make sure datapath is correct one for this speed */
   7278 	SOC_IF_ERROR_RETURN(_phy_84328_data_path_check(unit, port));
   7279 
   7280 	if (int_pc != NULL) {
   7281 		if ((sys_intf->type == SOC_PORT_IF_GMII) || (sys_intf->type == SOC_PORT_IF_SGMII)) {
   7282 			SOC_IF_ERROR_RETURN(PHY_SPEED_SET(int_pc->pd, unit, port, sys_intf->speed));
   7283 		} else if (_phy_84328_intf_sys_forced(unit, port, sys_intf->type) ) {
   7284 			/*
   7285 			 * When setting system side 40G DAC/XLAUI-DFE, tell internal SerDes to match
   7286 			 * with XLAUI.
   7287 			 *
   7288 			 * If flexports, the internal SerDes may be out of sync until it gets a chance 
   7289 			 *  to convert the port, so these operations may be best effort.
   7290 			 */
   7291 			new_type = (sys_intf->type == SOC_PORT_IF_CR4) ? SOC_PORT_IF_XLAUI : sys_intf->type;
   7292 			SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET(int_pc->pd, unit, port, &cur_type));
   7293 			if (cur_type != new_type) {
   7294 				(void) PHY_INTERFACE_SET(int_pc->pd, unit, port, new_type);
   7295 			}
   7296 
   7297 			/* Check if it must change to forced */
   7298 			SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &cur_an, &cur_an_done));
   7299 			if (cur_an == TRUE) {
   7300 				(void) PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit,port, FALSE);
   7301 			}
   7302 
   7303             if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2)) {
   7304                 /* Skip int_pc speed set during phy init */
   7305             } else if ((rv = PHY_SPEED_GET(int_pc->pd, unit, port, &cur_speed))
   7306                         != SOC_E_NONE) {
   7307                 /*
   7308                 LOG_CLI((BSL_META_U(unit,
   7309                                     "84328 u=%d p=%d speed get error\n"), unit, port));
   7310                 */
   7311                 return rv;
   7312             } else if (cur_speed  != sys_intf->speed) {
   7313 			    (void) PHY_SPEED_SET(int_pc->pd, unit, port, sys_intf->speed);
   7314             }
   7315 
   7316             /* For system intf=cr4 use XLAUI_DFE on Serdes (in forced mode)*/
   7317             if (sys_intf->type != SOC_PORT_IF_CR4) {
   7318                 /* Skip int_pc fw mode set */
   7319             } else if ((rv = PHY_CONTROL_GET(int_pc->pd, unit, port,
   7320                              SOC_PHY_CONTROL_FIRMWARE_MODE, &cur_fw_mode))
   7321                         != SOC_E_NONE) {
   7322                 /*
   7323                 LOG_CLI((BSL_META_U(unit,
   7324                                     "84328 u=%d p=%d fwmode get error\n"), unit, port));
   7325                 */
   7326                 return rv;
   7327             } else if (cur_fw_mode != SOC_PHY_FIRMWARE_FORCE_OSDFE) {
   7328                 (void) PHY_CONTROL_SET(int_pc->pd, unit, port,
   7329                                         SOC_PHY_CONTROL_FIRMWARE_MODE,
   7330                                         SOC_PHY_FIRMWARE_FORCE_OSDFE);
   7331             }
   7332 
   7333 		} else {
   7334 			SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit,port, TRUE));
   7335 		}
   7336 	}
   7337 
   7338 	/* Update interface type/speed */
   7339 	return _phy_84328_intf_line_sys_update(unit, port);
   7340 }
   7341 
   7342 STATIC int
   7343 _phy_84328_intf_line_sys_init(int unit, soc_port_t port)
   7344 {
   7345     phy_ctrl_t  *pc;
   7346 	phy84328_intf_cfg_t  *line_intf;
   7347 
   7348     pc = EXT_PHY_SW_STATE(unit, port);
   7349 	line_intf = &(LINE_INTF(pc));
   7350 
   7351 	return __phy_84328_speed_set(unit, port, line_intf->speed);
   7352 }
   7353 
   7354 /*
   7355  * Function:
   7356  *      phy_84328_speed_set
   7357  * Purpose:
   7358  *      Set PHY speed
   7359  * Parameters:
   7360  *      unit - StrataSwitch unit #.
   7361  *      port - StrataSwitch port #.
   7362  *      speed - link speed in Mbps
   7363  * Returns:
   7364  *      SOC_E_NONE
   7365  */
   7366 
   7367 STATIC int
   7368 _phy_84328_speed_set(int unit, soc_port_t port, int speed)
   7369 {
   7370 	int rv;
   7371     phy_ctrl_t  *pc;
   7372 	phy84328_intf_cfg_t  *line_intf;
   7373 	phy84328_intf_cfg_t  *sys_intf;
   7374 
   7375     COMPILER_REFERENCE(unit);
   7376     COMPILER_REFERENCE(port); 
   7377 
   7378     pc = EXT_PHY_SW_STATE(unit, port);
   7379 	line_intf = &(LINE_INTF(pc));
   7380 	sys_intf = &(SYS_INTF(pc));
   7381 
   7382     LOG_INFO(BSL_LS_SOC_PHY,
   7383              (BSL_META_U(unit,
   7384                          "phy_84328_speed_set: u=%d p=%d speed=%d\n"), 
   7385                          unit, port,speed));
   7386     if (PHY84328_SINGLE_PORT_MODE(pc)) {
   7387 		if (! _phy_84328_intf_is_single_port(line_intf->type)) {
   7388 			LOG_INFO(BSL_LS_SOC_PHY,
   7389                                  (BSL_META_U(unit,
   7390                                              "84328 speed set does not match interface: "
   7391                                              "u=%d p=%d speed=%d intf=%d\n"),
   7392                                   unit, port, speed, sys_intf->type));
   7393 			return SOC_E_PARAM;
   7394 		}
   7395 		switch (speed) {
   7396         case 100000:
   7397 		case 40000:
   7398 			break;
   7399 		case 42000:
   7400 			/* 42G only valid for HG[42] */
   7401 			if (! IS_HG_PORT(unit, port)) {
   7402 				speed = 40000;
   7403 			}
   7404 			break;
   7405 		default:
   7406 			return SOC_E_PARAM;
   7407 		}
   7408     } else {
   7409 		if (_phy_84328_intf_is_single_port(line_intf->type)) {
   7410 			LOG_ERROR(BSL_LS_SOC_PHY,
   7411                                   (BSL_META_U(unit,
   7412                                               "84328  invalid intf in quad port: u=%d p=%d intf=%d\n"),
   7413                                               unit, port, line_intf->type));
   7414 			return SOC_E_PARAM;
   7415 		} 
   7416 		switch (speed) {
   7417 		case 1000:
   7418             if (!_phy_84328_intf_type_1000(line_intf->type)) {
   7419                 line_intf->type = SOC_PORT_IF_GMII;
   7420             }
   7421             /*
   7422 			 * Changing speed to 1000 
   7423 			 * - if backplane interface then change to KX
   7424 			 * - if not KX, then set to GMII
   7425 			 */
   7426 			if (sys_intf->type == SOC_PORT_IF_KR) {
   7427 				sys_intf->type = SOC_PORT_IF_KX;
   7428 			} else if (sys_intf->type != SOC_PORT_IF_KX) {
   7429 				sys_intf->type = line_intf->type;
   7430 			}
   7431             break;
   7432         case 100:
   7433         case 10:
   7434             if (line_intf->type != SOC_PORT_IF_SGMII) {
   7435                 line_intf->type = SOC_PORT_IF_SGMII;
   7436             }
   7437             sys_intf->type = line_intf->type;
   7438             break;
   7439 		case 10000:
   7440 			/* 
   7441 			 * If changing from 1000 to 10000, then adjust interface 
   7442 			 */
   7443 			if (line_intf->speed <= 1000) {
   7444 				/* 
   7445 				 * If changing speed from 1000 to 10000, set line interface to SFI
   7446 				 */
   7447 				if (!_phy_84328_intf_type_10000(line_intf->type)) {
   7448 					line_intf->type = SOC_PORT_IF_SR;
   7449 				}
   7450 				/*
   7451 				 * Restore the configured system side interface
   7452 				 */
   7453 				sys_intf->type = CFG_SYS_INTF(pc);
   7454 				if (!_phy_84328_intf_type_10000(sys_intf->type)) {
   7455 					sys_intf->type = SOC_PORT_IF_XFI;
   7456 				}
   7457 			}
   7458 			break;
   7459 		case 40000:
   7460 		default:
   7461 			LOG_ERROR(BSL_LS_SOC_PHY,
   7462                                   (BSL_META_U(unit,
   7463                                               "84328  invalid speed: u=%d p=%d speed=%d\n"),
   7464                                               unit, port, speed));
   7465 			return SOC_E_PARAM;
   7466 		}
   7467 	}
   7468 	rv =  __phy_84328_speed_set(unit, port, speed);
   7469 	if (SOC_FAILURE(rv)) {
   7470 		LOG_ERROR(BSL_LS_SOC_PHY,
   7471                           (BSL_META_U(unit,
   7472                                       "84328  %s failed: u=%d p=%d\n"), FUNCTION_NAME(), unit, port));
   7473 	}
   7474 	return rv;
   7475 }
   7476 
   7477 /*
   7478  * Function:
   7479  *      phy_84328_speed_get
   7480  * Purpose:
   7481  *      Get PHY speed
   7482  * Parameters:
   7483  *      unit - StrataSwitch unit #.
   7484  *      port - StrataSwitch port #.
   7485  *      speed - current link speed in Mbps
   7486  * Returns:
   7487  *      SOC_E_NONE
   7488  */
   7489 
   7490 STATIC int
   7491 _phy_84328_speed_get(int unit, soc_port_t port, int *speed)
   7492 {
   7493 	phy84328_intf_cfg_t *line_intf;
   7494     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   7495 
   7496 	line_intf = &(LINE_INTF(pc));
   7497 	*speed = line_intf->speed;
   7498 
   7499     return SOC_E_NONE;
   7500 }
   7501 
   7502 
   7503 STATIC int
   7504 _phy_84328_intf_type_set(int unit, soc_port_t port, soc_port_if_t pif, int must_update)
   7505 {
   7506 	int			rv = SOC_E_NONE;
   7507     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   7508 	phy84328_intf_cfg_t *line_intf;
   7509 	int			update = 0;
   7510 	uint16		reg_data = 0, reg_mask = 0;
   7511     uint16      data = 0, mask = 0;
   7512 
   7513 	line_intf = &(LINE_INTF(pc));
   7514 	
   7515 	reg_data = 0;
   7516 	reg_mask = 0;
   7517 
   7518     FORCE_20BIT(pc) &= ~(FORCE_20BIT_AN);
   7519 
   7520     if (_phy_84328_intf_is_single_port(pif)) {
   7521 
   7522         if (!PHY84328_SINGLE_PORT_MODE(pc)) {
   7523             LOG_ERROR(BSL_LS_SOC_PHY,
   7524                       (BSL_META_U(unit,
   7525                                   "84328 invalid interface for quad port: u=%d p=%d\n"),
   7526                                   unit, port));
   7527             return SOC_E_CONFIG;
   7528         }
   7529 		/* 
   7530 		 * If rx polarity is flipped and the interface is CR4, then change the datapath
   7531          * to 20-bit as rx polarity cannot be handle on the line side in 4-bit
   7532 		 */
   7533         if (pif == SOC_PORT_IF_CR4) {
   7534 			if (AN_EN(pc)) {
   7535 				if (POL_RX_CFG(pc) && (CUR_DATAPATH(pc) != PHY84328_DATAPATH_20)) {
   7536 					CUR_DATAPATH(pc) = PHY84328_DATAPATH_20;
   7537 					update = 1;
   7538 				}
   7539                 if (POL_RX_CFG(pc)) {
   7540                     FORCE_20BIT(pc) |= FORCE_20BIT_AN ;
   7541                 }
   7542 			} else if (FORCE_20BIT(pc) == 0  && 
   7543                        CUR_DATAPATH(pc) != CFG_DATAPATH(pc)) {
   7544 				CUR_DATAPATH(pc) = CFG_DATAPATH(pc);
   7545 				update = 1;
   7546 			}
   7547 
   7548 			SOC_IF_ERROR_RETURN(
   7549 				_phy_84328_intf_datapath_reg_get(unit, port, CUR_DATAPATH(pc), &data, &mask));
   7550 			reg_data |= data;
   7551 			reg_mask |= mask;
   7552         }
   7553 		if ((pif != line_intf->type) || must_update) {
   7554             update = 1;
   7555 
   7556 		}
   7557     } else if (_phy_84328_intf_is_quad_port(pif)) {
   7558         if (PHY84328_SINGLE_PORT_MODE(pc)) {
   7559             LOG_ERROR(BSL_LS_SOC_PHY,
   7560                       (BSL_META_U(unit,
   7561                                   "84328 invalid interface for single port: u=%d p=%d\n"),
   7562                                   unit, port));
   7563             return SOC_E_CONFIG;
   7564         }
   7565 
   7566         if ((line_intf->type != pif) || must_update) {
   7567             update = 1;
   7568             SOC_IF_ERROR_RETURN(
   7569                 _phy_84328_intf_type_reg_get(unit, port, pif, PHY84328_INTF_SIDE_LINE,
   7570                                              &reg_data, &reg_mask));
   7571 
   7572         }
   7573     } else {
   7574         LOG_ERROR(BSL_LS_SOC_PHY,
   7575                   (BSL_META_U(unit,
   7576                               "84328 invalid interface for port: u=%d p=%d intf=%d\n"),
   7577                               unit, port, pif));
   7578         return SOC_E_CONFIG;
   7579     }
   7580 
   7581 	if (update) {
   7582 		line_intf->type = pif;
   7583 
   7584         SOC_IF_ERROR_RETURN(
   7585             _phy_84328_intf_type_reg_get(unit, port, pif, PHY84328_INTF_SIDE_LINE,
   7586                                              &data, &mask));
   7587         reg_data |= data;
   7588         reg_mask |= mask;
   7589 
   7590 		SOC_IF_ERROR_RETURN(_phy_84328_intf_update(unit, port, reg_data, reg_mask));
   7591 
   7592 	}
   7593 
   7594 	return rv;
   7595 }
   7596 
   7597 /*
   7598  * Function:
   7599  *      phy_84328_interface_set
   7600  * Purpose:
   7601  *      
   7602  *      
   7603  * Parameters:
   7604  *      unit - StrataSwitch unit #.
   7605  *      port - StrataSwitch port #.
   7606  *      pif - one of SOC_PORT_IF_*
   7607  * Returns:
   7608  *      SOC_E_NONE - success
   7609  *      SOC_E_UNAVAIL - unsupported interface
   7610  */
   7611 
   7612 STATIC int
   7613 _phy_84328_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   7614 {
   7615 	int rv;
   7616 
   7617 	LOG_INFO(BSL_LS_SOC_PHY,
   7618                  (BSL_META_U(unit,
   7619                              "84328 interface set: u=%d p=%d pif=%s\n"), 
   7620                              unit, port, phy84328_intf_names[pif]));
   7621 
   7622 
   7623 	if (pif == SOC_PORT_IF_MII) {
   7624 		return phy_null_interface_set(unit, port, pif);
   7625 	}
   7626 
   7627 	if (pif == SOC_PORT_IF_XGMII) {
   7628 		return phy_null_interface_set(unit, port, pif);
   7629 	}
   7630 
   7631 	rv = _phy_84328_intf_type_set(unit, port, pif, FALSE);
   7632 	if (SOC_FAILURE(rv)) {
   7633 		LOG_INFO(BSL_LS_SOC_PHY,
   7634                          (BSL_META_U(unit,
   7635                                      "84328  interface set check failed: u=%d p=%d\n"),
   7636                                      unit, port));
   7637 	}
   7638 
   7639 	if (_phy_84328_intf_line_forced(unit, port, pif)) {
   7640 		SOC_IF_ERROR_RETURN(_phy_84328_an_set(unit, port, 0));
   7641 	}
   7642 
   7643 	return SOC_E_NONE;
   7644 }
   7645 
   7646 /*
   7647  * Function:
   7648  *      phy_84328_interface_get
   7649  * Purpose:
   7650  *      Get the current operating mode of the PHY.
   7651  * Parameters:
   7652  *      unit - StrataSwitch unit #.
   7653  *      port - StrataSwitch port #.
   7654  *      pif - (OUT) one of SOC_PORT_IF_*
   7655  * Returns:
   7656  *      SOC_E_NONE
   7657  */
   7658 
   7659 STATIC int
   7660 _phy_84328_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   7661 {
   7662     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   7663 	phy84328_intf_cfg_t *line_intf;
   7664 
   7665 	/* interface set now operates on line side interface */
   7666 	line_intf = &(LINE_INTF(pc));
   7667 	*pif = line_intf->type;
   7668 
   7669     return SOC_E_NONE;
   7670 }
   7671 
   7672 STATIC int
   7673 _phy84328_init_ucode_bcst_load(int unit, int port)
   7674 {
   7675 	uint16 data16, mask16, num_words;
   7676 	uint8 *fw_ptr;
   7677 	int j, fw_length;
   7678 	phy_ctrl_t *pc;
   7679 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   7680 	int dbg_flag = 1;
   7681 #endif
   7682 
   7683 	pc = EXT_PHY_SW_STATE(unit, port);
   7684 
   7685 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   7686 	if (dbg_flag) {
   7687             LOG_INFO(BSL_LS_SOC_PHY,
   7688                      (BSL_META_U(unit,
   7689                                  "PHY84328 bcst download device name %s: u=%d p=%d\n"),
   7690                       pc->dev_name? pc->dev_name: "NULL", unit, port));
   7691 	}				 
   7692 #endif
   7693 	/* find the right firmware */
   7694 	if (pc->dev_name == dev_name_84328_a0) {
   7695         fw_ptr = phy84328_ucode_bin;
   7696         fw_length = phy84328_ucode_bin_len;
   7697     } else if (pc->dev_name == dev_name_84328) {
   7698         fw_ptr = phy84328B0_ucode_bin;
   7699         fw_length = phy84328B0_ucode_bin_len;
   7700     } else if (pc->dev_name == dev_name_84088) {
   7701         fw_ptr = phy84328B0_ucode_bin;
   7702         fw_length = phy84328B0_ucode_bin_len;
   7703 	} else {
   7704 		/* invalid device name */
   7705 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)		
   7706 		LOG_WARN(BSL_LS_SOC_PHY,
   7707                          (BSL_META_U(unit,
   7708                                      "firmware_bcst,invalid device name %s: u=%d p=%d\n"),
   7709                           pc->dev_name? pc->dev_name: "NULL", unit, port));
   7710 #endif						 
   7711 		return SOC_E_NONE;
   7712 	}
   7713 	
   7714 	/* clear SPA ctrl reg bit 15 and bit 13.
   7715 	 * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM
   7716 	 * bit 13, 0 clear download done status, 1 skip download
   7717 	 */
   7718 	mask16 = PHY84328_DEV1_SPA_CONTROL_STATUS_REGISTER_SPI_PORT_USED_MASK 
   7719 		| PHY84328_DEV1_SPA_CONTROL_STATUS_REGISTER_SPI_DWLD_DONE_MASK;
   7720 	data16 = 0;
   7721 	SOC_IF_ERROR_RETURN(
   7722 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7723 										PHY84328_DEV1_SPA_CONTROL_STATUS_REGISTER,
   7724 										data16,mask16));
   7725 	
   7726 	/* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */
   7727 	mask16 = PHY84328_DEV1_SPA_CONTROL_STATUS_REGISTER_SPI_BOOT_MASK;
   7728 	data16 = mask16;
   7729 	SOC_IF_ERROR_RETURN(
   7730 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7731 										PHY84328_DEV1_SPA_CONTROL_STATUS_REGISTER,
   7732 										data16,mask16));
   7733 	
   7734 	/* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */
   7735 	mask16 = PHY84328_DEV1_MISC_CTRL_SPI_DOWNLOAD_SIZE_MASK;
   7736 	data16 = mask16;
   7737 	SOC_IF_ERROR_RETURN(
   7738 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7739 										PHY84328_DEV1_MISC_CTRL,
   7740 										data16,mask16));
   7741 	
   7742 	/* deassert ucrst 1.ca10 bit 2=0 */
   7743 	mask16 = PHY84328_DEV1_GEN_CTRL_UCRST_MASK;
   7744 	data16 = 0x00; /*clear; not self-clearing*/
   7745 	SOC_IF_ERROR_RETURN(
   7746 		MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GEN_CTRL,
   7747 										data16,mask16));
   7748 	
   7749 	/* wait for 2ms for M8051 start and 5ms to initialize the RAM */
   7750 	sal_usleep(10000); /* Wait for 10ms */
   7751 	
   7752 	/* Write Starting Address, where the Code will reside in SRAM */
   7753 	data16 = 0x8000;
   7754 	SOC_IF_ERROR_RETURN(
   7755 		WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7756 									   PHY84328_DEV1_MSG_IN, data16));
   7757 	
   7758 	/* make sure address word is read by the micro */
   7759 	sal_udelay(10); /* Wait for 10us */
   7760 	
   7761 	/* Write SPI SRAM Count Size */
   7762 	data16 = (fw_length)/2;
   7763 	SOC_IF_ERROR_RETURN(
   7764 		WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7765 									   PHY84328_DEV1_MSG_IN, data16));
   7766 	
   7767 	/* make sure read by the micro */
   7768 	sal_udelay(10); /* Wait for 10us */
   7769     
   7770     if (pc->addr_write != NULL) { 
   7771         SOC_IF_ERROR_RETURN(
   7772             WRITE_ADDR_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7773                                            PHY84328_C45_DEV_PMA_PMD,
   7774                                            PHY84328_DEV1_MSG_IN));
   7775 	}
   7776 	/* Fill in the SRAM */
   7777 	num_words = (fw_length - 1);
   7778 	for (j = 0; j < num_words; j+=2) {
   7779 
   7780 		data16 = (fw_ptr[j] << 8) | fw_ptr[j+1];
   7781     
   7782         if (pc->data_write != NULL) {    
   7783     		SOC_IF_ERROR_RETURN(
   7784 	    		WRITE_DATA_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7785 		    								PHY84328_C45_DEV_PMA_PMD, data16));
   7786         } else {
   7787 
   7788     		/* Make sure the word is read by the Micro */
   7789 	        sal_udelay(10);
   7790             SOC_IF_ERROR_RETURN(
   7791                 WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   7792                                             PHY84328_DEV1_MSG_IN, data16));
   7793         }
   7794 
   7795 	}
   7796 	return SOC_E_NONE;
   7797 }
   7798 
   7799 STATIC int
   7800 __phy84328_init_ucode_bcst(int unit, int port, int cmd)
   7801 {
   7802     uint16 data16;
   7803     uint16 mask16;
   7804     phy_ctrl_t *pc;
   7805 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   7806 	int dbg_flag = 1;
   7807 #endif
   7808     pc = EXT_PHY_SW_STATE(unit, port);
   7809 
   7810 #ifdef BCM_WARM_BOOT_SUPPORT
   7811     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){
   7812         return SOC_E_NONE;
   7813     }
   7814 #endif
   7815 
   7816     if (cmd == PHYCTRL_UCODE_BCST_SETUP) {
   7817 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)	
   7818         if (dbg_flag == 1) {
   7819             LOG_INFO(BSL_LS_SOC_PHY,
   7820                      (BSL_META_U(unit,
   7821                                  "PHY84328 bcst setup: u=%d p=%d\n"), unit, port));
   7822         }
   7823 #endif		
   7824         /* Enable broadcast mode so all lanes get properly reset */
   7825         SOC_IF_ERROR_RETURN
   7826             (MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7827                     PHY84328_DEV1_BROADCAST_CTRL,
   7828                     PHY84328_DEV1_BROADCAST_CTRL_BROADCAST_MODE_ENABLE_MASK,
   7829                     PHY84328_DEV1_BROADCAST_CTRL_BROADCAST_MODE_ENABLE_MASK));
   7830         return SOC_E_NONE;
   7831     } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) {
   7832 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   7833         if (dbg_flag == 1) {
   7834             LOG_INFO(BSL_LS_SOC_PHY,
   7835                      (BSL_META_U(unit,
   7836                                  "PHY84328 micro setup: u=%d p=%d\n"), unit, port));
   7837         }
   7838 #endif
   7839         /* apply bcst Reset to start download code from MDIO */
   7840         mask16 = PHY84328_DEV1_GEN_CTRL_UCRST_MASK;
   7841         data16 = mask16; /*set*/
   7842         SOC_IF_ERROR_RETURN
   7843             (MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_GEN_CTRL,
   7844                                            data16,mask16));
   7845 
   7846         /* clear : 1.ca18 */
   7847         SOC_IF_ERROR_RETURN
   7848             (WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   7849                                            PHY84328_DEV1_GP_REG_0, 0));
   7850         /* clear : 1.ca19 */
   7851         SOC_IF_ERROR_RETURN
   7852             (WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   7853                                            PHY84328_DEV1_GP_REG_1, 0));
   7854         /* clear : 1.ca1a */
   7855         SOC_IF_ERROR_RETURN
   7856             (WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   7857                                            PHY84328_DEV1_GP_REG_2, 0));
   7858 
   7859         mask16 = PHY84328_DEV1_PMD_CONTROL_REGISTER_RESET_MASK;
   7860         data16 = mask16;
   7861         SOC_IF_ERROR_RETURN
   7862             (MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_PMD_CONTROL_REGISTER,
   7863                                            data16,mask16));
   7864 
   7865         /* Wait for 2.8 msec for 8051 to start */
   7866         sal_udelay(2800);
   7867 
   7868         return SOC_E_NONE;
   7869     } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) {
   7870 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   7871         if (dbg_flag == 1) {
   7872             LOG_INFO(BSL_LS_SOC_PHY,
   7873                      (BSL_META_U(unit,
   7874                                  "PHY84328 bcst enable: u=%d p=%d\n"), unit, port));
   7875         }
   7876 #endif
   7877         /* In case reset clears bcst register */
   7878         /* restore bcst register after reset */
   7879         /* Enable broadcast mode */
   7880         SOC_IF_ERROR_RETURN
   7881             (MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7882                     PHY84328_DEV1_BROADCAST_CTRL,
   7883                     PHY84328_DEV1_BROADCAST_CTRL_BROADCAST_MODE_ENABLE_MASK,
   7884                     PHY84328_DEV1_BROADCAST_CTRL_BROADCAST_MODE_ENABLE_MASK));
   7885 
   7886         return SOC_E_NONE;
   7887     } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) {
   7888 
   7889 		return _phy84328_init_ucode_bcst_load(unit, port);
   7890 
   7891     } else if (cmd == PHYCTRL_UCODE_BCST_END) {
   7892 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   7893         if (dbg_flag == 1) {
   7894             LOG_INFO(BSL_LS_SOC_PHY,
   7895                      (BSL_META_U(unit,
   7896                                  "PHY84328 bcst end: u=%d p=%d\n"), unit, port));
   7897         }
   7898 #endif
   7899         /* make sure last code word is read by the micro */
   7900         sal_udelay(20);
   7901 
   7902 
   7903         /* Read Hand-Shake message (Done) from Micro */
   7904         SOC_IF_ERROR_RETURN
   7905             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7906                                            PHY84328_DEV1_MSG_OUT, &data16));
   7907 
   7908         /* Download done message */
   7909 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)		
   7910         if (dbg_flag == 1) {
   7911             LOG_INFO(BSL_LS_SOC_PHY,
   7912                      (BSL_META_U(unit,
   7913                                  "PHY84328 MDIO firmware download done message=0x%x: u=%d p=%d\n"),
   7914                       data16, unit, port));
   7915         }
   7916 #endif
   7917         sal_udelay(100); /* Wait for 100 usecs */
   7918 
   7919         /* Read checksum for Micro.
   7920            The expected value is 0x0300 , 
   7921            where upper_byte=03 means mdio download is done
   7922            and lower byte=00 means no checksum error */
   7923         SOC_IF_ERROR_RETURN
   7924             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7925                                            PHY84328_DEV1_MSG_OUT, &data16));
   7926 
   7927         /* Download done message */
   7928 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)		
   7929         if (dbg_flag == 1) {
   7930             LOG_INFO(BSL_LS_SOC_PHY,
   7931                      (BSL_META_U(unit,
   7932                                  "PHY84328 MDIO firmware download status message state 0x%x checksum 0x%x: "
   7933                                  "u=%d p=%d\n"), (data16 >> 8) & 0xff, data16 & 0xff, unit, port));
   7934         }
   7935 #endif
   7936         /* Need to check if checksum is correct */
   7937         SOC_IF_ERROR_RETURN
   7938             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7939                                            PHY84328_DEV1_GP_REG_4, &data16));
   7940 
   7941         if (data16 == 0x600D) {
   7942 			/* read Rev-ID */
   7943 			SOC_IF_ERROR_RETURN
   7944 				(READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7945 											   PHY84328_DEV1_VERSION, &data16));
   7946 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)											   
   7947 			if (dbg_flag == 1) {
   7948                 LOG_INFO(BSL_LS_SOC_PHY,
   7949                          (BSL_META_U(unit,
   7950                                      "PHY84328 Firmware revID=0x%x: u=%d p=%d \n"),
   7951                                      data16, unit, port));
   7952             }
   7953 #endif			
   7954         }
   7955 
   7956         /* Disable broadcast mode */
   7957         SOC_IF_ERROR_RETURN
   7958             (MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   7959                     PHY84328_DEV1_BROADCAST_CTRL,
   7960                     0,
   7961                     PHY84328_DEV1_BROADCAST_CTRL_BROADCAST_MODE_ENABLE_MASK));
   7962 
   7963 		/* Go back to proper PMD mode */
   7964 		data16 = (PHY84328_SINGLE_PORT_MODE(pc)) ?
   7965 			PHY84328_DEV1_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK : 0;
   7966 		SOC_IF_ERROR_RETURN
   7967 			(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   7968 											 PHY84328_DEV1_SINGLE_PMD_CTRL, data16,
   7969 											 PHY84328_DEV1_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK));
   7970 
   7971 		/* Make sure micro completes its initialization */
   7972 		sal_udelay(5000);
   7973         return SOC_E_NONE;
   7974     } else {
   7975         LOG_ERROR(BSL_LS_SOC_PHY,
   7976                   (BSL_META_U(unit,
   7977                               "u=%d p=%d firmware_bcst: invalid cmd 0x%x\n"),
   7978                    unit, port,cmd));
   7979     }
   7980 
   7981     return SOC_E_FAIL;
   7982 }
   7983 
   7984 
   7985 /*
   7986  * Function:
   7987  *      phy_84328_precondition_before_probe
   7988  * Purpose:
   7989  *      When the device is in 40G, ie. after a power reset, and the 10G 
   7990  *      port being probed does not have the 40G address in PRTAD, the 
   7991  *      device will not respond until the port that has the 40G address
   7992  *      is probed. To avoid not programming ports correctly, make
   7993  *      sure the device is in quad (4x10G) PMD mode when the SDK port is 10G.
   7994  * Parameters:
   7995  *      unit - StrataSwitch unit #.
   7996  *      pc   - phy ctrl descriptor.
   7997  * Returns:
   7998  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   7999  */
   8000 
   8001 STATIC int
   8002 phy_84328_precondition_before_probe(int unit, phy_ctrl_t *pc)
   8003 {
   8004     int ids;
   8005     int rv = SOC_E_NOT_FOUND;
   8006     uint16 pmd_ctrl;
   8007     uint16 id0, id1;
   8008     uint16 saved_phy_id;
   8009 
   8010     /* Not required when the port is single PMD */
   8011     if (PHY84328_SINGLE_PORT_MODE(pc)) {
   8012         LOG_INFO(BSL_LS_SOC_PHY,
   8013                  (BSL_META_U(unit,
   8014                              "PMD must not be called when in single PMD\n")));
   8015         return rv;
   8016     }
   8017 
   8018     saved_phy_id = pc->phy_id;
   8019 
   8020     /* Look for first address that responds */
   8021     for (ids = 0; ids < 4; ids++) {
   8022 
   8023         pc->phy_id = (saved_phy_id & ~0x3) + ids;
   8024         LOG_INFO(BSL_LS_SOC_PHY,
   8025                  (BSL_META_U(unit,
   8026                              "Try device with address %x\n"), pc->phy_id));
   8027 
   8028         /* 
   8029          * Make sure the device has the correct dev IDs 
   8030          * Note that this is being called either because the soc probe found
   8031          * the ids or there was an id override. In the later case, the device
   8032          * might not have the 84328 ids so this PMD setup will not be supported
   8033          */
   8034         id0 = 0;
   8035         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   8036                                       PHY84328_DEV1_PMD_IDENTIFIER_REGISTER_0,
   8037                                       &id0);
   8038         if (id0 != 0x600d) {
   8039             continue;
   8040         }
   8041         id1 = 0;
   8042         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 
   8043                                       PHY84328_DEV1_PMD_IDENTIFIER_REGISTER_1,
   8044                                       &id1);
   8045         if (id1 != 0x8500) {
   8046             continue;
   8047         }
   8048 
   8049         /* Read device ids correctly so use this address to make sure device is in 10G */
   8050         pmd_ctrl = 0;
   8051         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   8052                                       PHY84328_DEV1_SINGLE_PMD_CTRL, &pmd_ctrl);
   8053         if (pmd_ctrl & PHY84328_DEV1_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK) {
   8054             LOG_INFO(BSL_LS_SOC_PHY,
   8055                      (BSL_META_U(unit,
   8056                                  "Device responded to address %x. Setting quad PMD mode\n"), 
   8057                       pc->phy_id));
   8058             pmd_ctrl = 0;   /* Clear single PMD */
   8059             SOC_IF_ERROR_RETURN(
   8060                     MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   8061                                             PHY84328_DEV1_SINGLE_PMD_CTRL, pmd_ctrl, 
   8062                                             PHY84328_DEV1_SINGLE_PMD_CTRL_SINGLE_PMD_MODE_MASK));
   8063         }
   8064         /* Found the address that responds and the device now is in 4x10G */
   8065         rv = SOC_E_NONE;
   8066         break;
   8067     }
   8068 
   8069     pc->phy_id = saved_phy_id;
   8070 
   8071     return rv;
   8072 }
   8073 
   8074 /*
   8075  * Function:
   8076  *      phy_84328_probe
   8077  * Purpose:
   8078  *      Complement the generic phy probe routine to identify this phy when its
   8079  *      phy id0 and id1 is same as some other phy's.
   8080  * Parameters:
   8081  *      unit - StrataSwitch unit #.
   8082  *      pc   - phy ctrl descriptor.
   8083  * Returns:
   8084  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   8085  */
   8086 STATIC int
   8087 _phy_84328_probe(int unit, phy_ctrl_t *pc)
   8088 {
   8089     uint32 devid;
   8090     uint16 chip_rev;
   8091 
   8092     SOC_IF_ERROR_RETURN(_phy_84328_config_devid(pc->unit, pc->port, pc, &devid));
   8093     SOC_IF_ERROR_RETURN(
   8094         READ_PHY84328_MMF_PMA_PMD_REG(unit, pc,
   8095                                       PHY84328_DEV1_CHIP_REV_REGISTER,
   8096                                       &chip_rev));
   8097 
   8098     if (devid == PHY84328_ID_84328) {
   8099         if (chip_rev == 0x00a0) {
   8100             pc->dev_name = dev_name_84328_a0;
   8101         } else {
   8102             pc->dev_name = dev_name_84328;
   8103         }
   8104     } else if (devid == PHY84328_ID_84324){
   8105         pc->dev_name = dev_name_84324;
   8106     } else if (devid == PHY84328_ID_84088){
   8107         pc->dev_name = dev_name_84088;
   8108     } else if (devid == PHY84328_ID_84024){
   8109         pc->dev_name = dev_name_84024;
   8110     } else {  /* not found */
   8111         LOG_WARN(BSL_LS_SOC_PHY,
   8112                  (BSL_META_U(unit,
   8113                              "port %d: BCM84xxx type PHY device detected, please use "
   8114                              "phy_84<xxx> config variable to select the specific type\n"),
   8115                   pc->port));
   8116         return SOC_E_NOT_FOUND;
   8117     }
   8118     pc->size = sizeof(phy84328_dev_desc_t);
   8119     return SOC_E_NONE;
   8120 }
   8121 
   8122 /* 
   8123  * Return the phy_id for the core 
   8124  *
   8125  * Currently assumes the addresses for the cores are 
   8126  * 4 apart, e.g. core0_addr=n, core1_addr=n+4; core2_addr=n+8
   8127  *
   8128  * This can be modified to specify the address via a config property.
   8129  * The config property spn_PORT_PHY_ADDR is already available to
   8130  * specify the address for the port, which in a multicore port, 
   8131  * refers to core0.
   8132  */
   8133 STATIC uint16 
   8134 _phy_84328_phy_id_get(phy_ctrl_t *pc, int core)
   8135 {
   8136     int phy_id = 0xff;
   8137     int id_map[PHY84328_MAX_CORES] = { 0xff , 0xff, 0xff };
   8138 
   8139     id_map[core%PHY84328_MAX_CORES] =
   8140         soc_property_port_suffix_num_get(
   8141                     pc->unit, pc->port, 
   8142                     core, spn_PORT_PHY_ADDR,
   8143                     "core", id_map[core % PHY84328_MAX_CORES]);
   8144 
   8145     phy_id = 
   8146         soc_property_port_get(
   8147                     pc->unit, pc->port, spn_PORT_PHY_ADDR, phy_id);
   8148 
   8149     if (phy_id != id_map[core % PHY84328_MAX_CORES]) {
   8150         return id_map[core % PHY84328_MAX_CORES];
   8151     } else {
   8152         return pc->phy_id + (core * 4);
   8153     }
   8154 }
   8155 
   8156 
   8157 STATIC int
   8158 _phy_84328_bsc_rw(int unit, soc_port_t port, int dev_addr, int opr,
   8159                     int addr, int count, void *data_array,uint32 ram_start)
   8160 {
   8161     phy_ctrl_t  *pc;
   8162     soc_timeout_t  to;
   8163     uint16 data16;
   8164     int i;
   8165     int access_type;
   8166     int data_type;
   8167 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   8168     sal_usecs_t start;
   8169     sal_usecs_t end;
   8170 #endif
   8171 
   8172     LOG_INFO(BSL_LS_SOC_PHY,
   8173              (BSL_META_U(unit,
   8174                          "phy_84328_bsc_read: u=%d p=%d addr=%04x\n"),
   8175                          unit, port, addr));
   8176 
   8177     if (!data_array) {
   8178         return SOC_E_PARAM;
   8179     }
   8180 
   8181     if (count > PHY84328_BSC_XFER_MAX) {
   8182         return SOC_E_PARAM;
   8183     }
   8184 
   8185     pc = EXT_PHY_SW_STATE(unit, port);
   8186     data_type = PHY84328_I2C_DATA_TYPE(opr);
   8187     access_type = PHY84328_I2C_ACCESS_TYPE(opr);
   8188 
   8189     if (access_type == PHY84328_I2CDEV_WRITE) {
   8190         for (i = 0; i < count; i++) {
   8191             if (data_type == PHY84328_I2C_8BIT) {
   8192                 SOC_IF_ERROR_RETURN
   8193                     (WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, ram_start + i,
   8194                           ((uint8 *)data_array)[i]));
   8195             } else {  /* 16 bit */
   8196                 SOC_IF_ERROR_RETURN
   8197                     (WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, ram_start + i,
   8198                           ((uint16 *)data_array)[i]));
   8199             }
   8200         }
   8201     }
   8202 
   8203     data16 = ram_start;
   8204     SOC_IF_ERROR_RETURN
   8205         (WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, 0x8004, data16));
   8206     SOC_IF_ERROR_RETURN
   8207         (WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, 0x8003, addr));
   8208     SOC_IF_ERROR_RETURN
   8209         (WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, 0x8002, count));
   8210 
   8211     data16 = 1;
   8212     data16 |= (dev_addr<<9);
   8213     if (access_type == PHY84328_I2CDEV_WRITE) {
   8214         data16 |= PHY84328_WR_FREQ_400KHZ;
   8215     }
   8216 
   8217     SOC_IF_ERROR_RETURN
   8218         (WRITE_PHY84328_MMF_PMA_PMD_REG(unit,pc,0x8005,data16));
   8219 
   8220     if (access_type == PHY84328_I2CDEV_WRITE) {
   8221         data16 =  0x8000 | PHY84328_BSC_WRITE_OP;
   8222     } else {
   8223         data16 =  0x8000 | PHY84328_BSC_READ_OP;
   8224     }
   8225 
   8226     if (data_type == PHY84328_I2C_16BIT) {
   8227         data16 |= (1 << 12);
   8228     }
   8229 
   8230 	/* Select first i2c port */
   8231 	if (PHY84328_SINGLE_PORT_MODE(pc)) {
   8232 		SOC_IF_ERROR_RETURN
   8233 			(MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_MISC_CTRL,
   8234 											 0, PHY84328_DEV1_MISC_CTRL_I2C_PORT_SEL_MASK));
   8235 	} else {
   8236         SOC_IF_ERROR_RETURN
   8237              (MODIFY_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_DEV1_MISC_CTRL,
   8238              (pc->phy_id & 0x3), PHY84328_DEV1_MISC_CTRL_I2C_PORT_SEL_MASK));
   8239     }
   8240 		
   8241 	SOC_IF_ERROR_RETURN
   8242 		(WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, 0x8000, data16));
   8243 
   8244 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   8245     start = sal_time_usecs();
   8246 #endif
   8247     soc_timeout_init(&to, 1000000, 0);
   8248     while (!soc_timeout_check(&to)) {
   8249         SOC_IF_ERROR_RETURN
   8250             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, 0x8000, &data16));
   8251         if (((data16 & PHY84328_2W_STAT) == PHY84328_2W_STAT_COMPLETE)) {
   8252             break;
   8253         }
   8254     }
   8255 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   8256     end = sal_time_usecs();
   8257 #endif
   8258     /* need some delays */
   8259     sal_usleep(10000);
   8260 
   8261 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT)
   8262     LOG_INFO(BSL_LS_SOC_PHY,
   8263              (BSL_META_U(unit,
   8264                          "BSC command status %d time=%d\n"),
   8265                          (data16 & PHY84328_2W_STAT), SAL_USECS_SUB(end, start)));
   8266 #endif
   8267 
   8268     if (access_type == PHY84328_I2CDEV_WRITE) {
   8269         return SOC_E_NONE;
   8270     }
   8271 
   8272     if ((data16 & PHY84328_2W_STAT) == PHY84328_2W_STAT_COMPLETE) {
   8273         for (i = 0; i < count; i++) {
   8274             SOC_IF_ERROR_RETURN
   8275                 (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, (ram_start+i), &data16));
   8276             if (data_type == PHY84328_I2C_16BIT) {
   8277                 ((uint16 *)data_array)[i] = data16;
   8278                 LOG_INFO(BSL_LS_SOC_PHY,
   8279                          (BSL_META_U(unit,
   8280                                      "%04x "), data16));
   8281             } else {
   8282                 ((uint8 *)data_array)[i] = (uint8)data16;
   8283                 LOG_INFO(BSL_LS_SOC_PHY,
   8284                          (BSL_META_U(unit,
   8285                                      "%02x "), data16));
   8286             }
   8287         }
   8288     }
   8289     return SOC_E_NONE;
   8290 }
   8291 
   8292 /*
   8293  * Read a slave device such as NVRAM/EEPROM connected to the 84328's I2C
   8294  * interface. This function will be mainly used for diagnostic or workaround
   8295  * purpose.
   8296  * Note:
   8297  * The size of read_array buffer must be greater than or equal to the
   8298  * parameter nbytes.
   8299  * usage example:
   8300  *   Retrieve the first 100 byte data of the non-volatile storage device with
   8301  *   I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0,
   8302  *   port 2.
   8303  *   uint8 data8[100];
   8304  *   phy_84328_i2cdev_read(0,2,0x50,0,100,data8);
   8305  */
   8306 int
   8307 phy_84328_i2cdev_read(int unit,
   8308                      soc_port_t port,
   8309                      int dev_addr,  /* 7 bit I2C bus device address */
   8310                      int offset,    /* starting data address to read */
   8311                      int nbytes,    /* number of bytes to read */
   8312                      uint8 *read_array)   /* buffer to hold retrieved data */
   8313 {
   8314     return _phy_84328_bsc_rw(unit, port, dev_addr,PHY84328_I2CDEV_READ,
   8315              offset, nbytes, (void *)read_array,PHY84328_READ_START_ADDR);
   8316 
   8317 }
   8318 
   8319 /*
   8320  * Write to a slave device such as NVRAM/EEPROM connected to the 84328's I2C
   8321  * interface. This function will be mainly used for diagnostic or workaround
   8322  * purpose.
   8323  * Note:
   8324  * The size of write_array buffer should be equal to the parameter nbytes.
   8325  * The EEPROM may limit the maximun write size to 16 bytes
   8326  * usage example:
   8327  *   Write to first 100 byte space of the non-volatile storage device with
   8328  *   I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0,
   8329  *   port 2, with written data specified in array data8.
   8330  *   uint8 data8[100];
   8331  *   *** initialize the data8 array with written data ***
   8332  *
   8333  *   phy_84328_i2cdev_write(0,2,0x50,0,100,data8);
   8334  */
   8335 
   8336 int
   8337 phy_84328_i2cdev_write(int unit,
   8338                      soc_port_t port,
   8339                      int dev_addr,  /* I2C bus device address */
   8340                      int offset,    /* starting data address to write to */
   8341                      int nbytes,    /* number of bytes to write */
   8342                      uint8 *write_array)   /* buffer to hold written data */
   8343 {
   8344     int j;
   8345     int rv = SOC_E_NONE;
   8346 
   8347     for (j = 0; j < (nbytes/PHY84328_BSC_WR_MAX); j++) {
   8348         rv = _phy_84328_bsc_rw(unit, port, dev_addr,PHY84328_I2CDEV_WRITE,
   8349                     offset + j * PHY84328_BSC_WR_MAX, PHY84328_BSC_WR_MAX,
   8350                     (void *)(write_array + j * PHY84328_BSC_WR_MAX),
   8351                     PHY84328_WRITE_START_ADDR);
   8352         if (rv != SOC_E_NONE) {
   8353             return rv;
   8354         }
   8355         sal_usleep(20000);
   8356     }
   8357     if (nbytes%PHY84328_BSC_WR_MAX) {
   8358         rv = _phy_84328_bsc_rw(unit, port, dev_addr,PHY84328_I2CDEV_WRITE,
   8359                 offset + j * PHY84328_BSC_WR_MAX, nbytes%PHY84328_BSC_WR_MAX,
   8360                 (void *)(write_array + j * PHY84328_BSC_WR_MAX),
   8361                 PHY84328_WRITE_START_ADDR);
   8362     }
   8363     return rv;
   8364 }
   8365 
   8366 /*
   8367  * Function:
   8368  *      _phy_84328_reg_read
   8369  * Purpose:
   8370  *      Routine to read PHY register
   8371  * Parameters:
   8372  *      uint         - BCM unit number
   8373  *      port         - port number
   8374  *      flags        - Flags which specify the register type
   8375  *      phy_reg_addr - Encoded register address
   8376  *      phy_data     - (OUT) Value read from PHY register
   8377  * Note:
   8378  *      This register read function is not thread safe. Higher level
   8379  * function that calls this function must obtain a per port lock
   8380  * to avoid overriding register page mapping between threads.
   8381  */
   8382 STATIC int
   8383 _phy_84328_reg_read(int unit, soc_port_t port, uint32 flags,
   8384                   uint32 phy_reg_addr, uint32 *phy_data)
   8385 {
   8386 	uint16               data16;
   8387     uint16               regdata;
   8388     phy_ctrl_t          *pc;      /* PHY software state */
   8389     int rv = SOC_E_NONE;
   8390 	int	rd_cnt;
   8391 
   8392     pc = EXT_PHY_SW_STATE(unit, port);
   8393 
   8394     rd_cnt = 1;
   8395 
   8396     if (flags & SOC_PHY_I2C_DATA8) {
   8397 
   8398         SOC_IF_ERROR_RETURN
   8399             (phy_84328_i2cdev_read(unit, port,
   8400                         SOC_PHY_I2C_DEVAD(phy_reg_addr),
   8401                         SOC_PHY_I2C_REGAD(phy_reg_addr),
   8402                         rd_cnt,
   8403                         (uint8 *)&data16));
   8404         *phy_data = *((uint8 *)&data16);
   8405 
   8406     } else if (flags & SOC_PHY_I2C_DATA16) {
   8407         /* This operation is generally targeted to access 16-bit device,
   8408          * such as PHY IC inside the SFP.  However there is no 16-bit
   8409          * scratch register space on the device.  Use 1.800e
   8410          * for this operation.
   8411          */
   8412         SOC_IF_ERROR_RETURN
   8413             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_I2C_TEMP_RAM,
   8414                    &regdata));
   8415 
   8416         rv = _phy_84328_bsc_rw(unit, port,
   8417                SOC_PHY_I2C_DEVAD(phy_reg_addr),
   8418                PHY84328_I2C_OP_TYPE(PHY84328_I2CDEV_READ,PHY84328_I2C_16BIT),
   8419                SOC_PHY_I2C_REGAD(phy_reg_addr),1,
   8420                (void *)&data16,PHY84328_I2C_TEMP_RAM);
   8421 
   8422         *phy_data = data16;
   8423 
   8424         /* restore the ram register value */
   8425         SOC_IF_ERROR_RETURN
   8426             (WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_I2C_TEMP_RAM,
   8427                  regdata));
   8428     } else {
   8429         SOC_IF_ERROR_RETURN
   8430             (READ_PHY_REG(unit, pc, phy_reg_addr, &data16));
   8431         *phy_data = data16;
   8432     }
   8433 
   8434     return rv;
   8435 }
   8436 
   8437 /*
   8438  * Function:
   8439  *      _phy_84328_reg_write
   8440  * Purpose:
   8441  *      Routine to write PHY register
   8442  * Parameters:
   8443  *      uint         - BCM unit number
   8444  *      port         - port number
   8445  *      flags        - Flags which specify the register type
   8446  *      phy_reg_addr - Encoded register address
   8447  *      phy_data     - Value write to PHY register
   8448  * Note:
   8449  *      This register read function is not thread safe. Higher level
   8450  * function that calls this function must obtain a per port lock
   8451  * to avoid overriding register page mapping between threads.
   8452  */
   8453 STATIC int
   8454 _phy_84328_reg_write(int unit, soc_port_t port, uint32 flags,
   8455                    uint32 phy_reg_addr, uint32 phy_data)
   8456 {
   8457     uint8  data8[4];
   8458     uint16 data16[2];
   8459     uint16 regdata[2];
   8460     phy_ctrl_t          *pc;      /* PHY software state */
   8461     int rv = SOC_E_NONE;
   8462     int wr_cnt;
   8463     pc = EXT_PHY_SW_STATE(unit, port);
   8464 
   8465     wr_cnt = 1;
   8466 
   8467     if (flags & SOC_PHY_I2C_DATA8) {
   8468         data8[0] = (uint8)phy_data;
   8469         SOC_IF_ERROR_RETURN
   8470             (phy_84328_i2cdev_write(unit, port,
   8471                         SOC_PHY_I2C_DEVAD(phy_reg_addr),
   8472                         SOC_PHY_I2C_REGAD(phy_reg_addr),
   8473                         wr_cnt,
   8474                         data8));
   8475     } else if (flags & SOC_PHY_I2C_DATA16) {
   8476         /* This operation is generally targeted to access 16-bit device,
   8477          * such as PHY IC inside the SFP.  However there is no 16-bit
   8478          * scratch register space on the device.  Use 1.800e
   8479          * for this operation.
   8480          */
   8481         /* save the temp ram register */
   8482         SOC_IF_ERROR_RETURN
   8483             (READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_I2C_TEMP_RAM,
   8484                  &regdata[0]));
   8485         data16[0] = phy_data;
   8486         rv = _phy_84328_bsc_rw(unit, port,
   8487               SOC_PHY_I2C_DEVAD(phy_reg_addr),
   8488               PHY84328_I2C_OP_TYPE(PHY84328_I2CDEV_WRITE,PHY84328_I2C_16BIT),
   8489               SOC_PHY_I2C_REGAD(phy_reg_addr),wr_cnt,
   8490               (void *)data16,PHY84328_I2C_TEMP_RAM);
   8491 
   8492         /* restore the ram register value */
   8493         SOC_IF_ERROR_RETURN
   8494             (WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, PHY84328_I2C_TEMP_RAM,
   8495                   regdata[0]));
   8496     } else {
   8497             SOC_IF_ERROR_RETURN
   8498             (WRITE_PHY_REG(unit, pc, phy_reg_addr, (uint16)phy_data));
   8499     }
   8500 
   8501     return rv;
   8502 }
   8503 
   8504 void
   8505 _phy_84328_dbg_reg_read(int unit, soc_port_t port, int reg)
   8506 {
   8507     uint16 data;
   8508     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   8509 
   8510     if (pc == NULL) {
   8511         return;
   8512     }
   8513     READ_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, &data);
   8514     LOG_CLI((BSL_META_U(unit,
   8515                         "1.%04x=0x%04x\n"), reg, data));
   8516 }
   8517 
   8518 void
   8519 _phy_84328_dbg_reg_write(int unit, soc_port_t port, int reg, uint16 val)
   8520 {
   8521     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   8522 
   8523     if (pc == NULL) {
   8524         return;
   8525     }
   8526     WRITE_PHY84328_MMF_PMA_PMD_REG(unit, pc, reg, val);
   8527     _phy_84328_dbg_reg_read(unit, port, reg);
   8528 }
   8529 
   8530 #ifdef PHY84328_MDIO_TRACING
   8531 STATIC int
   8532 _phy_84328_dbg_read(int unit, phy_ctrl_t *pc, uint32 addr, uint16 *data)
   8533 {
   8534 	int rv;
   8535 	rv = (pc->read)(unit, pc->phy_id, addr, data);
   8536 
   8537 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_REG) {
   8538 		LOG_CLI((BSL_META_U(unit,
   8539                                     "p%d(%d): READ addr=%04x data=%04x\n"),
   8540                          pc->port, pc->phy_id, addr, *data));
   8541 	}
   8542 	return rv;
   8543 		
   8544 }
   8545 
   8546 STATIC int
   8547 _phy_84328_dbg_write(int unit, phy_ctrl_t *pc, uint32 addr, uint16 data)
   8548 {
   8549 	int rv;
   8550 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_REG) {
   8551 		LOG_CLI((BSL_META_U(unit,
   8552                                     "p%d(%d): WRITE addr=%04x data=%04x\n"),
   8553                          pc->port, pc->phy_id, addr, data));
   8554 	}
   8555 	rv = (pc->write)(unit, pc->phy_id, addr, data);
   8556 	return rv;
   8557 }
   8558 
   8559 STATIC int
   8560 _phy_84328_dbg_modify(int unit, phy_ctrl_t *pc, uint32 addr, uint16 data, uint16 mask)
   8561 {
   8562 	int rv;
   8563 	if (DBG_FLAGS(pc) & PHY84328_DBG_F_REG) {
   8564 		LOG_CLI((BSL_META_U(unit,
   8565                                     "p%d(%d): MODIFY addr=%04x data=%04x mask=%04x\n"),
   8566                          pc->port, pc->phy_id, 
   8567                          addr, data, mask));
   8568 	}
   8569 	rv = phy_reg_modify(unit, pc, addr, data, mask);
   8570 	return rv;
   8571 }
   8572 #endif /* PHY84328_MDIO_TRACING */
   8573 
   8574 
   8575 
   8576 /******************************************************************************/
   8577 
   8578 
   8579 /*
   8580  * Function:
   8581  *      phy_84328_probe
   8582  * Purpose:
   8583  *      Complement the generic phy probe routine to identify this phy when its
   8584  *      phy id0 and id1 is same as some other phy's.
   8585  * Parameters:
   8586  *      unit - StrataSwitch unit #.
   8587  *      pc   - phy ctrl descriptor.
   8588  * Returns:
   8589  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   8590  */
   8591 STATIC int
   8592 phy_84328_probe(int unit, phy_ctrl_t *pc)
   8593 {
   8594     int rv;
   8595     char *dev_name = "";
   8596     uint16 prim_phy_id;
   8597     int core, all_cores;
   8598     soc_port_t port;
   8599 
   8600     pc->size = 0;
   8601     port = pc->port;
   8602     all_cores = PHY84328_CORES(unit, port);
   8603     if (all_cores > PHY84328_MAX_CORES) {
   8604         LOG_ERROR(BSL_LS_SOC_PHY,
   8605                                   (BSL_META_U(unit,
   8606                   "u=%d p=%d: too many cores %d\n"),
   8607                   unit, port, all_cores));
   8608         return SOC_E_NOT_FOUND;
   8609     }
   8610     prim_phy_id = pc->phy_id;
   8611     for (core = 0; core < all_cores; core++) {
   8612         
   8613         /* 
   8614          * During probe, reuse the pc for the port (first core only) as there are no
   8615          * pc's allocated yet for the other cores
   8616          */ 
   8617         pc->phy_id = _phy_84328_phy_id_get(pc, core);
   8618 
   8619         rv = _phy_84328_probe(unit, pc);
   8620         pc->phy_id = prim_phy_id;
   8621         if (rv != SOC_E_NONE) {
   8622             return rv;
   8623         }
   8624        
   8625         /* 
   8626          * Make sure the probed device name for all cores matches the first
   8627          * core device  name 
   8628          */
   8629         if (core == 0) {
   8630             dev_name = pc->dev_name;
   8631         } else if (pc->dev_name != dev_name) {
   8632             LOG_ERROR(BSL_LS_SOC_PHY,
   8633                                   (BSL_META_U(unit,
   8634                       "u=%d p=%d: all cores must have same device: core0=%s != core%d=%s\n"),
   8635                       unit, port, dev_name, core, pc->dev_name));
   8636             return SOC_E_NOT_FOUND;
   8637         }
   8638     }
   8639 
   8640     /* 
   8641      * Allocate one pc + one control block for each core
   8642      */
   8643     pc->size = sizeof(phy84328_dev_desc_t) + ((all_cores - 1) * PHY84328_CORE_STATE_SIZE);
   8644 
   8645     return SOC_E_NONE;
   8646 }
   8647 
   8648 STATIC void
   8649 _phy_84328_init_setup(int unit, soc_port_t port)
   8650 {
   8651     int core, all_cores;
   8652     phy_ctrl_t *core_pc;
   8653     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   8654     
   8655     /*	DBG_FLAGS(pc) = 0; */
   8656 	DBG_FLAGS(pc) = PHY84328_DBG_F_API_SET | PHY84328_DBG_F_DWLD;
   8657 	
   8658     all_cores = PHY84328_CORES(unit, port);
   8659     for (core = 0; core < all_cores; core++) {
   8660         core_pc = PHY84328_CORE_PC(pc, core);
   8661 
   8662         if (core > 0) {
   8663             /* Copy state from core 0 pc to other core pcs */
   8664             sal_memcpy(core_pc, pc , sizeof(phy_ctrl_t));
   8665 
   8666             /* Populate phy_id for core1..core2 */
   8667             core_pc->phy_id = _phy_84328_phy_id_get(pc, core);
   8668         }
   8669 
   8670 
   8671        CORE_NUM(core_pc) = core;
   8672         if (all_cores > 1) {
   8673             core_pc->phy_mode = PHYCTRL_MULTI_CORE_PORT;
   8674         }
   8675     }
   8676 }
   8677 
   8678 STATIC int
   8679 phy_84328_init(int unit, soc_port_t port)
   8680 {
   8681     int rv;
   8682     int pass;
   8683     int core, all_cores;
   8684     phy_ctrl_t *core_pc;
   8685     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   8686 
   8687     pass = PHYCTRL_INIT_STATE(pc);
   8688 
   8689     if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) {
   8690         _phy_84328_init_setup(unit, port);
   8691     }
   8692 
   8693     /*
   8694     if (DBG_FLAGS(pc) & PHY84328_DBG_F_API_SET) {
   8695         bsl_normal(BSL_APPL_SHELL, unit,
   8696                    "%s(%d, %d)\n", FUNCTION_NAME(), unit, port);
   8697     }
   8698     */
   8699 
   8700     all_cores = PHY84328_CORES(unit, port);
   8701     for (core = 0; core < all_cores; core++) {
   8702         core_pc = PHY84328_CORE_PC(pc, core);
   8703 
   8704         PHY84328_CORE_STATE_SET(unit, port, core, pc);
   8705         /* copy init state to core_pc */
   8706         PHYCTRL_INIT_STATE_SET(core_pc, pass);
   8707         rv = _phy_84328_init(unit, port);
   8708         PHY84328_CORE_STATE_SET(unit, port, 0, pc);
   8709 
   8710         if (rv != SOC_E_NONE) {
   8711             return rv;
   8712         }
   8713     }
   8714 
   8715     return SOC_E_NONE;
   8716 }
   8717 
   8718 STATIC int
   8719 _phy84328_init_ucode_bcst(int unit, int port, int cmd)
   8720 {
   8721     int rv;
   8722     int core, all_cores;
   8723     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   8724 
   8725     all_cores = PHY84328_CORES(unit, port);
   8726 
   8727     /*
   8728      * The actual load needs to happen only on the first core as the
   8729      * other cores will be in broadcast mode
   8730      */
   8731     if (cmd == PHYCTRL_UCODE_BCST_LOAD) {
   8732         all_cores = 1;
   8733     }
   8734     for (core = 0; core < all_cores; core++) {
   8735         PHY84328_CORE_STATE_SET(unit, port, core, pc);
   8736         rv = __phy84328_init_ucode_bcst(unit, port, cmd);
   8737         PHY84328_CORE_STATE_SET(unit, port, 0, pc);
   8738         if (rv != SOC_E_NONE) {
   8739             return rv;
   8740         }
   8741     }
   8742 
   8743     return SOC_E_NONE;
   8744 }
   8745 
   8746 STATIC int
   8747 phy_84328_firmware_set(int unit, int port, int offset, uint8 *array,int datalen)
   8748 {
   8749     /*
   8750     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   8751     */
   8752 
   8753     /* 
   8754      * When array==NULL, this function is used to broadcast the firmware.
   8755      * array==NULL should be specified only for internal use
   8756      */
   8757     /*
   8758     if (DBG_FLAGS(pc) & PHY84328_DBG_F_API_SET) {
   8759         bsl_normal(BSL_APPL_SHELL, unit,
   8760                    "%s(%d, %d)\n", FUNCTION_NAME(), unit, port);
   8761     }
   8762     */
   8763 
   8764     if (array == NULL) {
   8765         return _phy84328_init_ucode_bcst(unit, port, offset);
   8766     } else {
   8767         /*
   8768         bsl_warning(BSL__X, unit,
   8769                     "u=%d p=%d firmware download method not supported\n",
   8770                     unit, port);
   8771         */
   8772         return SOC_E_UNAVAIL;
   8773     }
   8774 
   8775     return SOC_E_NONE;
   8776 }
   8777 
   8778 STATIC int
   8779 phy_84328_enable_set(int unit, soc_port_t port, int enable)
   8780 {
   8781     PHY84328_CALL_SET(unit, port, (_phy_84328_enable_set(unit, port, enable)));
   8782 }
   8783 
   8784 STATIC int
   8785 phy_84328_speed_set(int unit, soc_port_t port, int speed)
   8786 {
   8787     PHY84328_CALL_SET(unit, port, (_phy_84328_speed_set(unit, port, speed)));
   8788 }
   8789 
   8790 STATIC int
   8791 phy_84328_speed_get(int unit, soc_port_t port, int *speed)
   8792 {
   8793     int port_speed = 0;
   8794 
   8795     PHY84328_CALL_GET(unit, port, (_phy_84328_speed_get(unit, port, speed)), 
   8796                       speed, port_speed);
   8797 }
   8798 
   8799 STATIC int
   8800 phy_84328_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   8801 {
   8802     PHY84328_CALL_SET(unit, port, (_phy_84328_interface_set(unit, port, pif)));
   8803 }
   8804 
   8805 STATIC int
   8806 phy_84328_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   8807 {
   8808     soc_port_if_t port_pif = 0;
   8809 
   8810     PHY84328_CALL_GET(unit, port, (_phy_84328_interface_get(unit, port, pif)), 
   8811                       pif, port_pif);
   8812 }
   8813 
   8814 STATIC int
   8815 phy_84328_lb_set(int unit, soc_port_t port, int enable)
   8816 {
   8817     PHY84328_CALL_SET(unit, port, (_phy_84328_lb_set(unit, port, enable)));
   8818 }
   8819 
   8820 STATIC int
   8821 phy_84328_lb_get(int unit, soc_port_t port, int *enable)
   8822 {
   8823     int port_enable = 0;
   8824 
   8825     PHY84328_CALL_GET(unit, port, (_phy_84328_lb_get(unit, port, enable)), 
   8826                       enable, port_enable);
   8827 }
   8828 
   8829 STATIC int
   8830 phy_84328_link_get(int unit, soc_port_t port, int *link)
   8831 {
   8832     int port_link = 0;
   8833 
   8834     PHY84328_CALL_GET(unit, port, (_phy_84328_link_get(unit, port, link)), 
   8835                       link, port_link);
   8836 }
   8837 
   8838 
   8839 STATIC int
   8840 phy_84328_an_set(int unit, soc_port_t port, int an)
   8841 {
   8842     PHY84328_CALL_SET(unit, port, (_phy_84328_an_set(unit, port, an)));
   8843 }
   8844 
   8845 
   8846 STATIC int
   8847 phy_84328_control_set(int unit, soc_port_t port,
   8848                       soc_phy_control_t type, uint32 value)
   8849 {
   8850     PHY84328_CALL_SET(unit, port,
   8851                       (phy_84328_control_port_set(unit, port, type, value)));
   8852 }
   8853 
   8854 STATIC int
   8855 phy_84328_control_get(int unit, soc_port_t port, 
   8856                        soc_phy_control_t type, uint32 *value)
   8857 {
   8858     uint32 port_value = 0;
   8859 
   8860     PHY84328_CALL_GET(unit, port,
   8861                       (phy_84328_control_port_get(unit, port, type, value)),
   8862                       value, port_value);
   8863 }
   8864 
   8865 STATIC int
   8866 phy_84328_reg_write(int unit, soc_port_t port, uint32 flags,
   8867                    uint32 phy_reg_addr, uint32 phy_data)
   8868 {
   8869 #ifdef BCM_WARM_BOOT_SUPPORT
   8870     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   8871         return SOC_E_NONE;
   8872     }
   8873 #endif
   8874     PHY84328_CALL_SET(unit, port,
   8875                       (_phy_84328_reg_write(unit, port, 
   8876                        flags, phy_reg_addr, phy_data)));
   8877 }
   8878 
   8879 STATIC int
   8880 phy_84328_reg_read(int unit, soc_port_t port, uint32 flags,
   8881                   uint32 phy_reg_addr, uint32 *phy_data)
   8882 {
   8883     uint32 port_phy_data  = 0;
   8884 
   8885     PHY84328_CALL_GET(unit, port,
   8886                       (_phy_84328_reg_read(
   8887                           unit, port, flags, phy_reg_addr, phy_data)),
   8888                       phy_data, port_phy_data);
   8889 }
   8890 
   8891 STATIC int
   8892 phy_84328_ability_advert_set(int unit, soc_port_t port,
   8893 							 soc_port_ability_t *ability)
   8894 {
   8895     PHY84328_CALL_SET(unit, port,
   8896                       (_phy_84328_ability_advert_set(unit, port, ability)));
   8897 }
   8898 
   8899 STATIC int
   8900 phy_84328_ability_advert_get(int unit, soc_port_t port,
   8901                            soc_port_ability_t *ability)
   8902 {
   8903     int rv;
   8904     int core, all_cores;
   8905     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   8906     soc_port_ability_t port_ability;
   8907 
   8908 
   8909     if (DBG_FLAGS(pc) & PHY84328_DBG_F_API_SET) {
   8910         LOG_INFO(BSL_LS_SOC_PHY,
   8911                       (BSL_META_U(unit,
   8912                    "%s(%d, %d)\n"), FUNCTION_NAME(), unit, port));
   8913     }
   8914 
   8915     all_cores = PHY84328_CORES(unit, port);
   8916     for (core = 0; core < all_cores; core++) {
   8917 
   8918         PHY84328_CORE_STATE_SET(unit, port, core, pc);
   8919         rv = _phy_84328_ability_advert_get(unit, port, ability);
   8920         PHY84328_CORE_STATE_SET(unit, port, 0, pc);
   8921 
   8922         if (rv != SOC_E_NONE) {
   8923             return rv;
   8924         }
   8925 
   8926         if (core > 0) {
   8927             if (sal_memcmp((const void *) &port_ability,
   8928                            (const void *) ability,
   8929                            sizeof(soc_port_ability_t))){
   8930                 /*
   8931                 bsl_error(BSL__X, unit,
   8932                           "84328 %s : ability does not match "
   8933                           "for all cores: u=%d p=%d\n",
   8934                           FUNCTION_NAME(), unit, port );
   8935                 */
   8936             }
   8937         } else if (all_cores > 1) {
   8938             sal_memcpy(&port_ability, ability , sizeof(soc_port_ability_t));
   8939         }
   8940     }
   8941 
   8942     return SOC_E_NONE;
   8943 }
   8944 
   8945 
   8946 STATIC int
   8947 phy_84328_diag_ctrl(int unit, soc_port_t port, uint32 inst, int op_type,  int op_cmd,  void *arg)
   8948 {
   8949 	int rv = SOC_E_NONE;
   8950     int core, all_cores;
   8951     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   8952     uint32 port_arg;
   8953 
   8954 
   8955     if (DBG_FLAGS(pc) & PHY84328_DBG_F_API_SET) {
   8956         LOG_INFO(BSL_LS_SOC_PHY,
   8957                       (BSL_META_U(unit,
   8958                    "%s(%d, %d)\n"), FUNCTION_NAME(), unit, port));
   8959     }
   8960 
   8961     all_cores = PHY84328_CORES(unit, port);
   8962     for (core = 0; core < all_cores; core++) {
   8963 
   8964         PHY84328_CORE_STATE_SET(unit, port, core, pc);
   8965 
   8966         switch(op_type)
   8967         {
   8968             case  PHY_DIAG_CTRL_SET:
   8969             case  PHY_DIAG_CTRL_CMD:
   8970                 rv =
   8971                 (_phy_84328_diag_ctrl(unit, port, inst, op_type,  op_cmd, arg));
   8972                 break;
   8973 
   8974             case  PHY_DIAG_CTRL_GET:
   8975                 rv =
   8976                 (_phy_84328_diag_ctrl(unit, port, inst, op_type,  op_cmd, arg));
   8977 
   8978                 if (core > 0) {
   8979                     if (sal_memcmp((const void *) &port_arg,
   8980                                    (const void *) arg,
   8981                                    sizeof(port_arg))){
   8982                         LOG_ERROR(BSL_LS_SOC_PHY,
   8983                                   (BSL_META_U(unit,
   8984                                   "84328 %s : arg does not match "
   8985                                   "for all cores: u=%d p=%d\n"),
   8986                                   FUNCTION_NAME(), unit, port ));
   8987                     }
   8988                 } else if (all_cores > 1) {
   8989                     sal_memcpy(&port_arg, arg , sizeof(port_arg));
   8990                 }
   8991                 break;
   8992 
   8993             default:
   8994                 LOG_INFO(BSL_LS_SOC_PHY,
   8995                       (BSL_META_U(unit,
   8996                            "84328 diag_ctrl bad operation: u=%d p=%d ctrl=0x%x\n"), 
   8997                            unit, port, op_cmd));
   8998                 rv = SOC_E_UNAVAIL;
   8999                 break;
   9000         }
   9001 
   9002         PHY84328_CORE_STATE_SET(unit, port, 0, pc);
   9003 
   9004         if (rv != SOC_E_NONE) {
   9005             return rv;
   9006         }
   9007 
   9008     }
   9009     return SOC_E_NONE;
   9010 }
   9011 
   9012 
   9013 STATIC int
   9014 phy_84328_ability_remote_get(int unit, soc_port_t port, 
   9015                             soc_port_ability_t *ability)
   9016 {
   9017     int rv;
   9018     int core, all_cores;
   9019     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   9020     soc_port_ability_t port_ability;
   9021 
   9022 
   9023     if (DBG_FLAGS(pc) & PHY84328_DBG_F_API_SET) {
   9024         LOG_INFO(BSL_LS_SOC_PHY,
   9025                       (BSL_META_U(unit,
   9026                    "%s(%d, %d)\n"), FUNCTION_NAME(), unit, port));
   9027     }
   9028 
   9029     all_cores = PHY84328_CORES(unit, port);
   9030     for (core = 0; core < all_cores; core++) {
   9031 
   9032         PHY84328_CORE_STATE_SET(unit, port, core, pc);
   9033         rv = _phy_84328_ability_remote_get(unit, port, ability);
   9034         PHY84328_CORE_STATE_SET(unit, port, 0, pc);
   9035 
   9036         if (rv != SOC_E_NONE) {
   9037             return rv;
   9038         }
   9039 
   9040         if (core > 0) {
   9041             if (sal_memcmp((const void *) &port_ability,
   9042                            (const void *) ability,
   9043                            sizeof(soc_port_ability_t))){
   9044                 /*
   9045                 LOG_ERROR(BSL_LS_SOC_PHY,
   9046                                   (BSL_META_U(unit,
   9047                           "84328 %s : ability does not match "
   9048                           "for all cores: u=%d p=%d\n"),
   9049                           FUNCTION_NAME(), unit, port ));
   9050                 */
   9051             }
   9052         } else if (all_cores > 1) {
   9053             sal_memcpy(&port_ability, ability , sizeof(soc_port_ability_t));
   9054         }
   9055     }
   9056 
   9057     return SOC_E_NONE;
   9058 }
   9059 
   9060 /*
   9061  * Variable:
   9062  *    phy_84328_drv
   9063  * Purpose:
   9064  *    Phy Driver for 40G PHY.
   9065  */
   9066 phy_driver_t phy_84328drv_xe = {
   9067     "84328 40-Gigabit PHY Driver",
   9068     phy_84328_init,        /* Init */
   9069     phy_null_reset,       /* Reset (dummy) */
   9070     phy_84328_link_get,    /* Link get   */
   9071     phy_84328_enable_set,  /* Enable set */
   9072     phy_null_enable_get,  /* Enable get */
   9073     phy_null_set,         /* Duplex set */
   9074     phy_null_one_get,     /* Duplex get */
   9075     phy_84328_speed_set,   /* Speed set  */
   9076     phy_84328_speed_get,   /* Speed get  */
   9077     phy_null_set,         /* Master set */
   9078     phy_null_zero_get,    /* Master get */
   9079     phy_84328_an_set,      /* ANA set */
   9080     phy_84328_an_get,      /* ANA get */
   9081     NULL,                 /* Local Advert set */
   9082     NULL,                 /* Local Advert get */
   9083     phy_null_mode_get,    /* Remote Advert get */
   9084     phy_84328_lb_set,      /* PHY loopback set */
   9085     phy_84328_lb_get,      /* PHY loopback set */
   9086     phy_84328_interface_set, /* IO Interface set */
   9087     phy_84328_interface_get, /* IO Interface get */
   9088     NULL,   /* PHY abilities mask */
   9089     NULL,
   9090     NULL,
   9091     phy_null_mdix_set,
   9092     phy_null_mdix_get,
   9093     phy_null_mdix_status_get,
   9094     NULL,
   9095     NULL,
   9096     phy_null_medium_get,
   9097     NULL,                    /* phy_cable_diag  */
   9098     NULL,                    /* phy_link_change */
   9099     phy_84328_control_set,    /* phy_control_set */
   9100     phy_84328_control_get,    /* phy_control_get */
   9101     phy_84328_reg_read,       /* phy_reg_read */
   9102     phy_84328_reg_write,      /* phy_reg_write */
   9103     NULL,                    /* phy_reg_modify */
   9104     NULL,                    /* phy_notify */
   9105     phy_84328_probe,         /* pd_probe  */
   9106     phy_84328_ability_advert_set,  /* pd_ability_advert_set */
   9107     phy_84328_ability_advert_get,  /* pd_ability_advert_get */
   9108     phy_84328_ability_remote_get,  /* pd_ability_remote_get */
   9109     phy_84328_ability_local_get,   /* pd_ability_local_get  */
   9110     phy_84328_firmware_set,        /* pd_firmware_set */
   9111     NULL,                          /* pd_timesync_config_set */
   9112     NULL,                          /* pd_timesync_config_get */
   9113     NULL,                          /* pd_timesync_control_set */
   9114     NULL,                          /* pd_timesync_control_get */
   9115     phy_84328_diag_ctrl,            /* .pd_diag_ctrl */
   9116     NULL,                          /* pd_lane_control_set */
   9117     NULL,                          /* pd_lane_control_get */
   9118     NULL,                          /* pd_lane_reg_read */
   9119     NULL,                          /* pd_lane_reg_write */
   9120     NULL,                          /* pd_oam_config_set */
   9121     NULL,                          /* pd_oam_config_get */
   9122     NULL,                          /* pd_oam_control_set */
   9123     NULL,                          /* pd_oam_control_get */
   9124     NULL,                          /* pd_timesync_enhanced_capture_get */
   9125     NULL,                          /* pd_multi_get */
   9126     phy_84328_precondition_before_probe /* pd_precondition_before_probe */
   9127 };
   9128 #else /* INCLUDE_PHY_84328 */
   9129 int _phy_84328_not_empty;
   9130 #endif /* INCLUDE_PHY_84328 */