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

phy8481.c (396628B)


      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:        phy8481.c
      8  * Purpose:    PHY Driver support for Broadcom 8481/848xx Serial 10Gig
      9  *             transceiver with XAUI/XFI interface.
     10  */
     11 
     12 #ifdef BCM_PLP_BASE_T_PHY  /* ePIL standalone driver */
     13 #define  PHYMOD_SUPPORT
     14 #define  INCLUDE_PHY_8481
     15 #else    /* switch SDK driver */
     16 #define  BCM848XX_DIAG_DSC_SUPPORT
     17 #endif /* BCM_PLP_BASE_T_PHY */
     18 
     19 #define  BCM848XX_STATE_MFG_DIAG_SUPPORT
     20 
     21 #include <sal/types.h>
     22 #include <shared/bsl.h>
     23 #include <soc/drv.h>
     24 #include <soc/debug.h>
     25 #include <soc/error.h>
     26 #include <soc/phyreg.h>
     27 
     28 #include <soc/phy.h>
     29 #include <soc/phy/phyctrl.h>
     30 #include <soc/phy/drv.h>
     31 
     32 #ifdef BCM_PLP_BASE_T_PHY     /**  ePIL PLP standalone driver  **/
     33     #define  PHYMOD_SUPPORT
     34     #define  INCLUDE_PHY_8481
     35     #include "legacy.h"
     36     #include <soc/property.h>
     37 #else                         /**  switch SDK driver           **/
     38     #define  BCM848XX_DIAG_DSC_SUPPORT
     39     #include <soc/drv.h>
     40     #include <soc/debug.h>
     41     #include "phydefs.h"      /* Must include before other phy related includes */
     42     #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
     43     #include "phyident.h"
     44     #include "phyreg.h"
     45     #include "phynull.h"
     46     #include "phyxehg.h"
     47 #endif /* BCM_PLP_BASE_T_PHY */
     48 
     49 #define  BCM848XX_STATE_MFG_DIAG_SUPPORT
     50 
     51 #if defined(INCLUDE_PHY_8481)
     52 
     53 #include "phy8481.h"
     54 
     55 /*
     56 #define PHY8481_ARM_MEM_DEBUG
     57 #define PHY8481_DEBUG_AUTOMEDIUM
     58 #define PHY8481_FW_DEBUG
     59 #define PHY8185X_DEBUG_CMD_HANDLER
     60 */
     61 extern uint8 bcm_8481_firmware[];
     62 extern int bcm_8481_firmware_size;
     63 
     64 extern uint8 bcm_8482A0_firmware[];
     65 extern int bcm_8482A0_firmware_size;
     66 
     67 extern uint8 bcm_8482B0_firmware[];
     68 extern int bcm_8482B0_firmware_size;
     69 
     70 extern uint8 bcm_8482B1_firmware[];
     71 extern int bcm_8482B1_firmware_size;
     72 
     73 extern uint8 bcm_84833_firmware[];
     74 extern int bcm_84833_firmware_size;
     75 
     76 extern uint8 bcm_84844_firmware[];
     77 extern int bcm_84844_firmware_size;
     78 
     79 extern uint8 bcm_84858_firmware[];
     80 extern int bcm_84858_firmware_size;
     81 
     82 extern uint8 bcm_8486x_firmware[];
     83 extern int bcm_8486x_firmware_size;
     84 
     85 extern uint8 bcm_84888A0_firmware[];
     86 extern int bcm_84888A0_firmware_size;
     87 
     88 extern uint8 bcm_84888B0_firmware[];
     89 extern int bcm_84888B0_firmware_size;
     90 
     91 extern void get_dsc_param_koi(void);
     92 extern void get_dsc_param_orca(void);
     93 
     94 extern void set_pc(phy_ctrl_t *pc);
     95 extern void set_intpc(phy_ctrl_t *pc);
     96 
     97 #define SOC_PORT_MEDIUM_XAUI      SOC_PORT_MEDIUM_FIBER
     98 #define PHY_FLAGS_XAUI            PHY_FLAGS_FIBER
     99 #define PHY_XAUI_MODE(unit, port) PHY_FIBER_MODE((unit), (port))
    100 #define SOC_PA_MEDIUM_XAUI        SOC_PA_MEDIUM_FIBER
    101 
    102 #define PHY8483X_MFG_TEST_SUPPORT   0x1
    103 #define PHY8483X_STATE_TEST_SUPPORT 0x2
    104 #define PHY8483X_FULL_SNR_SUPPORT   0x4
    105 #define PHY8483X_TIMESYNC_ENABLED   0x8
    106 #define PHY8483X_ATOMIC_ACCESS_SHD 0x10
    107 
    108 /* PRBS */
    109 #define PHY84834_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS         0x0135
    110 #define PHY84834_40G_PRBS31             (1 << 7)               
    111 #define PHY84834_40G_PRBS9              (1 << 6) 
    112 #define PHY84834_40G_PRBS_TX_ENABLE     (1 << 3) 
    113 #define PHY84834_40G_PRBS_RX_ENABLE     (1 << 0) 
    114 #define PHY84834_40G_PRBS_ENABLE     (PHY84834_40G_PRBS_RX_ENABLE | \
    115 	PHY84834_40G_PRBS_TX_ENABLE)
    116 
    117 #define PHY84834_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0            0x0140 
    118 #define PHY84834_USER_PRBS_CONTROL_0_REGISTER                       0xCD14 
    119 #define PHY84834_USER_PRBS_TX_INVERT   (1 << 4)
    120 #define PHY84834_USER_PRBS_RX_INVERT   (1 << 15)
    121 #define PHY84834_USER_PRBS_INVERT      (1 << 4 | 1 << 15)
    122 #define PHY84834_USER_PRBS_ENABLE      (1 << 7)
    123 #define PHY84834_USER_PRBS_TYPE_MASK   (0x7)
    124 
    125 #define PHY84834_USER_PRBS_STATUS_0_REGISTER                        0xCD15 
    126 #define PHY84834_GENSIG_8071_REGISTER                               0xCD16 
    127 #define PHY84834_RESET_CONTROL_REGISTER                             0xCD17 
    128 
    129 #define PHY8485X_MDIO_CONTROL_REGISTER                              0x4110
    130 #define PHY8485X_TX_PRBS_REGISTER                                   0xD0E1
    131 #define PHY848XX_TX_PRBS_ADDR32_REGISTER                            0xD203A1C2
    132 #define PHY8485X_RX_PRBS_REGISTER                                   0xD0D1
    133 #define PHY848XX_RX_PRBS_ADDR32_REGISTER                            0xD203A1A2
    134 #define PHY8485X_PRBS_STATUS_REGISTER                               0xD0D9
    135 #define PHY8485X_PRBS_ERR_COUNT_MSB_REGSTER                         0xD0DA
    136 #define PHY8485X_PRBS_ERR_COUNT_LSB_REGSTER                         0xD0DB
    137 #define PHY8488X_EN_CLK_MDC_XFI                                     0x8003
    138 
    139 #define PHY8485X_USER_PRBS_TYPE_MASK                                0x1
    140 #define PHY8485X_USER_PRBS_ENABLE                                   0x1
    141 
    142 #define PHY8488X_MDIO_CLOCK_CONTROL_REGISTER         0x8003
    143 #define PHY8488X_EN_CLK_MDC_XFI_SHIFT                0
    144 #define PHY8488X_EN_CLK_MDC_XFI_MASK                 BIT(PHY8488X_EN_CLK_MDC_XFI_SHIFT)
    145 #define PHY84834_DIAG_CMD_ACCESS_32BIT_XFI_ADDR      0xC020
    146 #define PHY848XX_PRBS_TX_ADDR32_REGISTER             0xD203A1C2
    147 #define PHY848XX_PRBS_RX_ADDR32_REGISTER             0xD203A1A2
    148 
    149 #define ADDR32BIT_HIGH(_addr32)                      ((uint16) ((_addr32) >> 16))
    150 #define ADDR32BIT_LOW(_addr32)                       ((uint16) ((_addr32) & 0xFFFF))
    151 #define ADDR32BIT_WRITE                              0x0000
    152 #define ADDR32BIT_READ                               0x0001
    153 
    154 #define PHY848XX_PRBS_INVERT_SHFT                    4
    155 #define PHY848XX_PRBS_POLYNOMIAL_SHFT                1
    156 #define PHY848XX_PRBS_ENABLE_SHFT                    0
    157 #define PHY848XX_PRBS_INVERT_MASK                    (0x1U << PHY848XX_PRBS_INVERT_SHFT)
    158 #define PHY848XX_PRBS_POLYNOMIAL_MASK                (0x7U << PHY848XX_PRBS_POLYNOMIAL_SHFT)
    159 #define PHY848XX_PRBS_ENABLE_MASK                    (0x1U << PHY848XX_PRBS_ENABLE_SHFT)
    160 #define PHY848XX_PRBS_PARAMETER_MASK                 (PHY848XX_PRBS_INVERT_MASK |  \
    161                                                       PHY848XX_PRBS_POLYNOMIAL_MASK)
    162 
    163 
    164 
    165 #define REG_GROUP_SHADOW18                                          0x18
    166 #define REG_GROUP_SHADOW1c                                          0x1c
    167 #define REG_GROUP_SHADOW_MISC_REG                                   0x17
    168 #define REG_GROUP_SHADOW_EXP_REG                                    0xf
    169 
    170 #define PHY8485X_PREEMPH_GET_PRE_TAP(_val) \
    171         ((_val) & 0xf)
    172 
    173 #define PHY8485X_PREEMPH_CTRL_MAIN_TAP_SHFT     4
    174 #define PHY8485X_PREEMPH_GET_MAIN_TAP(_val) \
    175         (((_val) >> PHY8485X_PREEMPH_CTRL_MAIN_TAP_SHFT) & 0x3f)
    176 
    177 #define PHY8485X_PREEMPH_CTRL_POST_TAP1_SHFT    10
    178 #define PHY8485X_PREEMPH_GET_POST_TAP1(_val) \
    179         (((_val) >> PHY8485X_PREEMPH_CTRL_POST_TAP1_SHFT) & 0x1f)
    180 
    181 #define PHY8485X_PREEMPH_CTRL_POST_TAP2_SHFT    16
    182 #define PHY8485X_PREEMPH_GET_POST_TAP2(_val) \
    183         (((_val) >> PHY8485X_PREEMPH_CTRL_POST_TAP2_SHFT) & 0x7)
    184 
    185 #define PHY8485X_PREEMPH_CTRL_HPF_EN_SHFT       15
    186 #define PHY8485X_PREEMPH_GET_HPF_EN(_val) \
    187         (((_val) >> PHY8485X_PREEMPH_CTRL_HPF_EN_SHFT) & 0x1)
    188 
    189 /* 5 bits pre_tap for SOC_PHY_CONTROL_PREEMPHASIS */
    190 #define PHY8488X_PREEMPH_CTL_PRE_TAP_MASK       0x1f
    191 #define PHY8488X_PREEMPH_CTL_PRE_TAP_SHFT       0
    192 #define PHY8488X_PREEMPH_GET_PRE_TAP(_val) \
    193         (((_val) >> PHY8488X_PREEMPH_CTL_PRE_TAP_SHFT) &  PHY8488X_PREEMPH_CTL_PRE_TAP_MASK)
    194 #define PHY8488X_PREEMPH_SET_PRE_TAP(_val) \
    195         (((_val)  & PHY8488X_PREEMPH_CTL_PRE_TAP_MASK) << PHY8488X_PREEMPH_CTL_PRE_TAP_SHFT)
    196 /* 7 bits main_tap for SOC_PHY_CONTROL_PREEMPHASIS */
    197 #define PHY8488X_PREEMPH_CTL_MAIN_TAP_MASK      0x3f
    198 #define PHY8488X_PREEMPH_CTL_MAIN_TAP_SHFT      5
    199 #define PHY8488X_PREEMPH_GET_MAIN_TAP(_val) \
    200         (((_val) >> PHY8488X_PREEMPH_CTL_MAIN_TAP_SHFT) &  PHY8488X_PREEMPH_CTL_MAIN_TAP_MASK)
    201 #define PHY8488X_PREEMPH_SET_MAIN_TAP(_val) \
    202         (((_val)  & PHY8488X_PREEMPH_CTL_MAIN_TAP_MASK) << PHY8488X_PREEMPH_CTL_MAIN_TAP_SHFT)
    203 /* 6 bits post1_tap for SOC_PHY_CONTROL_PREEMPHASIS */
    204 #define PHY8488X_PREEMPH_CTL_POST1_MASK         0x3f
    205 #define PHY8488X_PREEMPH_CTL_POST1_SHFT         12
    206 #define PHY8488X_PREEMPH_GET_POST1_TAP(_val) \
    207         (((_val) >> PHY8488X_PREEMPH_CTL_POST1_SHFT) &  PHY8488X_PREEMPH_CTL_POST1_MASK)
    208 #define PHY8488X_PREEMPH_SET_POST1_TAP(_val) \
    209         (((_val)  & PHY8488X_PREEMPH_CTL_POST1_MASK) << PHY8488X_PREEMPH_CTL_POST1_SHFT)
    210 /* 5 bits post2_tap for SOC_PHY_CONTROL_PREEMPHASIS  (signed) */
    211 #define PHY8488X_PREEMPH_CTL_POST2_MASK         0x1f
    212 #define PHY8488X_PREEMPH_CTL_POST2_SHFT         18
    213 #define PHY8488X_PREEMPH_GET_POST2_TAP(_val) \
    214         (((_val) >> PHY8488X_PREEMPH_CTL_POST2_SHFT) &  PHY8488X_PREEMPH_CTL_POST2_MASK)
    215 #define PHY8488X_PREEMPH_SET_POST2_TAP(_val) \
    216         (((_val)  & PHY8488X_PREEMPH_CTL_POST2_MASK) << PHY8488X_PREEMPH_CTL_POST2_SHFT)
    217 /* 4 bits post3_tap for SOC_PHY_CONTROL_PREEMPHASIS  (signed) */
    218 #define PHY8488X_PREEMPH_CTL_POST3_MASK         0x0f
    219 #define PHY8488X_PREEMPH_CTL_POST3_SHFT         24
    220 #define PHY8488X_PREEMPH_GET_POST3_TAP(_val) \
    221         (((_val) >> PHY8488X_PREEMPH_CTL_POST3_SHFT) &  PHY8488X_PREEMPH_CTL_POST3_MASK)
    222 #define PHY8488X_PREEMPH_SET_POST3_TAP(_val) \
    223         (((_val)  & PHY8488X_PREEMPH_CTL_POST3_MASK) << PHY8488X_PREEMPH_CTL_POST3_SHFT)
    224 
    225 /* typedefs */
    226 typedef struct {
    227     int           flags;
    228     soc_timeout_t to;
    229     uint8         *firmware;
    230     int           firmware_len;
    231     int           dl_dividend;
    232     int           dl_divisor;
    233     uint32        phy_ext_rom_boot;
    234     int           sys_forced_cl72;
    235     int           link_down;
    236     int           lb_speed;    /* intended speed for PHY loopback */
    237 } PHY8481_PRIV_t;
    238 
    239 #define LINK_DOWN(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->link_down)
    240 #define FLAGS(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->flags)
    241 #define TO(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->to)
    242 #define FIRMWARE(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->firmware)
    243 #define FIRMWARE_LEN(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->firmware_len)
    244 #define DL_DIVIDEND(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->dl_dividend)
    245 #define DL_DIVISOR(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->dl_divisor)
    246 #define PHY_EXT_ROM_BOOT(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->phy_ext_rom_boot)
    247 #define SYS_FORCED_CL72(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->sys_forced_cl72)
    248 #define LB_SPEED(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->lb_speed)
    249 
    250 #define PHY_ADDR_NONE  0xFF
    251 #define NXT_PC(pc) ((phy_ctrl_t *)((pc)->driver_data))
    252 #define LAST_IN_CHAIN(pc) (PHY_IS_CHAINED((pc)->unit, (pc)->port) && !NXT_PC(pc))
    253 
    254 #define PHYDRV_CALL_NOARG(pc,name) \
    255      do { \
    256         if (pc->driver_data) { \
    257 	    int rv; \
    258 	    phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \
    259 	    EXT_PHY_SW_STATE(pc->unit,pc->port) = (phy_ctrl_t *)(pc->driver_data); \
    260             rv = name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port); \
    261 	    EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \
    262 	    if (SOC_FAILURE(rv)) { \
    263 	        return rv; \
    264 	    } \
    265        } \
    266     } while(0)
    267 
    268 #define PHYDRV_CALL_ARG1(pc,name,arg0) \
    269     do { \
    270        if (pc->driver_data) { \
    271 	   int rv; \
    272 	   phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \
    273 	   EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \
    274            rv = name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit, \
    275 		(pc)->port,arg0); \
    276 	   EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \
    277 	   if (SOC_FAILURE(rv)) { \
    278 	       return rv; \
    279 	   } \
    280        } \
    281     } while(0)
    282 
    283 #define PHYDRV_CALL_ARG2(pc,name,arg0,arg1) \
    284     do { \
    285        if (pc->driver_data) { \
    286 	   int rv; \
    287 	   phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \
    288 	   EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \
    289            rv=name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port,arg0, \
    290 			arg1); \
    291 	   EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \
    292 	   if (SOC_FAILURE(rv)) { \
    293 	       return rv; \
    294 	   } \
    295        } \
    296     } while(0)
    297 
    298 #define PHYDRV_CALL_ARG3(pc,name,arg0,arg1,arg2) \
    299     do { \
    300        if (pc->driver_data) { \
    301            int rv; \
    302            phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \
    303            EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \
    304            rv=name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port,arg0, \
    305                         arg1,arg2); \
    306            EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \
    307            if (SOC_FAILURE(rv)) { \
    308                return rv; \
    309            } \
    310        } \
    311     } while(0)
    312 
    313 #define PHYDRV_CALL_ARG4(pc,name,arg0,arg1,arg2,arg3) \
    314     do { \
    315        if (pc->driver_data) { \
    316            int rv; \
    317            phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \
    318            EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \
    319            rv=name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port,arg0, \
    320                         arg1,arg2,arg3); \
    321            EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \
    322            if (SOC_FAILURE(rv)) { \
    323                return rv; \
    324            } \
    325        } \
    326     } while(0)
    327 
    328 /* default MDIO addresses of phy device on the xaui port, per port based*/
    329 static uint8 ext_phy_dft_addr1[] = {
    330     PHY_ADDR_NONE,  /* 0  */
    331     PHY_ADDR_NONE,  /* 1  */
    332     PHY_ADDR_NONE,  /* 2  */
    333     PHY_ADDR_NONE,  /* 3  */
    334     PHY_ADDR_NONE,  /* 4  */
    335     PHY_ADDR_NONE,  /* 5  */
    336     PHY_ADDR_NONE,  /* 6  */
    337     PHY_ADDR_NONE,  /* 7  */
    338     PHY_ADDR_NONE,  /* 8  */
    339     PHY_ADDR_NONE,  /* 9  */
    340     PHY_ADDR_NONE,  /* 10  */
    341     PHY_ADDR_NONE,  /* 11  */
    342     PHY_ADDR_NONE,  /* 12  */
    343     PHY_ADDR_NONE,  /* 13  */
    344     PHY_ADDR_NONE,  /* 14  */
    345     PHY_ADDR_NONE,  /* 15  */
    346     PHY_ADDR_NONE,  /* 16  */
    347     PHY_ADDR_NONE,  /* 17  */
    348     PHY_ADDR_NONE,  /* 18  */
    349     PHY_ADDR_NONE,  /* 19  */
    350     PHY_ADDR_NONE,  /* 20  */
    351     PHY_ADDR_NONE,  /* 21  */
    352     PHY_ADDR_NONE,  /* 22  */
    353     PHY_ADDR_NONE,  /* 23  */
    354     PHY_ADDR_NONE,  /* 24  */
    355     PHY_ADDR_NONE,  /* 25  */
    356     PHY_ADDR_NONE,  /* 26  */
    357     PHY_ADDR_NONE,  /* 27  */
    358     PHY_ADDR_NONE,  /* 28  */
    359     PHY_ADDR_NONE,  /* 29  */
    360     PHY_ADDR_NONE,  /* 30  */
    361     PHY_ADDR_NONE,  /* 31  */
    362     PHY_ADDR_NONE,  /* 32  */
    363     PHY_ADDR_NONE,  /* 33  */
    364     PHY_ADDR_NONE,  /* 34  */
    365     PHY_ADDR_NONE,  /* 35  */
    366     PHY_ADDR_NONE,  /* 36  */
    367     PHY_ADDR_NONE   /* 37  */
    368 };
    369 
    370 #define PHY_FW_HANDSHAKE(unit, port) \
    371     do { \
    372         if (PHY_HS_CAPABLE(unit, port)) { \
    373             soc_timeout_t  to; \
    374             uint16         status; \
    375             int            rv; \
    376             phy_ctrl_t    *pc = EXT_PHY_SW_STATE(unit, port); \
    377             sal_usleep(100); \
    378             soc_timeout_init(&to, 2000000, 0); \
    379             do { \
    380                 rv = READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400e, &status); \
    381                 if (((status & 0x2) == 0) || SOC_FAILURE(rv)) { \
    382                     break; \
    383                 } \
    384             } while (!soc_timeout_check(&to)); \
    385             if (((status & 0x2) != 0) && (status != 0xffff)) { \
    386                 LOG_WARN(BSL_LS_SOC_PHY, \
    387                          (BSL_META_U(unit, \
    388                                      "PHY8481 firmware handshake failed: u=%d p=%d status=0x%04x\n"), \
    389                           unit, port, status)); \
    390             } \
    391         } else { \
    392             sal_usleep(700000); \
    393         } \
    394     } while (0)
    395 
    396 #define PHY_IS_BCM84823(_pc)   ( PHY_MODEL_CHECK((_pc), \
    397                                                  PHY_BCM84823_OUI, \
    398                                                  PHY_BCM84823_MODEL) )
    399 
    400 #define PHY_IS_BCM84833(_pc)   ( PHY_MODEL_CHECK((_pc), \
    401                                                  PHY_BCM84833_OUI, \
    402                                                  PHY_BCM84833_MODEL) )
    403 
    404 #define PHY_IS_BCM84834(_pc)   ( PHY_MODEL_CHECK((_pc), \
    405                                                  PHY_BCM84834_OUI, \
    406                                                  PHY_BCM84834_MODEL) )
    407 
    408 #define PHY_IS_BCM84844(_pc)   ( PHY_MODEL_CHECK((_pc), \
    409                                                  PHY_BCM84844_OUI, \
    410                                                  PHY_BCM84844_MODEL) )
    411 
    412 #define PHY_IS_BCM8484X_A0(_pc) (PHY_IS_BCM8484X(_pc) \
    413                                    && ((_pc)->phy_rev == 0x8 ))
    414 
    415 
    416 #define PHY_IS_BCM84836(_pc)   ( PHY_MODEL_CHECK((_pc), \
    417                                                  PHY_BCM84836_OUI, \
    418                                                  PHY_BCM84836_MODEL) )
    419 
    420 #define PHY_IS_BCM84846(_pc)   ( PHY_MODEL_CHECK((_pc), \
    421                                                  PHY_BCM84846_OUI, \
    422                                                  PHY_BCM84846_MODEL) )
    423 
    424 #define PHY_IS_BCM84848(_pc)   ( PHY_MODEL_CHECK((_pc), \
    425                                                  PHY_BCM84848_OUI, \
    426                                                  PHY_BCM84848_MODEL) )
    427 
    428 #define PHY_IS_BCM8483X(_pc) \
    429                                ( ((_pc)->phy_oui == PHY_BCM8483X_OUI) && \
    430                                  (((_pc)->phy_model == PHY_BCM84833_MODEL) || \
    431                                   ((_pc)->phy_model == PHY_BCM84834_MODEL) || \
    432                                   ((_pc)->phy_model == PHY_BCM84835_MODEL) || \
    433                                   ((_pc)->phy_model == PHY_BCM84836_MODEL)) )
    434 
    435 #define PHY_IS_BCM8484X(_pc) \
    436                                ( ((_pc)->phy_oui == PHY_BCM8484X_OUI) && \
    437                                  (((_pc)->phy_model == PHY_BCM84844_MODEL) || \
    438                                   ((_pc)->phy_model == PHY_BCM84848_MODEL) || \
    439                                   ((_pc)->phy_model == PHY_BCM84846_MODEL)) )
    440 
    441 #define PHY_IS_BCM84858(_pc)   ( PHY_MODEL_CHECK((_pc), \
    442                                                  PHY_BCM84858_OUI, \
    443                                                  PHY_BCM84858_MODEL) )
    444 
    445 #define PHY_IS_BCM84856(_pc)   ( PHY_MODEL_CHECK((_pc), \
    446                                                  PHY_BCM84856_OUI, \
    447                                                  PHY_BCM84856_MODEL) )
    448 
    449 #define PHY_IS_BCM8485X(_pc) \
    450                                ( ((_pc)->phy_oui == PHY_BCM8485X_OUI) && \
    451                                  (((_pc)->phy_model == PHY_BCM84858_MODEL) || \
    452                                   ((_pc)->phy_model == PHY_BCM84856_MODEL)) )
    453 #define PHY_IS_BCM8486X(_pc) \
    454                                ( ((_pc)->phy_oui == PHY_BCM8486X_OUI) && \
    455                                  (((_pc)->phy_model == PHY_BCM84860_MODEL) || \
    456                                   ((_pc)->phy_model == PHY_BCM84861_MODEL) || \
    457                                   ((_pc)->phy_model == PHY_BCM84864_MODEL) || \
    458                                   ((_pc)->phy_model == PHY_BCM84868_MODEL)) )
    459 
    460 #define PHY_IS_BCM84888(_pc)   ( PHY_MODEL_CHECK((_pc), \
    461                                  PHY_BCM84888_OUI, \
    462                                  PHY_BCM84888_MODEL) )
    463 
    464 #define PHY_IS_BCM84884(_pc)   ( PHY_MODEL_CHECK((_pc), \
    465                                  PHY_BCM84884_OUI, \
    466                                  PHY_BCM84884_MODEL) )
    467 
    468 #define PHY_IS_BCM84888E(_pc)   ( PHY_MODEL_CHECK((_pc), \
    469                                  PHY_BCM84888E_OUI, \
    470                                  PHY_BCM84888E_MODEL) )
    471 
    472 #define PHY_IS_BCM84884E(_pc)   ( PHY_MODEL_CHECK((_pc), \
    473                                  PHY_BCM84884E_OUI, \
    474                                  PHY_BCM84884E_MODEL) )
    475 
    476 #define PHY_IS_BCM84881(_pc)   ( PHY_MODEL_CHECK((_pc), \
    477                                  PHY_BCM84881_OUI, \
    478                                  PHY_BCM84881_MODEL) )
    479 
    480 #define PHY_IS_BCM84880(_pc)   ( PHY_MODEL_CHECK((_pc), \
    481                                  PHY_BCM84880_OUI, \
    482                                  PHY_BCM84880_MODEL) )
    483 
    484 #define PHY_IS_BCM84888S(_pc)   ( PHY_MODEL_CHECK((_pc), \
    485                                  PHY_BCM84888S_OUI, \
    486                                  PHY_BCM84888S_MODEL) )
    487 
    488 #define PHY_IS_BCM84885(_pc)   ( PHY_MODEL_CHECK((_pc), \
    489                                  PHY_BCM84885_OUI, \
    490                                  PHY_BCM84885_MODEL) )
    491 
    492 #define PHY_IS_BCM84886(_pc)   ( PHY_MODEL_CHECK((_pc), \
    493                                  PHY_BCM84886_OUI, \
    494                                  PHY_BCM84886_MODEL) )
    495 
    496 #define PHY_IS_BCM84887(_pc)   ( PHY_MODEL_CHECK((_pc), \
    497                                  PHY_BCM84887_OUI, \
    498                                  PHY_BCM84887_MODEL) )
    499 
    500 #define PHY_IS_BCM8488X(_pc) \
    501                                ( ((_pc)->phy_oui == PHY_BCM8488X_OUI) && \
    502                                  (((_pc)->phy_model == PHY_BCM84888_MODEL) || \
    503                                   ((_pc)->phy_model == PHY_BCM84884_MODEL) || \
    504                                   ((_pc)->phy_model == PHY_BCM84888E_MODEL) || \
    505                                   ((_pc)->phy_model == PHY_BCM84881_MODEL) || \
    506                                   ((_pc)->phy_model == PHY_BCM84880_MODEL) || \
    507                                   ((_pc)->phy_model == PHY_BCM84884E_MODEL) || \
    508                                   ((_pc)->phy_model == PHY_BCM84888S_MODEL) || \
    509                                   ((_pc)->phy_model == PHY_BCM84885_MODEL) || \
    510                                   ((_pc)->phy_model == PHY_BCM84886_MODEL) || \
    511                                   ((_pc)->phy_model == PHY_BCM84887_MODEL) ) )
    512 
    513 #define PHY_IS_BCM8488X_A0(_pc) \
    514                                ( PHY_IS_BCM8488X(_pc) && \
    515                                      ((_pc)->phy_rev == 0x0) )
    516 
    517 #define PHY_IS_BCM8486X_AND_UP(_pc) \
    518                                ( PHY_IS_BCM8486X((_pc)) || \
    519                                  PHY_IS_BCM8488X(_pc) )
    520 
    521 #define PHY_IS_BCM8485X_AND_UP(_pc) \
    522                                ( PHY_IS_BCM8485X((_pc)) || \
    523                                  PHY_IS_BCM8486X((_pc)) || \
    524                                  PHY_IS_BCM8488X(_pc) )
    525 
    526 #define PHY_IS_BCM8484X_AND_UP(_pc) \
    527                                ( PHY_IS_BCM8484X((_pc)) || \
    528                                  PHY_IS_BCM8485X((_pc)) || \
    529                                  PHY_IS_BCM8486X((_pc)) || \
    530                                  PHY_IS_BCM8488X(_pc) )
    531 
    532 #define PHY_IS_BCM8483X_AND_UP(_pc) \
    533                                ( PHY_IS_BCM8483X((_pc)) || \
    534                                  PHY_IS_BCM8484X((_pc)) || \
    535                                  PHY_IS_BCM8485X((_pc)) || \
    536                                  PHY_IS_BCM8486X((_pc)) || \
    537                                  PHY_IS_BCM8488X(_pc) )
    538                                  
    539 #define PHY8481_IS_READY_FOR_CMD(_pc, _status) \
    540                                ((PHY_IS_BCM8483X(_pc) || PHY_IS_BCM8484X(_pc)) \
    541                                ? ( _status & PHY84834_CMD_OPEN_FOR_CMDS)       \
    542                                : ((_status != PHY8485X_CMD_SYSTEM_BUSY) &&     \
    543                                   (_status != PHY8485X_CMD_IN_PROGRESS)) )
    544 
    545 #define PHY8481_IS_OPEN_FOR_CMD(_pc, _status) \
    546                                ((PHY_IS_BCM8483X(_pc) || PHY_IS_BCM8484X(_pc)) \
    547                                ? ( _status &  PHY84834_CMD_OPEN_FOR_CMDS)      \
    548                                : ((_status == PHY8485X_CMD_OPEN_FOR_CMDS) ||   \
    549                                   (_status == PHY8485X_CMD_COMPLETE_ERROR)) )
    550 
    551 #define PHY8481_IS_CMD_COMPLETE(_pc, _status) \
    552                                ((PHY_IS_BCM8483X(_pc) || PHY_IS_BCM8484X(_pc)) \
    553                                ? ((_status & PHY8481_CMD_COMPLETE_PASS) ||     \
    554                                   (_status & PHY8481_CMD_COMPLETE_ERROR))      \
    555                                : ((_status == PHY8485X_CMD_OPEN_FOR_CMDS) ||   \
    556                                   (_status == PHY8485X_CMD_COMPLETE_ERROR)) )
    557 
    558 #define PHY8481_SET_FIBER_PREFERRED(unit, port, pc)\
    559                                 do {    \
    560                                         int fiber_preferred; \
    561                                         uint16 data16;    \
    562                                         if (!PHY_FORCED_COPPER_MODE(unit, port)) {  \
    563                                         /* Read the strap value and set fiber pref accordingly. */  \
    564                                         SOC_IF_ERROR_RETURN \
    565                                         (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16));\
    566                                         fiber_preferred = soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, (data16 & (1U << 8)) ? 1 : 0);\
    567                                         pc->automedium = TRUE; /* Always TRUE for this PHY */ }  \
    568                                         else { fiber_preferred = FALSE; pc->automedium = FALSE; } \
    569                                         pc->copper.preferred = !fiber_preferred; \
    570                                         pc->fiber.preferred = fiber_preferred; \
    571                                    }while(0)
    572 
    573 #define PHY8481_ENABLE_MEDIUM(_pc)\
    574                                 do {    _pc->copper.enable         = TRUE;\
    575                                         _pc->copper.force_duplex    = TRUE;\
    576                                         _pc->copper.force_speed    = 10000;\
    577                                         _pc->copper.autoneg_enable = TRUE;\
    578                                         _pc->copper.master = SOC_PORT_MS_AUTO;\
    579                                         _pc->copper.mdix = SOC_PORT_MDIX_AUTO;\
    580                                         _pc->fiber.enable          = TRUE;\
    581                                         _pc->fiber.force_speed     = 10000;\
    582                                         _pc->fiber.force_duplex    = TRUE;\
    583                                         _pc->fiber.autoneg_enable = FALSE;\
    584                                     } while(0)                                  
    585 
    586 STATIC int phy_8481_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability);
    587 STATIC int phy_8481_speed_get(int unit, soc_port_t port, int *speed);
    588 STATIC int phy_8481_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability);
    589 STATIC int phy_8481_an_get(int unit, soc_port_t port, int *an, int *an_done);
    590 STATIC int phy_8481_an_set(int unit, soc_port_t port, int an);
    591 STATIC int phy_8481_speed_set(int unit, soc_port_t port, int speed);
    592 STATIC int phy_8481_duplex_set(int unit, soc_port_t port, int duplex);
    593 STATIC int phy_8481_link_up(int unit, soc_port_t port);
    594 STATIC int phy_8481_enable_set(int unit, soc_port_t port, int enable);
    595 STATIC int phy_8481_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode);
    596 
    597 STATIC int _phy_8481_xaui_an_get(int unit, soc_port_t port, int *an, int *an_done);
    598 STATIC int _phy_8481_xaui_an_set(int unit, soc_port_t port, int an);
    599 STATIC int _phy_8481_medium_change(int unit, soc_port_t port, int force_update);
    600 STATIC int _phy_8481_medium_config_update(int unit, soc_port_t port,soc_phy_config_t *cfg);
    601 STATIC int _phy_8481_xaui_speed_get(int unit, soc_port_t port, int *speed);
    602 STATIC int _phy_8481_xaui_speed_set(int unit, soc_port_t port, int speed);
    603 STATIC int _phy_8481_medium_check(int unit, soc_port_t port, int *medium);
    604 STATIC int _phy_8481_xaui_enable_set(int unit, soc_port_t port, int enable);
    605 STATIC int _phy_8481_xaui_enable_get(int unit, soc_port_t port, int *enable);
    606 STATIC int _phy_8481_copper_enable_set(int unit, soc_port_t port, int enable);
    607 STATIC int _phy_8481_copper_enable_get(int unit, soc_port_t port, int *enable);
    608 STATIC int _phy_8481_halt(int unit, phy_ctrl_t *pc);
    609 STATIC int _phy_8481_write_to_arm(int unit, phy_ctrl_t *pc, uint32 addr, uint8 *data,int len);
    610 STATIC int _phy_8481_restart(int unit, phy_ctrl_t *pc);
    611 STATIC int _phy_8481_copper_an_set(int unit, soc_port_t port, int an);
    612 STATIC int _phy_8481_copper_lb_get(int unit, soc_port_t port, int *enable);
    613 STATIC int _phy_8481_xaui_nxt_dev_probe(int unit, soc_port_t port);
    614 /* STATIC */ int _phy84834_top_level_cmd_set(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size);
    615 /* STATIC */ int _phy84834_top_level_cmd_get(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size);
    616 /* STATIC */ int _phy84834_top_level_cmd_set_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size);
    617 /* STATIC */ int _phy84834_top_level_cmd_get_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size);
    618 STATIC int _phy8481_adjust_xfi_tx_preemphasis(int unit, int port, phy_ctrl_t *pc, uint32 phy_long_xfi);
    619 STATIC int _phy848xx_short_reach_enable_set(int unit,phy_ctrl_t *pc, uint16 enable );
    620 STATIC int _phy_84834_power_mode_set (int unit, soc_port_t port, uint32 mode);
    621 STATIC int _phy_84834_power_mode_get (int unit, soc_port_t port, uint32 *mode);
    622 STATIC int _phy_8481_check_firmware(int unit,phy_ctrl_t *pc);
    623 STATIC int _phy_8481_copper_speed_get(int unit, soc_port_t port, int *speed);
    624 STATIC int _phy_8481_copper_duplex_get(int unit, soc_port_t port, int *duplex);
    625 STATIC int _phy_8481_copper_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability);
    626 STATIC int _phy_8481_copper_an_get(int unit, soc_port_t port, int *an, int *an_done);
    627 STATIC int _phy_8481_xaui_duplex_get(int unit, soc_port_t port, int *duplex);
    628 STATIC int _phy_8481_xaui_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability);
    629 STATIC int _phy8485x_shadow_reg_read(int unit, phy_ctrl_t *pc, uint16 data1, uint16 data2, uint16 data3 , uint16 data4, uint16 *value);
    630 STATIC int _phy8485x_shadow_reg_write(int unit, phy_ctrl_t *pc, uint16 reg_group, uint16 reg_addr, uint16 bit_mask, uint16 bit_shift, uint16 value);
    631 STATIC int _phy84834_xfi_reg_set(int unit, phy_ctrl_t *pc, uint16 bank, uint16 offset, uint16 value);
    632 STATIC int _phy_84834_control_set(int unit, soc_port_t port, int intf, int lane, soc_phy_control_t type, uint32 value);
    633 STATIC int _phy_84834_control_get(int unit, soc_port_t port, int intf, int lane, soc_phy_control_t type, uint32 *value);
    634 
    635 int
    636 phy_8481_reg_xge_read(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank,
    637                 uint8 dev_addr, uint16 reg_addr, uint16 *data);
    638 int
    639 phy_8481_reg_xge_write(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank,
    640                 uint8 dev_addr, uint16 reg_addr, uint16 data);
    641 int
    642 phy_8481_reg_xge_modify(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank,
    643                 uint8 dev_addr, uint16 reg_addr, uint16 data, uint16 mask);
    644 #ifdef PHY8185X_DEBUG_CMD_HANDLER
    645 STATIC int _phy8485x_emi_mode_enable_get(int unit, phy_ctrl_t *pc, uint16 *status);
    646 STATIC int _phy8485x_emi_mode_enable_set(int unit, phy_ctrl_t *pc, uint16 status);
    647 STATIC int _phy8485x_sub_lf_rf_status_get(int unit, phy_ctrl_t *pc, uint16 *status);
    648 STATIC int _phy8485x_sub_lf_rf_set(int unit, phy_ctrl_t *pc);
    649 STATIC int _phy8485x_sub_lf_rf_clear(int unit, phy_ctrl_t *pc);
    650 STATIC int _phy8485x_snr_get(int unit, phy_ctrl_t *pc);
    651 STATIC int _phy8485x_current_temp_get(int unit, phy_ctrl_t *pc);
    652 STATIC int _phy8485x_upper_temp_warn_level_set(int unit, phy_ctrl_t *pc, uint16 temp);
    653 STATIC int _phy8485x_upper_temp_warn_level_get(int unit, phy_ctrl_t *pc, uint16 *temp);
    654 STATIC int _phy8485x_lower_temp_warn_level_set(int unit, phy_ctrl_t *pc, uint16 temp);
    655 STATIC int _phy8485x_lower_temp_warn_level_get(int unit, phy_ctrl_t *pc, uint16 *temp);
    656 STATIC int _phy8486x_xfi_2p5g_mode_get(int unit, phy_ctrl_t *pc, uint16 *mode_2p5g);
    657 STATIC int _phy84888_xfi_2p5g_mode_get(int unit, phy_ctrl_t *pc, uint16 *mode_2p5g, uint16 *mode_5g);
    658 STATIC int _phy_848xx_led_type_get (int unit, soc_port_t port, uint32 *led_type, uint32 *led_mode);
    659 STATIC int _phy_848xx_led_type_set (int unit, soc_port_t port, uint32 led_type, uint32 led_mode);
    660 STATIC int _phy_848xx_pause_frame_mode_get (int unit, soc_port_t port, uint32 *enable); 
    661 STATIC int _phy_848xx_pause_frame_mode_set (int unit, soc_port_t port, uint32 enable);
    662 #endif /* PHY8185X_DEBUG_CMD_HANDLER */
    663 STATIC int _phy_848xx_mgbase_802_3bz_type_get (int unit, phy_ctrl_t *pc, uint16 *frame_type, uint16 *frame_mode); 
    664 STATIC int _phy_848xx_mgbase_802_3bz_type_set (int unit, phy_ctrl_t *pc, uint16 frame_type, uint16 frame_mode); 
    665 
    666 STATIC int _phy848xx_xfi_2p5g_5g_mode_set(int unit, phy_ctrl_t *pc, uint16  mode_2p5g);
    667 STATIC int _phy_8485x_force_cl72_config(int unit, phy_ctrl_t *pc, uint16 enable);
    668 STATIC int _phy_8485x_force_cl72_status(int unit, phy_ctrl_t *pc, uint16 *value);
    669 STATIC int _phy84834_jumbo_packet_set(int unit, phy_ctrl_t *pc, uint16 mode);
    670 #if 0
    671 STATIC int _phy84834_jumbo_packet_get(int unit, phy_ctrl_t *pc, uint16 *mode);
    672 #endif
    673 
    674 #ifdef BCM_WARM_BOOT_SUPPORT
    675 STATIC int _phy84834_top_level_cmd_get_dispatch_v2(int unit,phy_ctrl_t *pc, uint16 cmd);
    676 STATIC int _phy84834_top_level_cmd_get_retrive_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size);
    677 STATIC int _phy_8481_reinit(int unit, soc_port_t port);
    678 #endif
    679 
    680 #if 1
    681 
    682 #define PHY84834_TOP_LEVEL_CMD_SET  _phy84834_top_level_cmd_set_v2
    683 #define PHY84834_TOP_LEVEL_CMD_GET  _phy84834_top_level_cmd_get_v2
    684 #define PHY84834_DIAG_CMD_SET_EEE_MODE_GENERIC PHY84834_DIAG_CMD_SET_EEE_MODE_V2
    685 #define PHY84834_DIAG_CMD_GET_EEE_MODE_GENERIC PHY84834_DIAG_CMD_GET_EEE_MODE_V2
    686 #define PHY84834_DIAG_CMD_SET_PAIR_SWAP_GENERIC PHY84834_DIAG_CMD_SET_PAIR_SWAP_V2
    687 #define PHY84834_DIAG_CMD_SET_1588_ENABLE_GENERIC PHY84834_DIAG_CMD_SET_1588_ENABLE_V2
    688 #define PHY84834_DIAG_CMD_GET_1588_ENABLE_GENERIC PHY84834_DIAG_CMD_GET_1588_ENABLE_V2
    689 #define PHY84834_DIAG_CMD_SET_XFI_M_REG_VALUES_GENERIC PHY84834_DIAG_CMD_SET_XFI_M_REG_VALUES_V2
    690 #define PHY84834_DIAG_CMD_GET_XFI_M_REG_VALUES_GENERIC PHY84834_DIAG_CMD_GET_XFI_M_REG_VALUES_V2
    691 #define PHY84834_DIAG_CMD_SET_XFI_TX_FILTERS_GENERIC PHY84834_DIAG_CMD_SET_XFI_TX_FILTERS
    692 #define PHY84834_DIAG_CMD_GET_XFI_TX_FILTERS_GENERIC PHY84834_DIAG_CMD_GET_XFI_TX_FILTERS
    693 #define PHY84834_DIAG_CMD_SET_SHORT_REACH_ENABLE_GENERIC PHY84834_DIAG_CMD_SET_SHORT_REACH_ENABLE_V2
    694 #define PHY84834_DIAG_CMD_GET_SHORT_REACH_ENABLE_GENERIC PHY84834_DIAG_CMD_GET_SHORT_REACH_ENABLE_V2
    695 #define PHY84834_DIAG_CMD_GET_SUB_LF_RF_STATUS_GENERIC PHY84834_DIAG_CMD_GET_SUB_LF_RF_STATUS_V2
    696 #define PHY84834_DIAG_CMD_CLEAR_SUB_LF_RF_GENERIC PHY84834_DIAG_CMD_CLEAR_SUB_LF_RF_V2
    697 #define PHY84834_DIAG_CMD_SET_SUB_LF_RF_GENERIC PHY84834_DIAG_CMD_SET_SUB_LF_RF_V2
    698 #define PHY84834_DIAG_CMD_GET_SNR_GENERIC PHY84834_DIAG_CMD_GET_SNR_V2
    699 #define PHY84834_DIAG_CMD_GET_CURRENT_TEMP_GENERIC PHY84834_DIAG_CMD_GET_CURRENT_TEMP_V2
    700 #define PHY84834_DIAG_CMD_SET_XFI_L_REG_VALUES_GENERIC PHY84834_DIAG_CMD_SET_XFI_L_REG_VALUES_V2
    701 #define PHY84834_DIAG_CMD_GET_XFI_L_REG_VALUES_GENERIC PHY84834_DIAG_CMD_GET_XFI_L_REG_VALUES_V2
    702 #define PHY8485X_DIAG_CMD_WRITE_SHADOW_REG PHY8485X_DIAG_CMD_WRITE_SHADOW_REG_V2
    703 #define PHY8485X_DIAG_CMD_READ_SHADOW_REG PHY8485X_DIAG_CMD_READ_SHADOW_REG_V2
    704 #define PHY8486x_DIAG_CMD_GET_XFI_2P5G_MODE  PHY84834_DIAG_CMD_GET_XFI_2P5G_MODE_V2
    705 #define PHY8486x_DIAG_CMD_SET_XFI_2P5G_MODE  PHY84834_DIAG_CMD_SET_XFI_2P5G_MODE_V2
    706 #define PHY848x_DIAG_CMD_SET_JUMBO_FRAME_MODE  PHY848X_DIAG_CMD_WRITE_JUMBO_FRAME_REG_V2
    707 #define PHY848x_DIAG_CMD_GET_JUMBO_FRAME_MODE  PHY848X_DIAG_CMD_READ_JUMBO_FRAME_REG_V2
    708 #define PHY84888_DIAG_CMD_SET_USXGMII_MODE  PHY84834_DIAG_CMD_SET_USXGMII
    709 #define PHY84888_DIAG_CMD_GET_USXGMII_MODE  PHY84834_DIAG_CMD_GET_USXGMII
    710 #define PHY84888_DIAG_CMD_SET_PAUSE_FRAME_MODE  PHY84834_DIAG_CMD_SET_PAUSE_FRAME_MODE
    711 #define PHY84888_DIAG_CMD_GET_PAUSE_FRAME_MODE  PHY84834_DIAG_CMD_GET_PAUSE_FRAME_MODE
    712 #define PHY84888_DIAG_CMD_SET_LED_TYPE  PHY84834_DIAG_CMD_SET_LED_TYPE
    713 #define PHY84888_DIAG_CMD_GET_LED_TYPE  PHY84834_DIAG_CMD_GET_LED_TYPE
    714 #define PHY84888_DIAG_CMD_SET_MGBASET_802_3BZ_TYPE  PHY84834_DIAG_CMD_SET_MGBASET_802_3BZ_TYPE
    715 #define PHY84888_DIAG_CMD_GET_MGBASET_802_3BZ_TYPE  PHY84834_DIAG_CMD_GET_MGBASET_802_3BZ_TYPE
    716 
    717 #else
    718 
    719 #define PHY84834_TOP_LEVEL_CMD_SET  _phy84834_top_level_cmd_set
    720 #define PHY84834_TOP_LEVEL_CMD_GET  _phy84834_top_level_cmd_get
    721 #define PHY84834_DIAG_CMD_SET_EEE_MODE_GENERIC PHY84834_DIAG_CMD_SET_EEE_MODE
    722 #define PHY84834_DIAG_CMD_GET_EEE_MODE_GENERIC PHY84834_DIAG_CMD_GET_EEE_MODE
    723 #define PHY84834_DIAG_CMD_SET_PAIR_SWAP_GENERIC PHY84834_DIAG_CMD_PAIR_SWAP_CHANGE
    724 #define PHY84834_DIAG_CMD_SET_1588_ENABLE_GENERIC PHY84834_DIAG_CMD_SET_1588_ENABLE
    725 #define PHY84834_DIAG_CMD_GET_1588_ENABLE_GENERIC PHY84834_DIAG_CMD_GET_1588_ENABLE
    726 
    727 #endif
    728 
    729 static char *dev_name_8481  = "BCM8481";
    730 static char *dev_name_84823 = "BCM84823";
    731 static char *dev_name_84834 = "BCM84834";
    732 static char *dev_name_84844 = "BCM84844";
    733 static char *dev_name_84858 = "BCM84858";
    734 static char *dev_name_8486x = "BCM8486x";
    735 static char *dev_name_84888 = "BCM84888";
    736 
    737 /* Function:
    738  *    phy_8481_init
    739  * Purpose:    
    740  *    Initialize 8481 phys
    741  * Parameters:
    742  *    unit - StrataSwitch unit #.
    743  *    port - StrataSwitch port #. 
    744  * Returns:    
    745  *    SOC_E_NONE
    746  */
    747 STATIC int
    748 phy_8481_init(int unit, soc_port_t port)
    749 {
    750     soc_timeout_t  to;
    751     phy_ctrl_t     *pc;
    752     uint16         fw_ver, data16 = 0;
    753     soc_port_ability_t  ability;
    754     int            rv, is_line = 0;
    755     int            medium;
    756     uint32         phy_mdi_pair_map;
    757     uint32         phy_long_xfi, sys_side = 0, priority = 0;
    758     uint8          *fw = NULL;
    759     int            fw_len = 0;
    760     uint16         cl72_value=0xff;   
    761     uint16         pair_swap_value;
    762 
    763     pc = EXT_PHY_SW_STATE(unit, port);
    764 
    765     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) ||
    766         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
    767 
    768         PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45);
    769         FLAGS(pc) = 0; /* device specific private flags */
    770         LINK_DOWN(pc) = TRUE;
    771 
    772         PHY_EXT_ROM_BOOT(pc) = soc_property_port_get(unit, port,
    773                                                 spn_PHY_EXT_ROM_BOOT, 1);
    774         DL_DIVIDEND(pc) = soc_property_port_get(unit, port,
    775                                                 spn_RATE_EXT_DOWNLOAD_MDIO_DIVIDEND, 1);
    776         DL_DIVISOR(pc) = soc_property_port_get(unit, port,
    777                                                 spn_RATE_EXT_DOWNLOAD_MDIO_DIVISOR, 0);
    778 
    779         SYS_FORCED_CL72(pc) = soc_property_port_get(unit, port, spn_PORT_INIT_CL72, 0);
    780 
    781         sys_side = soc_property_port_get(unit, port, spn_PHY_SERDES, 0);
    782         /* Set Repeater flag according to config for Orca/Mako              *\
    783         \* (PHY_SERDES == 2500 or 5000) means system side is 2500X or 5000X */
    784         if ( PHY_IS_BCM8486X_AND_UP(pc) &&
    785                      (sys_side != 2500) && (sys_side != 5000) ) {
    786             /* As setting 5G/2.5G line side speed ( @ 5G/2.5G over XFI mode), *\
    787             |* phy_8481_link_up() will notify internal SerDes with 10G speed. *|
    788             \* set REPEATER flag to tell MAC driver don't notify speed again! */
    789             PHY_FLAGS_SET(unit, port, PHY_FLAGS_REPEATER);
    790         } else {
    791             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_REPEATER);
    792         }
    793 
    794 #ifdef BCM_WARM_BOOT_SUPPORT
    795         if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){
    796             rv = _phy_8481_reinit(unit, port);
    797             if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) && PHY_IS_BCM8483X_AND_UP(pc)) {
    798                 SOC_IF_ERROR_RETURN
    799                     (_phy84834_top_level_cmd_get_dispatch_v2(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_EEE_MODE_V2));
    800                 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2);
    801             } else {
    802                 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_DEFAULT);
    803             }
    804             return rv;
    805         }
    806 #endif
    807 
    808 #if 0 
    809         /* reset the GPHY core */
    810         SOC_IF_ERROR_RETURN
    811             (MODIFY_PHY8481_MII_CTRLr(unit, pc,
    812                                           MII_CTRL_RESET, MII_CTRL_RESET));
    813         /* Wait for device to come out of reset */
    814         soc_timeout_init(&to, 2000000, 0);
    815         do {
    816             rv = READ_PHY8481_MII_CTRLr(unit, pc, &data16);
    817             if (((data16 & MII_CTRL_RESET) == 0) ||
    818                 SOC_FAILURE(rv)) {
    819                 break;
    820             }
    821         } while (!soc_timeout_check(&to));
    822         if ((data16 & MII_CTRL_RESET) != 0) {
    823             LOG_WARN(BSL_LS_SOC_PHY,
    824                      (BSL_META_U(unit,
    825                                  "PHY8481 GPHY core reset failed: u=%d p=%d\n"),
    826                       unit, port));
    827         }
    828 #endif
    829 
    830         SOC_IF_ERROR_RETURN
    831                 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16));
    832         /* Compare config property with Config13 Strap pin (30.0x401a[13]) */
    833         if ( PHY_EXT_ROM_BOOT(pc) != ((data16 & (1U << 13)) >> 13) ) {
    834             LOG_WARN( BSL_LS_SOC_PHY, (BSL_META_U(unit,
    835                      "Cannot load firmware from MDIO/SPIROM: "
    836                      "Config13 strap mismatch with the config property "
    837                      "phy_ext_rom_boot (unit=%d port=%d\n"),  unit, port) );
    838         }
    839 
    840         if ( soc_property_port_get(unit, port, spn_PHY_FORCE_FIRMWARE_LOAD, TRUE) ) {
    841             fw_ver = 0;
    842         } else {
    843             /* Read the f/w version register,                         *\
    844             \* if != 0, that means f/w is running and no need to load */
    845             SOC_IF_ERROR_RETURN
    846                 (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400f, &fw_ver));
    847             
    848             /* Disable loopback */
    849             /* PCS Control 1 Reg. DEVAD=3 Addr=0, bit[14] PCS loopback mode  */
    850             SOC_IF_ERROR_RETURN
    851                 (MODIFY_PHY8481_PCS_CTRLr(unit, pc,
    852                                 0, PCS_IEEE_CTL1_LPBK));
    853             /* 1000BASE-T/100BASE-TX MII Contol Reg. DEVAD=7, Addr=0xFFE0 bit[14] */    
    854             SOC_IF_ERROR_RETURN               
    855                     (MODIFY_PHY8481_MII_CTRLr(unit, pc, 0, MII_CTRL_LE));
    856 
    857         }
    858 
    859         if ( (! fw_ver) && (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1)
    860                         && (PHY_EXT_ROM_BOOT(pc)) ) {
    861             LOG_INFO(BSL_LS_SOC_PHY,
    862                      (BSL_META_U(unit,
    863                                  "PHY8481: SPI-ROM Attempting firmware download : u=%d p=%d\n"),
    864                       unit, port));
    865             /* Reset the device PMA/PMD and PCS */
    866             SOC_IF_ERROR_RETURN
    867                 (MODIFY_PHY8481_PMAD_CTRLr(unit, pc, MII_CTRL_RESET,
    868                                                      MII_CTRL_RESET) );
    869             /* Wait for device to come out of reset */
    870             soc_timeout_init(&to, 2000000, 0);
    871             if ( PHY_IS_BCM8484X_A0(pc) ) {
    872                 sal_usleep(300000);
    873             }
    874 
    875             do {
    876                 rv = READ_PHY8481_PMAD_CTRLr(unit, pc, &data16);
    877                 if ( ((data16 & MII_CTRL_RESET) == 0) || SOC_FAILURE(rv) ) {
    878                     break;
    879                 }
    880             } while ( ! soc_timeout_check(&to) );
    881             if ( ( data16 & MII_CTRL_RESET) != 0 ) {
    882                 LOG_WARN(BSL_LS_SOC_PHY,
    883                          (BSL_META_U(unit, "PHY8481 reset failed: u=%d p=%d\n"),
    884                           unit, port));
    885                 /* failed to load FW from SPIROM, try MDIO FW load */
    886                 PHY_EXT_ROM_BOOT(pc) = 0;
    887             }
    888         }
    889     
    890         if ( (! fw_ver) && (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1)
    891                         && (! PHY_EXT_ROM_BOOT(pc))) {
    892             /* Attempting f/w download */
    893             LOG_INFO(BSL_LS_SOC_PHY,
    894                      (BSL_META_U(unit,
    895                                  "PHY8481: Attempting firmware download : u=%d p=%d\n"),
    896                       unit, port));
    897             switch ( PHY_OUI_MODEL(  PHY_OUI(pc->phy_id0, pc->phy_id1),
    898                                    PHY_MODEL(pc->phy_id0, pc->phy_id1)) ) {
    899     
    900             case  PHY_OUI_MODEL(PHY_BCM8481X_OUI, PHY_BCM8481X_MODEL) :
    901                 if ((PHY_REV(pc->phy_id0, pc->phy_id1) >= 0x2)) {
    902                     /* C0 and beyond only */
    903                     FIRMWARE(pc) = bcm_8481_firmware;
    904                     FIRMWARE_LEN(pc) = bcm_8481_firmware_size;
    905                     pc->dev_name = dev_name_8481;
    906                 }
    907             break;
    908     
    909             case  PHY_OUI_MODEL(PHY_BCM84822_OUI, PHY_BCM84822_MODEL) :
    910             case  PHY_OUI_MODEL(PHY_BCM84823_OUI, PHY_BCM84823_MODEL) :
    911                 if (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x0)  {
    912                     FIRMWARE(pc) = bcm_8482A0_firmware;
    913                     FIRMWARE_LEN(pc) = bcm_8482A0_firmware_size;
    914                 }
    915                 if (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x1)  {
    916                     FIRMWARE(pc) = bcm_8482B0_firmware;
    917                     FIRMWARE_LEN(pc) = bcm_8482B0_firmware_size;
    918                 }
    919                 if (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x2)  {
    920                     FIRMWARE(pc) = bcm_8482B1_firmware;
    921                     FIRMWARE_LEN(pc) = bcm_8482B1_firmware_size;
    922                 }
    923                 pc->flags |= PHYCTRL_MDIO_BCST;
    924                 pc->dev_name = dev_name_84823;
    925             break;
    926     
    927             case  PHY_OUI_MODEL(PHY_BCM84833_OUI, PHY_BCM84833_MODEL) :
    928             case  PHY_OUI_MODEL(PHY_BCM84834_OUI, PHY_BCM84834_MODEL) :
    929             case  PHY_OUI_MODEL(PHY_BCM84835_OUI, PHY_BCM84835_MODEL) :
    930             case  PHY_OUI_MODEL(PHY_BCM84836_OUI, PHY_BCM84836_MODEL) :
    931                 FIRMWARE(pc) = bcm_84833_firmware;
    932                 FIRMWARE_LEN(pc) = bcm_84833_firmware_size;
    933                 pc->flags |= PHYCTRL_MDIO_BCST;
    934                 pc->dev_name = dev_name_84834;
    935             break;
    936 
    937             case  PHY_OUI_MODEL(PHY_BCM84844_OUI, PHY_BCM84844_MODEL) :
    938             case  PHY_OUI_MODEL(PHY_BCM84846_OUI, PHY_BCM84846_MODEL) :
    939             case  PHY_OUI_MODEL(PHY_BCM84848_OUI, PHY_BCM84848_MODEL) :
    940                 FIRMWARE(pc) = bcm_84844_firmware;
    941                 FIRMWARE_LEN(pc) = bcm_84844_firmware_size;
    942                 pc->flags |= PHYCTRL_MDIO_BCST;
    943                 pc->dev_name = dev_name_84844;
    944             break;
    945     
    946             case  PHY_OUI_MODEL(PHY_BCM84858_OUI, PHY_BCM84858_MODEL) :
    947             case  PHY_OUI_MODEL(PHY_BCM84856_OUI, PHY_BCM84856_MODEL) :
    948                 FIRMWARE(pc) = bcm_84858_firmware;
    949                 FIRMWARE_LEN(pc) = bcm_84858_firmware_size;
    950                 pc->flags |= PHYCTRL_MDIO_BCST;
    951                 pc->dev_name = dev_name_84858;
    952             break;
    953     
    954             case  PHY_OUI_MODEL(PHY_BCM84860_OUI, PHY_BCM84860_MODEL) |
    955                   PHY_OUI_MODEL(PHY_BCM84861_OUI, PHY_BCM84861_MODEL) :
    956             case  PHY_OUI_MODEL(PHY_BCM84864_OUI, PHY_BCM84864_MODEL) |
    957                   PHY_OUI_MODEL(PHY_BCM84868_OUI, PHY_BCM84868_MODEL) :
    958                 FIRMWARE(pc) = bcm_8486x_firmware;
    959                 FIRMWARE_LEN(pc) = bcm_8486x_firmware_size;
    960                 pc->flags |= PHYCTRL_MDIO_BCST;
    961                 pc->dev_name = dev_name_8486x;
    962             break;
    963 
    964             case  PHY_OUI_MODEL(PHY_BCM84888_OUI, PHY_BCM84888_MODEL) |
    965                   PHY_OUI_MODEL(PHY_BCM84887_OUI, PHY_BCM84887_MODEL) |
    966                   PHY_OUI_MODEL(PHY_BCM84884_OUI, PHY_BCM84884_MODEL) :
    967             case  PHY_OUI_MODEL(PHY_BCM84888E_OUI, PHY_BCM84888E_MODEL) |
    968                   PHY_OUI_MODEL(PHY_BCM84884E_OUI, PHY_BCM84884E_MODEL) :
    969             case  PHY_OUI_MODEL(PHY_BCM84881_OUI, PHY_BCM84881_MODEL) |
    970                   PHY_OUI_MODEL(PHY_BCM84880_OUI, PHY_BCM84880_MODEL) :
    971             case  PHY_OUI_MODEL(PHY_BCM84885_OUI, PHY_BCM84885_MODEL) |
    972                   PHY_OUI_MODEL(PHY_BCM84888S_OUI, PHY_BCM84888S_MODEL) | 
    973                   PHY_OUI_MODEL(PHY_BCM84886_OUI, PHY_BCM84886_MODEL) :
    974                 if ( (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x0) || (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x4) || (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x8) )  {
    975                     FIRMWARE(pc) = bcm_84888A0_firmware;
    976                     FIRMWARE_LEN(pc) = bcm_84888A0_firmware_size;
    977                 }
    978                 if ( (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x1) || (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x5) || (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x9) )  {
    979                     FIRMWARE(pc) = bcm_84888B0_firmware;
    980                     FIRMWARE_LEN(pc) = bcm_84888B0_firmware_size;
    981                 } 
    982                 pc->flags |= PHYCTRL_MDIO_BCST;
    983                 pc->dev_name = dev_name_84888;
    984             break;
    985 
    986             default:
    987                 FIRMWARE(pc) = NULL;
    988                 FIRMWARE_LEN(pc) = 0;
    989             break;
    990             }
    991 
    992             /* Now check whether a newer version of firmware is available for this model */ 
    993             rv = soc_phy_fw_get(pc->dev_name, &fw, &fw_len);  
    994             if (SOC_SUCCESS(rv)) {
    995                 FIRMWARE(pc) = fw;
    996                 FIRMWARE_LEN(pc) = fw_len;
    997             }
    998 
    999             if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_CHAINED)) {
   1000             /*  No broadcast mode download in chained PHY. */
   1001                 pc->flags &= ~PHYCTRL_MDIO_BCST;
   1002             }
   1003    
   1004             if ( FIRMWARE(pc) ) {
   1005                 if (pc->flags & PHYCTRL_MDIO_BCST) {
   1006                     /* indicate second pass of init is needed */
   1007                     PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2);
   1008                     return SOC_E_NONE;
   1009                 }
   1010 
   1011                 SOC_IF_ERROR_RETURN
   1012                     (_phy_8481_halt(unit, pc));
   1013                 SOC_IF_ERROR_RETURN
   1014                     (_phy_8481_write_to_arm(unit, pc, 0, FIRMWARE(pc), FIRMWARE_LEN(pc)));
   1015     
   1016                 /* write_addr=0xc300_0000, data=0x0000_002c, enable bottom write protection 
   1017                    and set VINITHI signal to 0 (reset vector at 0x0000_0000) */
   1018 
   1019                 SOC_IF_ERROR_RETURN
   1020                     (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 0x0000));
   1021                 SOC_IF_ERROR_RETURN
   1022                     (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0000));
   1023                 SOC_IF_ERROR_RETURN
   1024                     (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xc300));
   1025                 if (PHY_IS_BCM8485X_AND_UP(pc)) {
   1026                     SOC_IF_ERROR_RETURN
   1027                         (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0x0000));
   1028                 } else {
   1029                     SOC_IF_ERROR_RETURN
   1030                         (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0x002c));
   1031                 }
   1032                 SOC_IF_ERROR_RETURN
   1033                     (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 0x0000));
   1034                 SOC_IF_ERROR_RETURN
   1035                     (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 
   1036                         (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT)));
   1037 
   1038                 /* Reset the processor to start execution of the code in the on-chip memory */
   1039                 if ( PHY_IS_BCM8486X_AND_UP(pc) ) {
   1040                     SOC_IF_ERROR_RETURN
   1041                         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x8004,0x5555));
   1042                     if ( PHY_IS_BCM8488X(pc) ) {
   1043                         /* Set 1e.0x0009[0]  */
   1044                         SOC_IF_ERROR_RETURN
   1045                             (MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 0x0009, 1, PHY8488X_SOFT_RESET_MASK));
   1046                         sal_usleep(200);
   1047                     }
   1048                     SOC_IF_ERROR_RETURN
   1049                         (WRITE_PHY8481_PMAD_REG(unit, pc, 0x0000 , 0x8000));
   1050                 } else
   1051                 if ( PHY_IS_BCM8485X_AND_UP(pc) ) {
   1052                     SOC_IF_ERROR_RETURN
   1053                         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4186,0x0004));
   1054                     SOC_IF_ERROR_RETURN
   1055                         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4186,0x0000));
   1056                 }
   1057 
   1058                 /* check the strap pin Config13 */
   1059                 SOC_IF_ERROR_RETURN
   1060                     (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16));
   1061                 if (data16 & (1U << 13)) {
   1062                     /* Now reset only the ARM core */
   1063                     SOC_IF_ERROR_RETURN
   1064                         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0040));
   1065                     SOC_IF_ERROR_RETURN
   1066                         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0000));
   1067                 } else {
   1068                     SOC_IF_ERROR_RETURN
   1069                         (MODIFY_PHY8481_PMAD_CTRLr(unit, pc,
   1070                                               MII_CTRL_RESET, MII_CTRL_RESET));
   1071                 }
   1072 
   1073                 if (PHY_IS_BCM8484X_A0(pc)) {
   1074                     sal_usleep(300000);
   1075                 }
   1076                 soc_timeout_init(&TO(pc), 2000000, 0);
   1077     
   1078             } else {
   1079                 LOG_WARN(BSL_LS_SOC_PHY,
   1080                          (BSL_META_U(unit,
   1081                                      "PHY8481: firmware download not possible with this model: u=%d p=%d\n"),
   1082                           unit, port));
   1083             }
   1084         }
   1085 
   1086         /* Need to disable port here for 8484X firmware workaround */
   1087         /* Workaround (SDK-45594 Part 1 of 2) */
   1088         if (PHY_IS_BCM8484X(pc)) {
   1089             SOC_IF_ERROR_RETURN
   1090                 (MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc,
   1091                                                         (1U << 7), 1U << 7));
   1092         }
   1093 
   1094         if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) {
   1095             /* indicate second pass of init is needed */
   1096             PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2);
   1097             return SOC_E_NONE;
   1098         }
   1099     }
   1100     
   1101     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) ||
   1102         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   1103 
   1104 #ifdef BCM_WARM_BOOT_SUPPORT
   1105         uint16 args[5];
   1106         if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){
   1107             if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) && PHY_IS_BCM8483X_AND_UP(pc)) {
   1108                 SOC_IF_ERROR_RETURN
   1109                     (_phy84834_top_level_cmd_get_retrive_v2(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_EEE_MODE_V2, args, 4));
   1110                 if (!args[0]) {
   1111                     PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   1112                     PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE);
   1113                     LOG_INFO(BSL_LS_SOC_PHY,
   1114                              (BSL_META_U(unit,
   1115                                          "u=%d p=%d recovered EEE None\n"), unit, port));
   1116                 } else if (args[0] == 1) {
   1117                     PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   1118                     PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE);
   1119                     LOG_INFO(BSL_LS_SOC_PHY,
   1120                              (BSL_META_U(unit,
   1121                                          "u=%d p=%d recovered EEE Native\n"), unit, port));
   1122                 } else if (args[0] == 2) {
   1123                     PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   1124                     PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_MODE);
   1125                     LOG_INFO(BSL_LS_SOC_PHY,
   1126                              (BSL_META_U(unit,
   1127                                          "u=%d p=%d recovered EEE AutogrEEEn\n"), unit, port));
   1128                 }
   1129             }
   1130             PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_DEFAULT);
   1131         
   1132             PHY8481_SET_FIBER_PREFERRED(unit, port, pc);    
   1133             PHY8481_ENABLE_MEDIUM(pc);
   1134             return SOC_E_NONE;
   1135         }
   1136 #endif
   1137 
   1138         do {
   1139             rv = READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400f, &fw_ver);
   1140             if ( SOC_FAILURE(rv) ) {
   1141                 data16 = MII_CTRL_RESET;
   1142                 break;
   1143             }
   1144             rv = READ_PHY8481_PMAD_CTRLr(unit, pc, &data16);
   1145             if ( SOC_FAILURE(rv) ) {
   1146                 break;
   1147             }
   1148             if ( fw_ver && (!(data16 & MII_CTRL_RESET)) ) {
   1149                 /* version is set and the reset bit has cleared */
   1150                 break;
   1151             }
   1152         } while ( !soc_timeout_check(&TO(pc)) );
   1153         if ( (data16 & MII_CTRL_RESET) || (! fw_ver) ) {
   1154             LOG_WARN(BSL_LS_SOC_PHY,
   1155                      (BSL_META_U(unit,
   1156                                  "PHY8481 : u=%d p=%d : Firmware might not be running\n"),
   1157                       unit, port));
   1158         }
   1159 
   1160         SOC_IF_ERROR_RETURN
   1161             (_phy_8481_check_firmware(unit, pc));
   1162 
   1163         PHY8481_SET_FIBER_PREFERRED(unit, port, pc);
   1164         /* software controlled medium selection is not available yet */
   1165         PHY8481_ENABLE_MEDIUM(pc);
   1166         pc->power_mode = SOC_PHY_CONTROL_POWER_FULL;
   1167 
   1168         /* Need to disable port here for 8484X firmware workaround */
   1169         /* Workaround (SDK-45594 Part 2 of 2) */
   1170         if (PHY_IS_BCM8484X(pc)) {
   1171             SOC_IF_ERROR_RETURN(
   1172                 phy_8481_enable_set(unit,port, FALSE));
   1173         }
   1174 
   1175         soc_timeout_init(&TO(pc), 700000, 0);
   1176 
   1177         if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) {
   1178             /* indicate second pass of init is needed */
   1179             PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS3);
   1180             return SOC_E_NONE;
   1181         }
   1182     }
   1183     
   1184     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS3) ||
   1185         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
   1186 
   1187         PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS4);
   1188 
   1189         while (!soc_timeout_check(&TO(pc))) {
   1190             if (PHY_HS_CAPABLE(unit, port)) {
   1191                 rv = READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400e, &data16);
   1192                 if (((data16 & 0x2) == 0) || SOC_FAILURE(rv)) {
   1193                     break;
   1194                 }
   1195             } else {
   1196                 sal_usleep(100);
   1197             }
   1198         }
   1199 
   1200         if ( PHY_IS_BCM8486X_AND_UP(pc) ) {    /* Mako and Orca supports 5G/2.5G speed */
   1201 
   1202             if ( PHY_IS_BCM8488X(pc) ) {
   1203                 /* Default priority IEEE 802.3bz 5GBase-T & 2.5GBase-T  */
   1204                 priority = soc_property_port_get(unit, port,
   1205                                      spn_PHY_MGBASET_802P3BZ_PRIORITY, 1);
   1206                 _phy_848xx_mgbase_802_3bz_type_set(unit, pc,
   1207                                                    (priority) ? 1 : 0, (priority) ? 1 : 0);                 
   1208             }
   1209             sys_side = soc_property_port_get(unit, port, spn_PHY_SERDES, 0);
   1210             if ( (sys_side == 2500 && PHY_IS_BCM8486X(pc)) ||
   1211                    (PHY_IS_BCM8488X(pc) && (sys_side == 2500 || sys_side == 5000)) ) {
   1212                 /* MAC interface defaults to 2500BASE-X mode    */
   1213                 data16 = PHY84834_DIAG_CMD_XFI_2P5G_MODE_2500X;
   1214             } else {
   1215                 /* MAC interface is 5G/2.5G over XFI mode       */
   1216                 data16 = PHY84834_DIAG_CMD_XFI_2P5G_MODE_XFI;
   1217             }
   1218             /* command handler code SET_XFI_2P5G_MODE (0x8017) */
   1219             SOC_IF_ERROR_RETURN(
   1220                     _phy848xx_xfi_2p5g_5g_mode_set(unit, pc, data16) );
   1221         }
   1222 
   1223         if (!PHY_FORCED_COPPER_MODE(unit, port)) {
   1224             SOC_IF_ERROR_RETURN
   1225                     (MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc,
   1226                                 pc->fiber.preferred ? 1U<<8 : 0, 1U<<8));
   1227         }
   1228     
   1229         phy_mdi_pair_map = soc_property_port_get(unit, port,
   1230                                                  spn_PHY_MDI_PAIR_MAP, 0);
   1231         if ( phy_mdi_pair_map ) {
   1232             /* convert  16'b_00wW_00xX_00yY_00zZ --> 16'b_0000_0000_wWxX_yYzZ */
   1233             pair_swap_value = ((phy_mdi_pair_map & (0x3<<12)) >> 6) |
   1234                               ((phy_mdi_pair_map & (0x3<<8 )) >> 4) | 
   1235                               ((phy_mdi_pair_map & (0x3<<4 )) >> 2) |
   1236                               ((phy_mdi_pair_map & (0x3<<0 )) >> 0) ;
   1237 
   1238             if ( PHY_IS_BCM8484X_AND_UP(pc) ) {
   1239                 SOC_IF_ERROR_RETURN
   1240                     (PHY84834_TOP_LEVEL_CMD_SET(unit, pc,
   1241                             (uint16) PHY84834_DIAG_CMD_SET_PAIR_SWAP_GENERIC,
   1242                             &pair_swap_value, 1) );
   1243             } else {
   1244                 SOC_IF_ERROR_RETURN
   1245                     (MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 0x4005, 0, (1U << 1)));
   1246                 sal_udelay(35000);
   1247 
   1248                 SOC_IF_ERROR_RETURN
   1249                     (MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 0x4009, pair_swap_value, 0xff));
   1250                
   1251                 SOC_IF_ERROR_RETURN
   1252                     (MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 0x4005,
   1253                                 (1U << 6)|(1U << 4)|(1U << 1),
   1254                                 (1U << 6)|(1U << 4)|(1U << 1)));
   1255                 sal_udelay(35000);
   1256             }
   1257         }
   1258 
   1259         /* By default XFI cannot drive long distance cables. TX premphasis needs
   1260          * to be adjusted if long cables are used on the XFI side
   1261          */
   1262         phy_long_xfi = soc_property_port_get(unit, port, 
   1263                                              spn_PHY_LONG_XFI, 0);
   1264         if (phy_long_xfi) {
   1265             if (!(pc->flags & PHYCTRL_SYS_SIDE_CTRL)) {
   1266                 is_line = 1;
   1267                 pc->flags |= PHYCTRL_SYS_SIDE_CTRL;
   1268             }
   1269 
   1270             SOC_IF_ERROR_RETURN(
   1271               _phy8481_adjust_xfi_tx_preemphasis(unit, port, pc, phy_long_xfi));                
   1272 
   1273             if (is_line) {
   1274                 pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL;
   1275                 is_line = 0;
   1276             }
   1277         }
   1278 
   1279         if (!PHY_FORCED_COPPER_MODE(unit, port)) {
   1280             /* check if there is another PHY device connected to the XAUI port */
   1281             rv = _phy_8481_xaui_nxt_dev_probe(unit,port);
   1282             if (SOC_SUCCESS(rv)) {
   1283                 PHYDRV_CALL_NOARG(pc,PHY_INIT);
   1284             }
   1285         } else {
   1286             pc->fiber.preferred = FALSE;
   1287             pc->copper.preferred = TRUE;
   1288         }
   1289 
   1290         /* Copper - Set Local Advertising Configuration */
   1291         PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
   1292         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
   1293 
   1294         if (!PHY_FORCED_COPPER_MODE(unit, port)) {
   1295             PHY8481_SELECT_REGS_CU(unit, pc);
   1296         }
   1297         SOC_IF_ERROR_RETURN
   1298             (phy_8481_ability_local_get(unit, port, &ability));
   1299         SOC_IF_ERROR_RETURN
   1300             (phy_8481_ability_advert_set(unit, port, &ability));
   1301     
   1302         /* Fiber - Set Local Advertising Configuration */
   1303         if (!PHY_FORCED_COPPER_MODE(unit, port)) {
   1304             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   1305             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
   1306             PHY8481_SELECT_REGS_XAUI(unit, pc);
   1307             SOC_IF_ERROR_RETURN
   1308                 (phy_8481_ability_local_get(unit, port, &ability));
   1309             SOC_IF_ERROR_RETURN
   1310                 (phy_8481_ability_advert_set(unit, port, &ability));
   1311         }
   1312     
   1313     
   1314         /* The following should be done only after the chained PHY is probed as
   1315            the PHY flags should be determined by the base PHY.
   1316          */
   1317         SOC_IF_ERROR_RETURN
   1318             (_phy_8481_medium_check(unit, port, &medium));
   1319 
   1320     
   1321         if (medium == SOC_PORT_MEDIUM_COPPER) {
   1322             PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
   1323             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
   1324             PHY8481_SELECT_REGS_CU(unit, pc);
   1325         } else {        /* Fiber */
   1326             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   1327             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
   1328             PHY8481_SELECT_REGS_XAUI(unit, pc);
   1329         }
   1330 
   1331         /*
   1332          * Configure Auxiliary 1000BASE-X control register to turn off
   1333          * carrier extension.  The Intel 7131 NIC does not accept carrier
   1334          * extension and gets CRC errors.
   1335          */
   1336         /* Disable carrier extension */
   1337         SOC_IF_ERROR_RETURN
   1338             (MODIFY_PHY8481_AUX_1000X_CTRLr(unit, pc, 0x0040, 0x0040));
   1339 
   1340         if (PHY_IS_BCM8485X_AND_UP(pc) || PHY_IS_BCM8484X(pc)) {
   1341             /* Enable Jumbo Packet */
   1342             SOC_IF_ERROR_RETURN(
   1343                     _phy84834_jumbo_packet_set(unit, pc, 1));
   1344         } else {
   1345            /* Enable 18K jumbo frame support in 8482x and 8483x */
   1346             SOC_IF_ERROR_RETURN
   1347                 (MODIFY_PHY8481_MII_AUX_CTRLr(unit, pc, (1U << 14), (1U << 14)));
   1348             SOC_IF_ERROR_RETURN
   1349                 (MODIFY_PHY8481_PHY_ECRr(unit, pc, (1U << 0), (1U << 0)));
   1350             SOC_IF_ERROR_RETURN
   1351                 (MODIFY_PHY8481_EXP_PATTERN_GENr(unit, pc, (1U << 14), (1U << 14)));
   1352             SOC_IF_ERROR_RETURN
   1353                 (MODIFY_PHY8481_MISC_1000X_CTRL2r(unit, pc, (1U << 0), (1U << 0)));
   1354             SOC_IF_ERROR_RETURN
   1355                 (MODIFY_PHY8481_AUX_1000X_CTRLr(unit, pc, (1U << 1), (1U << 1))); 
   1356         }
   1357 
   1358         if (PHY_IS_BCM8484X(pc) && IS_HG_PORT(unit, port)) {
   1359             SOC_IF_ERROR_RETURN(
   1360                 WRITE_PHY8481_PMAD_REG(unit, pc, 0xa939, 0x0183));
   1361         }
   1362 
   1363         PHY_FW_HANDSHAKE(unit, port);
   1364 
   1365         /* config property PHY_OPERATIONAL_MODE == 0x80 or 0x8000 or 0x8080 *\
   1366         \*        means to keep Super Isolate enabled                       */
   1367         if ( (soc_property_port_get(unit, port, spn_PHY_OPERATIONAL_MODE, 0)
   1368               & TOP_CONFIG_XGPHY_DISABLE) == 0 ) {
   1369             /* Remove  Super Isolate  and  XGPH Disable  by default */
   1370             SOC_IF_ERROR_RETURN(
   1371                 MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc,   0x00,
   1372                                                     TOP_CONFIG_XGPHY_DISABLE) );
   1373         }
   1374         PHY_FW_HANDSHAKE(unit, port);
   1375 
   1376         if ( PHY_IS_BCM8485X_AND_UP(pc) ) {
   1377             if (SYS_FORCED_CL72(pc)) {
   1378                 _phy_8485x_force_cl72_config(unit, pc, 1);
   1379                 (_phy_8485x_force_cl72_status(unit, pc, (uint16 *)&cl72_value));
   1380             } else {
   1381                 (_phy_8485x_force_cl72_status(unit, pc, (uint16 *)&cl72_value));
   1382             }
   1383         }
   1384     }
   1385 
   1386     return SOC_E_NONE;
   1387 }
   1388 
   1389 
   1390 #ifdef BCM_WARM_BOOT_SUPPORT
   1391 STATIC int
   1392 _phy_8481_reinit(int unit,soc_port_t port)  {
   1393     phy_ctrl_t     *pc;
   1394     int fiber_preferred, medium; 
   1395     uint16 data16;
   1396 
   1397     pc = EXT_PHY_SW_STATE(unit, port);
   1398 
   1399     SOC_IF_ERROR_RETURN
   1400         (_phy_8481_check_firmware(unit, pc));
   1401 
   1402     SOC_IF_ERROR_RETURN
   1403         (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16));
   1404     fiber_preferred = data16 & (1U << 8) ? 1 : 0;
   1405 
   1406     pc->copper.preferred = !fiber_preferred;
   1407     pc->fiber.preferred = fiber_preferred;
   1408 
   1409     pc->automedium = TRUE; /* Always TRUE for this PHY */
   1410 
   1411     SOC_IF_ERROR_RETURN
   1412         (_phy_8481_medium_check(unit, port, &medium));
   1413 
   1414     if (medium == SOC_PORT_MEDIUM_COPPER) {
   1415         PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
   1416         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
   1417         SOC_IF_ERROR_RETURN
   1418             (_phy_8481_copper_speed_get(unit, port, &pc->copper.force_speed));
   1419         SOC_IF_ERROR_RETURN
   1420             (_phy_8481_copper_duplex_get(unit, port, &pc->copper.force_duplex));
   1421         SOC_IF_ERROR_RETURN
   1422             (_phy_8481_copper_ability_advert_get(unit, port, &pc->copper.advert_ability));
   1423         SOC_IF_ERROR_RETURN
   1424             (_phy_8481_copper_an_get(unit, port, &pc->copper.autoneg_enable, NULL));
   1425     } else {        /* Fiber */
   1426         PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   1427         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
   1428 
   1429         SOC_IF_ERROR_RETURN
   1430             (_phy_8481_xaui_speed_get(unit, port, &pc->fiber.force_speed));
   1431         SOC_IF_ERROR_RETURN
   1432             (_phy_8481_xaui_duplex_get(unit, port, &pc->fiber.force_duplex));
   1433         SOC_IF_ERROR_RETURN
   1434             (_phy_8481_xaui_ability_advert_get(unit, port, &pc->fiber.advert_ability));
   1435         SOC_IF_ERROR_RETURN
   1436             (_phy_8481_xaui_an_get(unit, port, &pc->fiber.autoneg_enable, NULL));
   1437     }
   1438 
   1439     pc->power_mode = SOC_PHY_CONTROL_POWER_FULL;
   1440 
   1441     return SOC_E_NONE;
   1442 }
   1443 #endif
   1444 
   1445 STATIC int
   1446 _phy_8481_clear_eee_stats(int unit,phy_ctrl_t *pc) {
   1447     uint16 temp;
   1448 
   1449    /* Clearing 10G EEE stats: Enable clear on Read  */
   1450     SOC_IF_ERROR_RETURN
   1451             (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc, 0x0003, 0x000f));
   1452     SOC_IF_ERROR_RETURN
   1453             (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc, 0x000f, 0x000f));
   1454     SOC_IF_ERROR_RETURN
   1455             (READ_PHY8481_EXP_EEE_TX_EVENTS_HIGHr(unit, pc, &temp));
   1456     SOC_IF_ERROR_RETURN
   1457             (READ_PHY8481_EXP_EEE_TX_EVENTS_LOWr(unit, pc, &temp));
   1458     /* Clearing 10G EEE stats: Disable clear on Read  */
   1459     SOC_IF_ERROR_RETURN
   1460             (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc, 0x0002, 0x000f));
   1461 
   1462     /* Clearning 1G EEE stats  */
   1463     SOC_IF_ERROR_RETURN
   1464             (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8002, 0x8002));
   1465     SOC_IF_ERROR_RETURN
   1466             (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8000, 0x8002));
   1467 
   1468     return SOC_E_NONE;
   1469 }
   1470 
   1471 STATIC int
   1472 _phy_8481_check_firmware(int unit,phy_ctrl_t *pc) {
   1473     uint16 tmp16;
   1474     uint8  fw_ver_chip_rev, fw_ver_main, fw_ver_branch, fw_ver_sub_branch,
   1475            fw_date_month, fw_date_day, fw_date_year, spirom_crc_check_status;
   1476     
   1477     SOC_IF_ERROR_RETURN
   1478                 (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400f, &tmp16));
   1479     fw_ver_chip_rev = (tmp16 >> 12) & 0xf;
   1480     fw_ver_main     = (tmp16 >> 7) & 0x1f;
   1481     fw_ver_branch   =  tmp16 & 0x7f;
   1482     
   1483     if (PHY_IS_BCM8485X_AND_UP(pc)) {
   1484         fw_ver_sub_branch = fw_ver_chip_rev;
   1485     }
   1486     else {    
   1487         SOC_IF_ERROR_RETURN
   1488             (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x4011,&tmp16));
   1489             fw_ver_sub_branch =  (tmp16 >> 11) & 0x1f;
   1490     }
   1491 
   1492     SOC_IF_ERROR_RETURN
   1493         (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x4010,&tmp16));
   1494     
   1495         fw_date_month = (tmp16 >> 9) & 0xf;                      /* BIT[12:9] */
   1496         fw_date_day   = (tmp16 >> 4) & 0x1f;                     /* BIT[9:4]  */
   1497         fw_date_year  = (tmp16 & 0xf) | ((tmp16 & BIT(13)) >> 9); /* [13,3:0] */
   1498     
   1499     LOG_CLI((BSL_META_U(unit,
   1500                         "BCM848xx: u=%d p=%d: init. Chip Rev = %02d "
   1501                         "Version = %02d.%02d.%02d Date = %02d/%02d/20%02d (%s)\n"),
   1502              unit, pc->port, fw_ver_chip_rev, fw_ver_main, fw_ver_branch, fw_ver_sub_branch,
   1503              fw_date_month, fw_date_day, fw_date_year,
   1504              PHY_EXT_ROM_BOOT(pc) ? "SPI" : "MDIO"));
   1505    
   1506     SOC_IF_ERROR_RETURN
   1507         (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400d, &tmp16));
   1508     spirom_crc_check_status = (tmp16 >> 14) & 0x3;
   1509     if(spirom_crc_check_status == 0x2) {
   1510         LOG_INFO(BSL_LS_SOC_PHY, (BSL_META_U(unit, "SPIROM bad CRC \n")));
   1511     }
   1512 
   1513     if (PHY_IS_BCM84823(pc) && ((fw_ver_main > 3) || ((fw_ver_main == 3) && (fw_ver_branch >= 2)))) {
   1514         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_HS_CAPABLE);
   1515     }
   1516     if (PHY_IS_BCM84823(pc) && ((fw_ver_main > 4) || ((fw_ver_main == 4) && (fw_ver_branch >= 18)))) {
   1517         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE);
   1518         SOC_IF_ERROR_RETURN
   1519            (MODIFY_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, 0x0002, 0x0003));
   1520         /* Clearing the stats: Disable clear on Read  */
   1521         SOC_IF_ERROR_RETURN
   1522            (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x0000, 0x0001));
   1523     }
   1524     if (PHY_IS_BCM8483X(pc) && ((fw_ver_main > 1) || ((fw_ver_main == 1) && (fw_ver_branch >= 15)))) {
   1525         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_HS_CAPABLE);
   1526         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE);
   1527         /* Clearing the stats: Disable clear on Read  */
   1528         SOC_IF_ERROR_RETURN
   1529            (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x0000, 0x0001));
   1530     }
   1531     if (PHY_IS_BCM8484X(pc) && ((fw_ver_main > 0) || ((fw_ver_main == 0) && (fw_ver_branch >= 3)))) {
   1532         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_HS_CAPABLE);
   1533         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE);
   1534 
   1535         /* Set flag for FW versions >= 1.08.00 */
   1536         if ( ((fw_ver_main == 1) && (fw_ver_branch >= 8)) || (fw_ver_main > 1) ) {
   1537              FLAGS(pc) |= PHY8483X_ATOMIC_ACCESS_SHD;
   1538         }
   1539     }
   1540     if (PHY_IS_BCM8483X(pc) && ((fw_ver_main > 1) || ((fw_ver_main == 1) && (fw_ver_branch >= 40)))) {
   1541         FLAGS(pc) |= PHY8483X_MFG_TEST_SUPPORT;
   1542         FLAGS(pc) |= PHY8483X_STATE_TEST_SUPPORT;
   1543     }
   1544     if (PHY_IS_BCM8484X(pc) && ((fw_ver_main > 0) || ((fw_ver_main == 0) && (fw_ver_branch >= 3)))) {
   1545         FLAGS(pc) |= PHY8483X_MFG_TEST_SUPPORT;
   1546         FLAGS(pc) |= PHY8483X_STATE_TEST_SUPPORT;
   1547         FLAGS(pc) |= PHY8483X_FULL_SNR_SUPPORT;
   1548     }
   1549     if (PHY_IS_BCM8483X(pc) && ((fw_ver_main > 1) || ((fw_ver_main == 1) && (fw_ver_branch >= 52)))) {
   1550         FLAGS(pc) |= PHY8483X_FULL_SNR_SUPPORT;
   1551     }
   1552     if ( (PHY_IS_BCM8485X(pc) && ((fw_ver_main > 0) || ((fw_ver_main == 0) && (fw_ver_branch >= 3 )))) ||
   1553          (PHY_IS_BCM8486X_AND_UP(pc)) ) {
   1554         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_HS_CAPABLE);
   1555         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE);
   1556         FLAGS(pc) |= PHY8483X_FULL_SNR_SUPPORT;
   1557         FLAGS(pc) |= PHY8483X_STATE_TEST_SUPPORT;
   1558         FLAGS(pc) |= PHY8483X_MFG_TEST_SUPPORT;
   1559 
   1560         /* Set flag for FW versions >= 1.00.05 */
   1561         if ( ((fw_ver_main == 1) && (fw_ver_branch >= 1)) ||
   1562               (fw_ver_main >  1) || (PHY_IS_BCM8486X_AND_UP(pc)) ) {
   1563             FLAGS(pc) |= PHY8483X_ATOMIC_ACCESS_SHD;
   1564         }
   1565     }
   1566 
   1567     return SOC_E_NONE;
   1568 }
   1569     
   1570 
   1571 
   1572 STATIC int
   1573 _phy_8481_copper_link_get(int unit, soc_port_t port, int *link) {
   1574 
   1575     uint16  pcs_mii_stat, pcs_mii_stat2, pcs_mii_stat3;
   1576     uint16  speed_val, ctrl;
   1577     phy_ctrl_t     *pc;
   1578     int an,an_done,cur_speed;
   1579 
   1580     pc = EXT_PHY_SW_STATE(unit, port);
   1581 
   1582     PHY8481_SELECT_REGS_CU(unit, pc);
   1583 
   1584     SOC_IF_ERROR_RETURN
   1585         (READ_PHY8481_MII_STATr(unit, pc, &pc->mii_stat));
   1586 
   1587     SOC_IF_ERROR_RETURN
   1588         (phy_8481_an_get(unit,port,&an,&an_done));
   1589 
   1590     /* return link false if in the middle of autoneg */
   1591     if (an == TRUE && an_done == FALSE) {
   1592         *link = FALSE;
   1593         return SOC_E_NONE;
   1594     } 
   1595 
   1596     /* PCS link status , DEVAD=3 */
   1597     SOC_IF_ERROR_RETURN
   1598         (READ_PHY8481_PCS_STATr(unit, pc, &pcs_mii_stat));
   1599 
   1600     if (pcs_mii_stat == 0xffff) {
   1601        /* mii_stat == 0xffff check is to handle removable PHY daughter cards */
   1602         *link = FALSE;
   1603         return SOC_E_NONE;
   1604     } 
   1605 
   1606    /* check if the current speed is set to 10G */
   1607     cur_speed = 0;
   1608     if (an) { /* autoneg is enabled */
   1609             SOC_IF_ERROR_RETURN
   1610                 (READ_PHY8481_TENG_AN_CTRLr(unit, pc, &ctrl));
   1611             if ((ctrl & TENG_IEEE_AN_CTRL_10GBT)&&(pcs_mii_stat & MII_STAT_LA)) {
   1612                 cur_speed = 10000;
   1613             }
   1614     } else { /* forced mode */
   1615         SOC_IF_ERROR_RETURN
   1616             (READ_PHY8481_PMAD_CTRLr(unit, pc, &speed_val));
   1617         if ((speed_val & (IEEE_CTRLr_SPEED_10G_MASK|PMAD_MII_CTRL_SS_MASK))==IEEE_CTRLr_SPEED_10G) {
   1618             cur_speed = 10000;
   1619         }
   1620     }
   1621 
   1622     if (cur_speed == 10000) { /* check all 3 device's link status if 10G */
   1623         if PHY_IS_BCM84823(pc) {
   1624                 SOC_IF_ERROR_RETURN
   1625                     (READ_PHY8481_PCS_REG(unit, pc, 0x20, &pcs_mii_stat2));
   1626 
   1627                 SOC_IF_ERROR_RETURN
   1628                     (READ_PHY8481_PCS_REG(unit, pc, 0x21, &pcs_mii_stat3));
   1629 
   1630                 *link = (pcs_mii_stat & MII_STAT_LA) && ((pcs_mii_stat2 & 0x1001) == 0x1001) &&
   1631                         (pcs_mii_stat3 & 0x8000) ? TRUE : FALSE;
   1632         } else {
   1633                 *link = pcs_mii_stat & MII_STAT_LA ?  TRUE : FALSE;
   1634         }
   1635     } else {
   1636         *link = (pc->mii_stat & MII_STAT_LA) ? TRUE : FALSE;
   1637     }
   1638 
   1639     return SOC_E_NONE;
   1640 }
   1641 
   1642 STATIC int
   1643 _phy_8481_xaui_link_get(int unit, soc_port_t port, int *link) {
   1644 
   1645     phy_ctrl_t *pc;
   1646     uint16  status;
   1647     int     an_done;
   1648     int     an;
   1649     int     speed;
   1650     int     speed_local;
   1651 
   1652     pc = EXT_PHY_SW_STATE(unit, port);
   1653 
   1654     if ((!PHY_COPPER_MODE(unit, port)) && NXT_PC(pc)) {
   1655         /* there is a PHY device connected to this XAUI port */
   1656         /* When it is in AN mode, its negotiated speed needs to be
   1657          * propagated to this device. Sync up here since this function is periodically
   1658          * called by a dedicated linkscan task.
   1659          */
   1660         PHYDRV_CALL_ARG1(pc,PHY_LINK_GET,link);
   1661 
   1662         if (*link == TRUE) {
   1663             /* check if in an mode */
   1664             PHYDRV_CALL_ARG2(pc,PHY_AUTO_NEGOTIATE_GET,&an,&an_done);
   1665 
   1666             if (an == TRUE && an_done == TRUE) {
   1667                 /* get the speed */
   1668                 PHYDRV_CALL_ARG1(pc,PHY_SPEED_GET,&speed);
   1669                 SOC_IF_ERROR_RETURN
   1670                     (_phy_8481_xaui_speed_get(unit, port, &speed_local));
   1671 
   1672                 if (speed && (speed != speed_local)) {
   1673                     /* set this device's speed accordingly */
   1674                     SOC_IF_ERROR_RETURN
   1675                         (_phy_8481_xaui_speed_set(unit,port,speed));
   1676                 }
   1677             }
   1678         }
   1679         return SOC_E_NONE;
   1680     }
   1681 
   1682     SOC_IF_ERROR_RETURN
   1683         (READ_PHY8481_TOP_CONFIG_LINK_STATUS_REG(unit, pc, &status));
   1684 
   1685    /* status != 0xffff check is to handle removable PHY daughter cards */
   1686     *link =  ((status != 0xffff) && (status & TOP_CONFIG_LINK_STATUS_REG_FIBER_LINK)) ? TRUE : FALSE;
   1687 
   1688     return (SOC_E_NONE);
   1689 }
   1690 
   1691 
   1692 static int
   1693 _phy8481_auto_negotiate_gcd(int unit, soc_port_t port, int *speed, int *duplex)
   1694 {
   1695     int        t_speed, t_duplex;
   1696     uint16     mii_ana, mii_anp;
   1697     uint16     mii_gb_stat, mii_esr, mii_gb_ctrl;
   1698     phy_ctrl_t *pc;
   1699 
   1700     t_speed = 0;
   1701     t_duplex = 0;
   1702     mii_gb_stat = 0;            /* Start off 0 */
   1703     mii_gb_ctrl = 0;            /* Start off 0 */
   1704 
   1705     pc = EXT_PHY_SW_STATE(unit, port);
   1706     SOC_IF_ERROR_RETURN
   1707         (READ_PHY8481_MII_ANAr(unit, pc, &mii_ana));
   1708     SOC_IF_ERROR_RETURN
   1709         (READ_PHY8481_MII_ANPr(unit, pc, &mii_anp));
   1710 
   1711     if (pc->mii_stat & MII_STAT_ES) {    /* Supports extended status */
   1712         /*
   1713          * If the PHY supports extended status, check if it is 1000MB
   1714          * capable.  If it is, check the 1000Base status register to see
   1715          * if 1000MB negotiated.
   1716          */
   1717         SOC_IF_ERROR_RETURN
   1718             (READ_PHY8481_MII_ESRr(unit, pc, &mii_esr));
   1719 
   1720         if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | 
   1721                        MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) {
   1722             SOC_IF_ERROR_RETURN
   1723                 (READ_PHY8481_MII_GB_STATr(unit, pc, &mii_gb_stat));
   1724             SOC_IF_ERROR_RETURN
   1725                 (READ_PHY8481_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl));
   1726         }
   1727     }
   1728 
   1729     /*
   1730      * At this point, if we did not see Gig status, one of mii_gb_stat or 
   1731      * mii_gb_ctrl will be 0. This will cause the first 2 cases below to 
   1732      * fail and fall into the default 10/100 cases.
   1733      */
   1734 
   1735     mii_ana &= mii_anp;
   1736 
   1737     if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) &&
   1738         (mii_gb_stat & MII_GB_STAT_LP_1000FD)) {
   1739         t_speed  = 1000;
   1740         t_duplex = 1;
   1741     } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) &&
   1742                (mii_gb_stat & MII_GB_STAT_LP_1000HD)) {
   1743         t_speed  = 1000;
   1744         t_duplex = 0;
   1745     } else if (mii_ana & MII_ANA_FD_100) {         /* [a] */
   1746         t_speed = 100;
   1747         t_duplex = 1;
   1748     } else if (mii_ana & MII_ANA_T4) {            /* [b] */
   1749         t_speed = 100;
   1750         t_duplex = 0;
   1751     } else if (mii_ana & MII_ANA_HD_100) {        /* [c] */
   1752         t_speed = 100;
   1753         t_duplex = 0;
   1754     } else if (mii_ana & MII_ANA_FD_10) {        /* [d] */
   1755         t_speed = 10;
   1756         t_duplex = 1 ;
   1757     } else if (mii_ana & MII_ANA_HD_10) {        /* [e] */
   1758         t_speed = 10;
   1759         t_duplex = 0;
   1760     }
   1761 
   1762     if (speed)  {
   1763         *speed  = t_speed;
   1764     }
   1765     if (duplex) {
   1766        *duplex = t_duplex;
   1767     }
   1768 
   1769     return(SOC_E_NONE);
   1770 }
   1771 
   1772 /*
   1773  * Function:
   1774  *    phy_8481_link_get
   1775  * Purpose:
   1776  *    Get layer2 connection status.
   1777  * Parameters:
   1778  *    unit - StrataSwitch unit #.
   1779  *    port - StrataSwitch port #. 
   1780  *      link - address of memory to store link up/down state.
   1781  * Returns:    
   1782  *    SOC_E_NONE
   1783  */
   1784 
   1785 STATIC int
   1786 phy_8481_link_get(int unit, soc_port_t port, int *link)
   1787 {
   1788 
   1789     phy_ctrl_t *pc;
   1790 
   1791     pc = EXT_PHY_SW_STATE(unit, port);
   1792 
   1793     if (link == NULL) {
   1794         return SOC_E_NONE;
   1795     }
   1796 
   1797     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1798         *link = FALSE;
   1799         return SOC_E_NONE;
   1800     }
   1801 
   1802     if (pc->automedium) {
   1803        SOC_IF_ERROR_RETURN
   1804            (_phy_8481_medium_change(unit, port,FALSE));
   1805     }
   1806 
   1807     if (PHY_COPPER_MODE(unit, port)) {
   1808         SOC_IF_ERROR_RETURN(_phy_8481_copper_link_get(unit, port, link));
   1809     } else {
   1810         SOC_IF_ERROR_RETURN(_phy_8481_xaui_link_get(unit, port, link));
   1811     }
   1812 
   1813     LINK_DOWN(pc) =  ! (*link);
   1814     return SOC_E_NONE;
   1815 }
   1816 
   1817 /*
   1818  * Function:
   1819  *    phy_8481_enable_set
   1820  * Purpose:
   1821  *    Enable/Disable phy 
   1822  * Parameters:
   1823  *    unit - StrataSwitch unit #.
   1824  *    port - StrataSwitch port #. 
   1825  *      enable - on/off state to set
   1826  * Returns:    
   1827  *    SOC_E_NONE
   1828  */
   1829 
   1830 STATIC int
   1831 _phy_8481_copper_enable_set(int unit, soc_port_t port, int enable)
   1832 {
   1833     phy_ctrl_t *pc;
   1834 
   1835     pc = EXT_PHY_SW_STATE(unit, port);
   1836 
   1837     PHY_FW_HANDSHAKE(unit, port);
   1838     SOC_IF_ERROR_RETURN
   1839         (MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, enable ? 0:(1U << 7), 1U << 7));
   1840     PHY_FW_HANDSHAKE(unit, port);
   1841 
   1842     return (SOC_E_NONE);
   1843 }
   1844 
   1845 STATIC int
   1846 _phy_8481_copper_enable_get(int unit, soc_port_t port, int *enable)
   1847 {
   1848     phy_ctrl_t *pc;
   1849     uint16 data16;
   1850     pc = EXT_PHY_SW_STATE(unit, port);
   1851 
   1852     SOC_IF_ERROR_RETURN
   1853         (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16));
   1854     if((data16 & (1U << 7)) != 0) {
   1855         *enable = FALSE;
   1856     }
   1857     else {
   1858         *enable = TRUE;
   1859     }
   1860 
   1861     return (SOC_E_NONE);
   1862 }
   1863 
   1864 STATIC int
   1865 _phy_8481_xaui_enable_set(int unit, soc_port_t port, int enable)
   1866 {
   1867     phy_ctrl_t *pc;
   1868 
   1869     pc = EXT_PHY_SW_STATE(unit, port);
   1870 
   1871     PHYDRV_CALL_ARG1(pc,PHY_ENABLE_SET,enable);
   1872 
   1873     return (SOC_E_NONE);
   1874 }
   1875 
   1876 STATIC int
   1877 _phy_8481_xaui_enable_get(int unit, soc_port_t port, int *enable)
   1878 {
   1879     phy_ctrl_t *pc;
   1880     pc = EXT_PHY_SW_STATE(unit, port);
   1881 
   1882     PHYDRV_CALL_ARG1(pc,PHY_ENABLE_GET,enable);
   1883 
   1884     return (SOC_E_NONE);
   1885 }
   1886 
   1887 
   1888 STATIC int
   1889 phy_8481_enable_set(int unit, soc_port_t port, int enable)
   1890 {
   1891     phy_ctrl_t    *pc;
   1892 
   1893     pc     = EXT_PHY_SW_STATE(unit, port);
   1894 
   1895     /* Do not incorrectly Power up the interface if medium is disabled and
   1896      * global enable = true
   1897      */
   1898     if (pc->copper.enable && (pc->automedium || PHY_COPPER_MODE(unit, port))) {
   1899         SOC_IF_ERROR_RETURN
   1900             (_phy_8481_copper_enable_set(unit, port, enable));
   1901 
   1902         LOG_INFO(BSL_LS_SOC_PHY,
   1903                  (BSL_META_U(unit,
   1904                              "phy_8481_enable_set: "
   1905                              "Power %s copper medium\n"), (enable) ? "up" : "down"));
   1906     }
   1907 
   1908     if (pc->fiber.enable && (pc->automedium || PHY_FIBER_MODE(unit, port))) {
   1909         SOC_IF_ERROR_RETURN
   1910             (_phy_8481_xaui_enable_set(unit, port, enable));
   1911 
   1912         LOG_INFO(BSL_LS_SOC_PHY,
   1913                  (BSL_META_U(unit,
   1914                              "phy_8481_enable_set: "
   1915                              "Power %s fiber medium\n"), (enable) ? "up" : "down"));
   1916     }
   1917 
   1918     /* Update software state */
   1919     if (enable) {
   1920         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
   1921     } else {
   1922         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
   1923     }
   1924 
   1925     return SOC_E_NONE;
   1926 }
   1927 
   1928 /*
   1929  * Function:
   1930  *      phy_8481_enable_get
   1931  * Purpose:
   1932  *      Enable or disable the physical interface for a 8481 device.
   1933  * Parameters:
   1934  *      unit - StrataSwitch unit #.
   1935  *      port - StrataSwitch port #.
   1936  *      enable - (OUT) Boolean, true = enable PHY, false = disable.
   1937  * Returns:
   1938  *      SOC_E_XXX
   1939  */
   1940 
   1941 STATIC int
   1942 phy_8481_enable_get(int unit, soc_port_t port, int *enable)
   1943 {
   1944     int data16 = 0;
   1945     *enable = FALSE;
   1946 
   1947     if (PHY_COPPER_MODE(unit, port)) { /* Copper mode  */
   1948         SOC_IF_ERROR_RETURN
   1949             (_phy_8481_copper_enable_get(unit, port, &data16));
   1950         if(data16 == 1) {
   1951             *enable = TRUE;
   1952         }
   1953     }
   1954     else { /* Fiber mode  */
   1955         SOC_IF_ERROR_RETURN
   1956             (_phy_8481_xaui_enable_get(unit, port, &data16));
   1957         if(data16 == 1) {
   1958             *enable = TRUE;
   1959         }
   1960     }
   1961 
   1962     return SOC_E_NONE;
   1963 }
   1964 
   1965 /*
   1966  * Function:
   1967  *    phy_8481_lb_set
   1968  * Purpose:
   1969  *    Put 8481 in PHY PCS/PMA/PMD loopback
   1970  * Parameters:
   1971  *    unit - StrataSwitch unit #.
   1972  *    port - StrataSwitch port #. 
   1973  *      enable - binary value for on/off (1/0)
   1974  * Returns:    
   1975  *    SOC_E_NONE
   1976  */
   1977 
   1978 STATIC int
   1979 _phy_8481_copper_lb_set(int unit, soc_port_t port, int enable)
   1980 {
   1981     phy_ctrl_t *pc;
   1982     uint16      data16 = 0;
   1983     int         lbmood, speed, rv = SOC_E_NONE;
   1984 
   1985     pc = EXT_PHY_SW_STATE(unit, port);
   1986 
   1987     if ( enable ) {         /* enable loopback */
   1988         SOC_IF_ERROR_RETURN(_phy_8481_copper_lb_get(unit, port, &lbmood));
   1989         if ( lbmood ) {             /* already in PHY loopback mode */
   1990             return SOC_E_NONE;      /* do nothing               */
   1991         }
   1992 
   1993         /* try to get the intended loopback speed from LB_SPEED */
   1994         if ( 0 == (speed = LB_SPEED(pc)) ) {    /* 0 means LB_SPEED not set */
   1995             /* intended loopback speed was not set,                        *\
   1996             \* get real line side speed to determine what registers to set */
   1997             SOC_IF_ERROR_RETURN(_phy_8481_copper_speed_get(unit, port, &speed));
   1998         }
   1999         if ( speed >= 2500 ) {     /*  10G / 5G / 2.5G  */
   2000             /* 1000BASE-T/100BASE-TX MII Contol Reg. DEVAD=7, Addr=0xFFe0    */
   2001             if ( PHY_IS_BCM8484X_AND_UP(pc) ) {
   2002                 /* turn off MII Control Loopback, and enable AutoNeg */
   2003                 SOC_IF_ERROR_RETURN(
   2004                     MODIFY_PHY8481_MII_CTRLr(unit, pc,
   2005                                              MII_CTRL_AE,
   2006                                              MII_CTRL_AE | MII_CTRL_LE) );
   2007             }
   2008             /* PCS Control 1 Reg. DEVAD=3 Addr=0, clear bit[14] PCS loopback mode  */
   2009             if ( PHY_IS_BCM8488X(pc) ) {
   2010                 SOC_IF_ERROR_RETURN
   2011                     (MODIFY_PHY8481_PCS_CTRLr(unit, pc, 0, PCS_IEEE_CTL1_LPBK));
   2012             }
   2013 
   2014             /* PCS control Reg.(3.0x0000), clear bits [5:2] */
   2015             if ( PHY_IS_BCM8488X(pc) ) {
   2016                 SOC_IF_ERROR_RETURN
   2017                     (MODIFY_PHY8481_PCS_CTRLr(unit, pc, 0, MGBASE_AN_CTRL_SPEED_MASK_LB));
   2018             }
   2019 
   2020             if ( PHY_IS_BCM8486X_AND_UP(pc) ) {
   2021                 switch ( speed ) {
   2022                 case  2500 :
   2023                     PHY_FLAGS_SET(unit, port, PHY_FLAGS_NO_SYS_LINE_SPD_SYNC);
   2024                     data16 = (PHY_IS_BCM8488X(pc)) ? (PCS_IEEE_CTL1_SPEED_SEL_2P5G << 2) : MGBASE_AN_CTRL_SPEED_2P5G;
   2025                     break;
   2026                 case  5000 :
   2027                     PHY_FLAGS_SET(unit, port, PHY_FLAGS_NO_SYS_LINE_SPD_SYNC);
   2028                     data16 = (PHY_IS_BCM8488X(pc)) ? (PCS_IEEE_CTL1_SPEED_SEL_5G <<2) : MGBASE_AN_CTRL_SPEED_5G;
   2029                     break;
   2030                 case 10000 :
   2031                     if (PHY_IS_BCM8488X(pc)) {
   2032                         data16 = 0;
   2033                     }
   2034                     break;
   2035                 default :
   2036                     data16 = 0;
   2037                 }
   2038                 if ( PHY_IS_BCM8488X(pc) ) {
   2039                     /* PCS control Reg.(3.0x0000), Speed 10G/5G/2.5G [5:2] */    
   2040                     SOC_IF_ERROR_RETURN(
   2041                             MODIFY_PHY8481_PCS_CTRLr(unit, pc,
   2042                                         data16, MGBASE_AN_CTRL_SPEED_MASK_LB) );
   2043                 } else {
   2044                 /* MGBASE-T AN Control Reg.(30.0x0000), Speed_5G/2.5G[6:5] */
   2045                 SOC_IF_ERROR_RETURN(
   2046                     MODIFY_PHY8481_MGBASET_AN_CTRLr(unit, pc,
   2047                                     data16, MGBASE_AN_CTRL_SPEED_MASK) );
   2048                 }
   2049             } 
   2050             /* PCS Control 1 Reg. DEVAD=3 Addr=0, set bit[14] PCS loopback mode  */    
   2051             SOC_IF_ERROR_RETURN
   2052                 (MODIFY_PHY8481_PCS_CTRLr(unit, pc,
   2053                                 PCS_IEEE_CTL1_LPBK, PCS_IEEE_CTL1_LPBK));
   2054 
   2055         } else {                    /* 1G / 100M / 10M */
   2056             /* 1000BASE-T/100BASE-TX MII Contol Reg. DEVAD=7, Addr=0xFFE0    */
   2057             if ( PHY_IS_BCM8484X_AND_UP(pc) ) {
   2058                  /* Clear PCS loopback bit  */
   2059                  SOC_IF_ERROR_RETURN
   2060                     (MODIFY_PHY8481_PCS_CTRLr(unit, pc,
   2061                                     0, PCS_IEEE_CTL1_LPBK));
   2062                 if ( speed == 100 ) {
   2063                     SOC_IF_ERROR_RETURN(
   2064                         WRITE_PHY8481_MII_CTRLr(unit, pc,
   2065                                             PHY8481_MII_CTRL_LOOPBACK_100M) );
   2066                 } else {  /* speed = 1000 */
   2067                     SOC_IF_ERROR_RETURN(
   2068                         WRITE_PHY8481_MII_CTRLr(unit, pc,
   2069                                             PHY8481_MII_CTRL_LOOPBACK_1G) );
   2070                 }
   2071             } else {
   2072                 SOC_IF_ERROR_RETURN               /* bit[14] : Internal Loopback */
   2073                     (MODIFY_PHY8481_MII_CTRLr(unit, pc, MII_CTRL_LE, MII_CTRL_LE));
   2074             }
   2075         }
   2076 
   2077     } else {                /* disable loopback */
   2078         LB_SPEED(pc) = 0;   /* clear intended loopback speed */
   2079         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_NO_SYS_LINE_SPD_SYNC);
   2080         /* PCS Control 1 Reg. DEVAD=3 Addr=0, bit[14] PCS loopback mode  */
   2081         SOC_IF_ERROR_RETURN
   2082             (READ_PHY8481_PCS_CTRLr(unit, pc, &data16));
   2083         if ( data16 & PCS_IEEE_CTL1_LPBK ) {
   2084             data16 &= (~PCS_IEEE_CTL1_LPBK);   /* bit[14] : Internal Loopback */
   2085             SOC_IF_ERROR_RETURN
   2086                 (WRITE_PHY8481_PCS_CTRLr(unit, pc, data16));
   2087         }
   2088         /* 1000BASE-T/100BASE-TX MII Contol Reg. DEVAD=7, Addr=0xFFE0    */
   2089         SOC_IF_ERROR_RETURN
   2090             (READ_PHY8481_MII_CTRLr(unit, pc, &data16));
   2091         if ( data16 & MII_CTRL_LE ) {
   2092             data16 &= (~MII_CTRL_LE);          /* bit[14] : Internal Loopback */
   2093             SOC_IF_ERROR_RETURN
   2094                 (WRITE_PHY8481_MII_CTRLr(unit, pc, data16));
   2095         }
   2096     }
   2097     sal_udelay(180);  /* wait for the loopback setting to take effect */
   2098 
   2099     /* wait for MAC side Link UP/down state while enabling/disabling loopback */
   2100     if ( PHY_IS_BCM8483X_AND_UP(pc) ) {
   2101         soc_timeout_init(&TO(pc), 1000000, 0);
   2102         do {
   2103             rv = READ_PHY84834_CORE_CFG_LINK_STATUSr(unit, pc, &data16);
   2104             if ( (( enable) && ( (data16 & CORE_CFG_LINK_STAT_MAC_LINK_STATUS))) ||
   2105                  ((!enable) && (!(data16 & CORE_CFG_LINK_STAT_MAC_LINK_STATUS))) ||
   2106                  SOC_FAILURE(rv)  ) {
   2107                 break;
   2108             }
   2109         } while ( ! soc_timeout_check(&TO(pc)) );
   2110     }
   2111 
   2112     return rv;
   2113 }
   2114       
   2115 STATIC int
   2116 _phy_8481_xaui_lb_set(int unit, soc_port_t port, int enable)
   2117 {
   2118     phy_ctrl_t *pc; 
   2119 
   2120     pc = EXT_PHY_SW_STATE(unit, port);
   2121 
   2122     SOC_IF_ERROR_RETURN
   2123         (MODIFY_PHY8481_PHYXS_L_CTRLr(unit, pc, (enable) ? MII_CTRL_LE : 0, MII_CTRL_LE));
   2124 
   2125     /* Configure Loopback in SerDes */
   2126     SOC_IF_ERROR_RETURN
   2127         (MODIFY_PHY8481_PHYXS_L_COMBO_IEEE0_MIICNTLr(unit, pc,
   2128                                              (enable) ? MII_CTRL_LE : 0,
   2129                                              MII_CTRL_LE));
   2130     return SOC_E_NONE;
   2131 }
   2132 
   2133 STATIC int
   2134 phy_8481_lb_set(int unit, soc_port_t port, int enable)
   2135 {
   2136     phy_ctrl_t *pc; 
   2137 
   2138     pc = EXT_PHY_SW_STATE(unit, port);
   2139 
   2140     if ( PHY_COPPER_MODE(unit, port) ) {
   2141         SOC_IF_ERROR_RETURN(_phy_8481_copper_lb_set(unit, port, enable));
   2142     } else {
   2143         if ( NXT_PC(pc) ) {
   2144             PHYDRV_CALL_ARG1(pc,PHY_LOOPBACK_SET,enable);
   2145             return SOC_E_NONE;
   2146         }
   2147         SOC_IF_ERROR_RETURN(_phy_8481_xaui_lb_set(unit, port, enable));
   2148     }
   2149 
   2150     if ( enable ) {
   2151         /* set link-down flag in order to notify appropriate speed *\
   2152         \* in phy_8481_link_up()                                   */
   2153         LINK_DOWN(pc) = TRUE;
   2154         /* PHY driver has to call phy_8481_link_up() when setting loopback */
   2155         SOC_IF_ERROR_RETURN( phy_8481_link_up(unit, port) );
   2156     }
   2157 
   2158     return SOC_E_NONE;
   2159 }
   2160 
   2161 /*
   2162  * Function:
   2163  *    phy_8481_lb_get
   2164  * Purpose:
   2165  *    Get 8481 PHY loopback state
   2166  * Parameters:
   2167  *    unit - StrataSwitch unit #.
   2168  *    port - StrataSwitch port #. 
   2169  *      enable - address of location to store binary value for on/off (1/0)
   2170  * Returns:    
   2171  *    SOC_E_NONE
   2172  */
   2173 
   2174 STATIC int
   2175 _phy_8481_copper_lb_get(int unit, soc_port_t port, int *enable)
   2176 {
   2177     phy_ctrl_t *pc;
   2178     uint16      tmp;
   2179 
   2180     pc = EXT_PHY_SW_STATE(unit, port);
   2181 
   2182     /* PCS Control 1 Reg. DEVAD=3 Addr=0, bit[14] PCS loopback mode */
   2183     SOC_IF_ERROR_RETURN
   2184             (READ_PHY8481_PCS_CTRLr(unit, pc, &tmp));
   2185     /* ctrl != 0xffff check is to handle removable PHY daughter cards */
   2186     *enable = ((tmp != 0xffff) && (tmp & PCS_IEEE_CTL1_LPBK)) ? TRUE : FALSE;
   2187 
   2188     if ( ! (*enable) ) {
   2189         /* 1000BASE-T/100BASE-TX MII Contol Reg. DEVAD=7, Addr=0xFFe0    */
   2190         SOC_IF_ERROR_RETURN               /* bit[14] : Internal Loopback */
   2191                 (READ_PHY8481_MII_CTRLr(unit, pc, &tmp));
   2192        /* ctrl != 0xffff check is to handle removable PHY daughter cards */
   2193         *enable = ((tmp != 0xffff) && (tmp & MII_CTRL_LE)) ? TRUE : FALSE;
   2194     }
   2195 
   2196     LOG_INFO(BSL_LS_SOC_PHY,
   2197              (BSL_META_U(unit,
   2198                          "phy_8481_lb_get: u=%d port%d: loopback:%s\n"),
   2199               unit, port, *enable ? "Enabled": "Disabled"));
   2200 
   2201 
   2202     return SOC_E_NONE;
   2203 }
   2204 
   2205 STATIC int
   2206 _phy_8481_xaui_lb_get(int unit, soc_port_t port, int *enable)
   2207 {
   2208     uint16      mii_ctrl;
   2209     phy_ctrl_t *pc;
   2210 
   2211     pc = EXT_PHY_SW_STATE(unit, port);
   2212 
   2213     SOC_IF_ERROR_RETURN
   2214         (READ_PHY8481_PHYXS_L_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl));
   2215     /* ctrl != 0xffff check is to handle removable PHY daughter cards */
   2216     *enable = (mii_ctrl != 0xffff) && ((mii_ctrl & MII_CTRL_LE) == MII_CTRL_LE);
   2217 
   2218     return (SOC_E_NONE);
   2219 }
   2220 
   2221 STATIC int
   2222 phy_8481_lb_get(int unit, soc_port_t port, int *enable)
   2223 {
   2224     phy_ctrl_t *pc;
   2225 
   2226     pc = EXT_PHY_SW_STATE(unit, port);
   2227 
   2228     if (PHY_COPPER_MODE(unit, port)) {
   2229         SOC_IF_ERROR_RETURN(_phy_8481_copper_lb_get(unit, port, enable));
   2230     } else {
   2231         if (NXT_PC(pc)) {
   2232             PHYDRV_CALL_ARG1(pc,PHY_LOOPBACK_GET,enable);
   2233             return SOC_E_NONE;
   2234         }
   2235         SOC_IF_ERROR_RETURN(_phy_8481_xaui_lb_get(unit, port, enable));
   2236     }
   2237 
   2238     return SOC_E_NONE;
   2239 }
   2240 
   2241 int
   2242 phy_8481_xehg_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   2243 {
   2244     int speed =0;
   2245 
   2246     SOC_IF_ERROR_RETURN(phy_8481_speed_get(unit, port, &speed));
   2247     switch (speed) {
   2248         case 100  : /* fall through */
   2249         case 1000 :
   2250             *pif = SOC_PORT_IF_SGMII;
   2251             break;
   2252         case 10000:
   2253             *pif = SOC_PORT_IF_XFI;
   2254             break;
   2255         case 2500 : /* fall through */
   2256         case 5000 :
   2257             if ( PHY_REPEATER(unit, port) ) {
   2258                 /* MAC interface is in XFI mode */
   2259                 *pif = SOC_PORT_IF_XFI;
   2260             } else {
   2261                 /* MAC interface is in 2500/5000BASE-X mode */
   2262                 *pif = SOC_PORT_IF_SGMII;
   2263             }
   2264             break;
   2265          case 0 :
   2266                 *pif = SOC_PORT_IF_XFI;    
   2267             break;
   2268         default:   
   2269            return SOC_E_PARAM; 
   2270     }
   2271     
   2272     return SOC_E_NONE;
   2273 }
   2274 
   2275 #ifdef PHY8481_DEBUG_AUTOMEDIUM
   2276 int
   2277 show_phy_8481_clkrst_reg(int unit, soc_port_t port)
   2278 {
   2279     phy_ctrl_t   *pc;
   2280     uint16    status=0;
   2281 
   2282     pc = EXT_PHY_SW_STATE(unit, port);
   2283 
   2284     SOC_IF_ERROR_RETURN
   2285         (READ_PHY8481_TOP_CONFIG_LINK_STATUS_REG(unit, pc, &status));
   2286 
   2287     LOG_CLI((BSL_META_U(unit,
   2288                         "TOP_CONFIG_LINK_STATUS_REG = %x\n"), status));
   2289 
   2290     return SOC_E_NONE;
   2291 }
   2292 #endif
   2293 
   2294 STATIC int
   2295 _phy_8481_medium_check(int unit, soc_port_t port, int *medium)
   2296 {
   2297     phy_ctrl_t   *pc;
   2298     uint16    status;
   2299 
   2300     pc = EXT_PHY_SW_STATE(unit, port);
   2301 
   2302     if (PHY_FORCED_COPPER_MODE(unit, port)) {
   2303         *medium = SOC_PORT_MEDIUM_COPPER;
   2304         return SOC_E_NONE;
   2305     }
   2306 
   2307     SOC_IF_ERROR_RETURN
   2308         (READ_PHY8481_TOP_CONFIG_LINK_STATUS_REG(unit, pc, &status));
   2309 
   2310 
   2311     if ( status & TOP_CONFIG_LINK_STATUS_REG_FIBER_PRIO ) {
   2312         if ( status & TOP_CONFIG_LINK_STATUS_REG_FIBER_ACT ) {
   2313             *medium = SOC_PORT_MEDIUM_FIBER;
   2314         } else if ( status & TOP_CONFIG_LINK_STATUS_REG_COPPER_ACT ) {
   2315                 *medium = SOC_PORT_MEDIUM_COPPER;
   2316         } else {
   2317             *medium = SOC_PORT_MEDIUM_FIBER;
   2318         }
   2319     } else {
   2320         if ( status & TOP_CONFIG_LINK_STATUS_REG_COPPER_ACT ) {
   2321             *medium = SOC_PORT_MEDIUM_COPPER;
   2322         } else  if ( status & TOP_CONFIG_LINK_STATUS_REG_FIBER_ACT ) {
   2323             *medium = SOC_PORT_MEDIUM_FIBER;
   2324         } else {
   2325             *medium = SOC_PORT_MEDIUM_COPPER;
   2326         }
   2327     }
   2328 
   2329     return SOC_E_NONE;
   2330 }
   2331 
   2332 STATIC int
   2333 _phy_8481_medium_change(int unit, soc_port_t port, int force_update)
   2334 {
   2335     phy_ctrl_t    *pc;
   2336     int            medium;
   2337 
   2338     pc    = EXT_PHY_SW_STATE(unit, port);
   2339 
   2340     SOC_IF_ERROR_RETURN
   2341         (_phy_8481_medium_check(unit, port, &medium));
   2342 
   2343     if (medium == SOC_PORT_MEDIUM_COPPER) {
   2344         if ((!PHY_COPPER_MODE(unit, port)) || force_update) { /* Was fiber */
   2345             PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
   2346             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
   2347             PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE);
   2348             PHY8481_SELECT_REGS_CU(unit, pc);
   2349 
   2350             if (pc->copper.enable) {
   2351                 /* PHYDRV_CALL_ARG1(pc,PHY_ENABLE_SET,FALSE); */
   2352                 SOC_IF_ERROR_RETURN
   2353                     (_phy_8481_medium_config_update(unit, port, &pc->copper));
   2354             }
   2355 
   2356             LOG_INFO(BSL_LS_SOC_PHY,
   2357                      (BSL_META_U(unit,
   2358                                  "_phy_8481_link_auto_detect: u=%d p=%d [F->X]\n"),
   2359                       unit, port));
   2360         }
   2361     } else {        /* Fiber */
   2362         if ((!PHY_FIBER_MODE(unit, port)) || force_update) { /* Was copper */
   2363             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   2364             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
   2365             PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE);
   2366             PHY8481_SELECT_REGS_XAUI(unit, pc);
   2367 
   2368             if (pc->fiber.enable) {
   2369                 /* PHYDRV_CALL_ARG1(pc,PHY_ENABLE_SET,TRUE); */
   2370                 SOC_IF_ERROR_RETURN
   2371                     (_phy_8481_medium_config_update(unit, port, &pc->fiber));
   2372             }
   2373 
   2374             LOG_INFO(BSL_LS_SOC_PHY,
   2375                      (BSL_META_U(unit,
   2376                                  "_phy_8481_link_auto_detect: u=%d p=%d [C->X]\n"),
   2377                       unit, port));
   2378         }
   2379     }
   2380 
   2381     return SOC_E_NONE;
   2382 }
   2383 
   2384 /*
   2385  * Function:
   2386  *      phy_8481_medium_status
   2387  * Purpose:
   2388  *      Indicate the current active medium
   2389  * Parameters:
   2390  *      unit - StrataSwitch unit #.
   2391  *      port - StrataSwitch port #.
   2392  *      medium - (OUT) One of:
   2393  *              SOC_PORT_MEDIUM_COPPER
   2394  *              SOC_PORT_MEDIUM_XAUI
   2395  * Returns:
   2396  *      SOC_E_NONE
   2397  */
   2398 
   2399 STATIC int
   2400 phy_8481_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium)
   2401 {
   2402     if (PHY_COPPER_MODE(unit, port)) {
   2403         *medium = SOC_PORT_MEDIUM_COPPER;
   2404     } else {
   2405         *medium = SOC_PORT_MEDIUM_XAUI;
   2406     }
   2407 
   2408     return SOC_E_NONE;
   2409 }
   2410 
   2411 /*
   2412  * Function:
   2413  *      _phy_8481_medium_config_update
   2414  * Purpose:
   2415  *      Update the PHY with config parameters
   2416  * Parameters:
   2417  *      unit - StrataSwitch unit #.
   2418  *      port - StrataSwitch port #.
   2419  *      cfg - Config structure.
   2420  * Returns:
   2421  *      SOC_E_XXX
   2422  */
   2423 
   2424 STATIC int
   2425 _phy_8481_medium_config_update(int unit, soc_port_t port,
   2426                                 soc_phy_config_t *cfg)
   2427 {
   2428 
   2429     SOC_IF_ERROR_RETURN
   2430         (phy_8481_speed_set(unit, port, cfg->force_speed));
   2431     SOC_IF_ERROR_RETURN
   2432         (phy_8481_duplex_set(unit, port, cfg->force_duplex));
   2433     SOC_IF_ERROR_RETURN
   2434         (phy_8481_ability_advert_set(unit, port, &cfg->advert_ability));
   2435     SOC_IF_ERROR_RETURN
   2436         (phy_8481_an_set(unit, port, cfg->autoneg_enable));
   2437     SOC_IF_ERROR_RETURN
   2438         (phy_8481_mdix_set(unit, port, cfg->mdix));
   2439 
   2440     return SOC_E_NONE;
   2441 }
   2442 
   2443 /*
   2444  * Function:
   2445  *      phy_8481_medium_config_set
   2446  * Purpose:
   2447  *      Set the operating parameters that are automatically selected
   2448  *      when medium switches type.
   2449  * Parameters:
   2450  *      unit - StrataSwitch unit #
   2451  *      port - Port number
   2452  *      medium - SOC_PORT_MEDIUM_COPPER/XAUI
   2453  *      cfg - Operating parameters
   2454  * Returns:
   2455  *      SOC_E_XXX
   2456  */
   2457 
   2458 STATIC int
   2459 phy_8481_medium_config_set(int unit, soc_port_t port, 
   2460                            soc_port_medium_t  medium,
   2461                            soc_phy_config_t  *cfg)
   2462 {
   2463     phy_ctrl_t    *pc;
   2464     soc_phy_config_t *active_medium;  /* Currently active medium */
   2465     soc_phy_config_t *change_medium;  /* Requested medium */
   2466     soc_phy_config_t *other_medium;   /* The other medium */
   2467     int               medium_update;
   2468 
   2469     if (NULL == cfg || cfg->enable != TRUE) {
   2470         return SOC_E_PARAM;
   2471     }
   2472 
   2473     pc            = EXT_PHY_SW_STATE(unit, port);
   2474     medium_update = FALSE;
   2475 
   2476     switch (medium) {
   2477     case SOC_PORT_MEDIUM_COPPER:
   2478         if (!pc->automedium) {
   2479             if (!PHY_COPPER_MODE(unit, port)) {
   2480                 return SOC_E_UNAVAIL;
   2481             }
   2482             /* check if device is fiber capable before switching */
   2483             if (cfg->preferred == 0) {
   2484                 if (PHY_FORCED_COPPER_MODE(unit, port)) {
   2485                     /* return if not fiber capable*/
   2486                     return SOC_E_UNAVAIL;
   2487                 }
   2488             }
   2489         }
   2490         change_medium  = &pc->copper;
   2491         other_medium   = &pc->fiber;
   2492         break;
   2493     case SOC_PORT_MEDIUM_FIBER:
   2494         if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) {
   2495             return SOC_E_UNAVAIL;
   2496         }
   2497         change_medium  = &pc->fiber;
   2498         other_medium   = &pc->copper;
   2499         break;
   2500     default:
   2501         return SOC_E_PARAM;
   2502     }
   2503 
   2504     /*
   2505      * Changes take effect immediately if the target medium is active or
   2506      * the preferred medium changes.
   2507      */
   2508     if (change_medium->enable != cfg->enable) {
   2509         medium_update = TRUE;
   2510     }
   2511     if (change_medium->preferred != cfg->preferred) {
   2512         /* Make sure that only one medium is preferred */
   2513         other_medium->preferred = !cfg->preferred;
   2514         medium_update = TRUE;
   2515     }
   2516 
   2517     sal_memcpy(change_medium, cfg, sizeof(*change_medium));
   2518 
   2519     if (!PHY_FORCED_COPPER_MODE(unit, port)) {
   2520         PHY_FW_HANDSHAKE(unit, port);
   2521         SOC_IF_ERROR_RETURN
   2522             (MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, pc->fiber.preferred ? 1U<<8 : 0, 1U<<8));
   2523         PHY_FW_HANDSHAKE(unit, port);
   2524     }
   2525 
   2526     if (medium_update) {
   2527         /* The new configuration may cause medium change. Check
   2528          * and update medium.
   2529          */
   2530         SOC_IF_ERROR_RETURN
   2531             (_phy_8481_medium_change(unit, port,TRUE));
   2532     } else {
   2533         active_medium = (PHY_COPPER_MODE(unit, port)) ?  
   2534                             &pc->copper : &pc->fiber;
   2535         if (active_medium == change_medium) {
   2536             /* If the medium to update is active, update the configuration */
   2537             SOC_IF_ERROR_RETURN
   2538                 (_phy_8481_medium_config_update(unit, port, change_medium));
   2539         }
   2540     }
   2541     return SOC_E_NONE;
   2542 }
   2543 
   2544 /*
   2545  * Function:
   2546  *      phy_8481_medium_config_get
   2547  * Purpose:
   2548  *      Get the operating parameters that are automatically selected
   2549  *      when medium switches type.
   2550  * Parameters:
   2551  *      unit - StrataSwitch unit #
   2552  *      port - Port number
   2553  *      medium - SOC_PORT_MEDIUM_COPPER/XAUI
   2554  *      cfg - (OUT) Operating parameters
   2555  * Returns:
   2556  *      SOC_E_XXX
   2557  */
   2558 
   2559 STATIC int
   2560 phy_8481_medium_config_get(int unit, soc_port_t port, 
   2561                            soc_port_medium_t medium,
   2562                            soc_phy_config_t *cfg)
   2563 {
   2564     int            rv;
   2565     phy_ctrl_t    *pc;
   2566 
   2567     pc = EXT_PHY_SW_STATE(unit, port);
   2568     rv = SOC_E_NONE;
   2569 
   2570     switch (medium) {
   2571     case SOC_PORT_MEDIUM_COPPER:
   2572         if (pc->automedium || PHY_COPPER_MODE(unit, port)) {
   2573             sal_memcpy(cfg, &pc->copper, sizeof (*cfg));
   2574         } else {
   2575             rv = SOC_E_UNAVAIL;
   2576         }
   2577         break;
   2578     case SOC_PORT_MEDIUM_FIBER:
   2579         if (pc->automedium || (!PHY_COPPER_MODE(unit, port))) {
   2580             sal_memcpy(cfg, &pc->fiber, sizeof (*cfg));
   2581         } else {
   2582             rv = SOC_E_UNAVAIL;
   2583         }
   2584         break;
   2585     default:
   2586         rv = SOC_E_PARAM;
   2587         break;
   2588     }
   2589 
   2590     return rv;
   2591 }
   2592 
   2593 /* STATIC */ int
   2594 _phy84834_top_level_cmd_set(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size)
   2595 {
   2596     soc_timeout_t  to;
   2597     int            rv;
   2598     uint16 status;
   2599 
   2600     if ((size < 1) || (size > 4)) {
   2601         return (SOC_E_PARAM);
   2602     }
   2603 
   2604     if (cmd == PHY84834_DIAG_CMD_PAIR_SWAP_CHANGE) {
   2605         SOC_IF_ERROR_RETURN
   2606             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, PHY84834_CMD_OPEN_OVERRIDE));
   2607     }
   2608 
   2609     soc_timeout_init(&to, 7000000, 0);
   2610     do {
   2611         rv = READ_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, &status);
   2612         if (((status & PHY84834_CMD_OPEN_FOR_CMDS) != 0) ||
   2613             SOC_FAILURE(rv)) {
   2614             break;
   2615         }
   2616     } while (!soc_timeout_check(&to));
   2617     if ((status & PHY84834_CMD_OPEN_FOR_CMDS) == 0) {
   2618         LOG_CLI((BSL_META_U(unit,
   2619                             "PHY84834_TOP_LEVEL_CMD_SET failed: u=%d p=%d cmd=%08x\n"),
   2620                  unit, pc->port, cmd));
   2621         return (SOC_E_FAIL);
   2622     }
   2623 
   2624     if (size-- > 0) {
   2625         if (cmd == PHY84834_DIAG_CMD_PAIR_SWAP_CHANGE) {
   2626             SOC_IF_ERROR_RETURN
   2627                 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_4r(unit, pc, arg[0]));
   2628         } else {
   2629             SOC_IF_ERROR_RETURN
   2630                 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_3r(unit, pc, arg[0]));
   2631         }
   2632     }
   2633     if (size-- > 0) {
   2634         SOC_IF_ERROR_RETURN
   2635             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_4r(unit, pc, arg[1]));
   2636     }
   2637     /* coverity[dead_error_condition:FALSE] */
   2638     if (size-- > 0) {
   2639         /* coverity[dead_error_begin] */
   2640         SOC_IF_ERROR_RETURN
   2641             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_12r(unit, pc, arg[2]));
   2642     }
   2643     /* coverity[dead_error_condition:FALSE] */
   2644     if (size-- > 0) {
   2645         /* coverity[dead_error_begin] */ 
   2646         SOC_IF_ERROR_RETURN
   2647             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_13r(unit, pc, arg[3]));
   2648     }
   2649 
   2650     SOC_IF_ERROR_RETURN
   2651         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, cmd));
   2652 
   2653     soc_timeout_init(&to, 1000000, 0);
   2654     do {
   2655         rv = READ_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, &status);
   2656         if (((status & (PHY84834_CMD_COMPLETE_PASS | PHY84834_CMD_COMPLETE_ERROR)) != 0) ||
   2657             SOC_FAILURE(rv)) {
   2658             break;
   2659         }
   2660     } while (!soc_timeout_check(&to));
   2661     if ((status & PHY84834_CMD_COMPLETE_PASS) == 0) {
   2662         LOG_CLI((BSL_META_U(unit,
   2663                             "PHY84834_TOP_LEVEL_CMD_SET failed: u=%d p=%d cmd=%08x\n"),
   2664                  unit, pc->port, cmd));
   2665         return (SOC_E_FAIL);
   2666     }
   2667 
   2668     SOC_IF_ERROR_RETURN
   2669         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE));
   2670 
   2671     return (SOC_E_NONE);
   2672 }
   2673 
   2674 /* STATIC */ int
   2675 _phy84834_top_level_cmd_get(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size)
   2676 {
   2677     soc_timeout_t  to;
   2678     int            rv;
   2679     uint16 status;
   2680 
   2681     if ((size < 1) || (size > 4)) {
   2682         return (SOC_E_PARAM);
   2683     }
   2684 
   2685     soc_timeout_init(&to, 7000000, 0);
   2686     do {
   2687         rv = READ_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, &status);
   2688         if (((status & PHY84834_CMD_OPEN_FOR_CMDS) != 0) ||
   2689             SOC_FAILURE(rv)) {
   2690             break;
   2691         }
   2692     } while (!soc_timeout_check(&to));
   2693     if ((status & PHY84834_CMD_OPEN_FOR_CMDS) == 0) {
   2694         LOG_CLI((BSL_META_U(unit,
   2695                             "PHY84834_TOP_LEVEL_CMD_GET failed: u=%d p=%d cmd=%08x\n"),
   2696                  unit, pc->port, cmd));
   2697         return (SOC_E_FAIL);
   2698     }
   2699     SOC_IF_ERROR_RETURN
   2700         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, cmd));
   2701 
   2702     soc_timeout_init(&to, 1000000, 0);
   2703 
   2704     do {
   2705         rv = READ_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, &status);
   2706         if (((status & (PHY84834_CMD_COMPLETE_PASS | PHY84834_CMD_COMPLETE_ERROR)) != 0) ||
   2707             SOC_FAILURE(rv)) {
   2708             break;
   2709         }
   2710     } while (!soc_timeout_check(&to));
   2711     if ((status & PHY84834_CMD_COMPLETE_PASS) == 0) {
   2712         LOG_CLI((BSL_META_U(unit,
   2713                             "PHY84834_TOP_LEVEL_CMD_GET failed: u=%d p=%d cmd=%08x\n"),
   2714                  unit, pc->port, cmd));
   2715         return (SOC_E_FAIL);
   2716     }
   2717     if (size-- > 0) {
   2718         SOC_IF_ERROR_RETURN
   2719             (READ_PHY84834_TOP_CONFIG_SCRATCH_3r(unit, pc, &arg[0]));
   2720     }
   2721     if (size-- > 0) {
   2722         SOC_IF_ERROR_RETURN
   2723             (READ_PHY84834_TOP_CONFIG_SCRATCH_4r(unit, pc, &arg[1]));
   2724     }
   2725     /* coverity[dead_error_condition:FALSE] */
   2726     if (size-- > 0) {
   2727         /* coverity[dead_error_begin] */ 
   2728         SOC_IF_ERROR_RETURN
   2729             (READ_PHY84834_TOP_CONFIG_SCRATCH_12r(unit, pc, &arg[2]));
   2730     }
   2731     /* coverity[dead_error_condition:FALSE] */
   2732     if (size-- > 0) {
   2733         /* coverity[dead_error_begin] */
   2734         SOC_IF_ERROR_RETURN
   2735             (READ_PHY84834_TOP_CONFIG_SCRATCH_13r(unit, pc, &arg[3]));
   2736     }
   2737 
   2738     SOC_IF_ERROR_RETURN
   2739         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE));
   2740 
   2741     return (SOC_E_NONE);
   2742 
   2743 }
   2744 
   2745 /* STATIC */ int
   2746 _phy84834_top_level_cmd_set_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size)
   2747 {
   2748     soc_timeout_t  to;
   2749     int            rv;
   2750     uint16 status;
   2751 
   2752     if ((size < 1) || (size > 5)) {
   2753         return (SOC_E_PARAM);
   2754     }
   2755 
   2756     soc_timeout_init(&to, 7000000, 0);
   2757     do {
   2758         rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status);
   2759         if (PHY8481_IS_READY_FOR_CMD(pc, status) || SOC_FAILURE(rv)) {    
   2760             break;
   2761         }
   2762     } while (!soc_timeout_check(&to));
   2763     if (!PHY8481_IS_OPEN_FOR_CMD(pc, status)) {
   2764         LOG_CLI((BSL_META_U(unit,
   2765                             "PHY84834_TOP_LEVEL_CMD_SET failed:<1> u=%d p=%d "
   2766                             "cmd=%04x status=%04x\n"), unit, pc->port, cmd, status));
   2767         return (SOC_E_FAIL);
   2768     }
   2769     
   2770     if (size-- > 0) {
   2771         if (cmd == PHY84834_DIAG_CMD_SET_PAIR_SWAP_V2) {
   2772             SOC_IF_ERROR_RETURN
   2773                 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, arg[0]));
   2774         } else {
   2775             SOC_IF_ERROR_RETURN
   2776                 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, arg[0]));
   2777         }
   2778     }
   2779     if (size-- > 0) {
   2780         SOC_IF_ERROR_RETURN
   2781             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, arg[1]));
   2782     }
   2783     /* coverity[dead_error_condition:FALSE] */ 
   2784     if (size-- > 0) {
   2785          /* coverity[dead_error_begin] */
   2786         SOC_IF_ERROR_RETURN
   2787             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, arg[2]));
   2788     }
   2789     /* coverity[dead_error_condition:FALSE] */
   2790     if (size-- > 0) {
   2791         /* coverity[dead_error_begin] */
   2792         SOC_IF_ERROR_RETURN
   2793             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, arg[3]));
   2794     }
   2795     /* coverity[dead_error_condition:FALSE] */
   2796     if (size-- > 0) {
   2797         /* coverity[dead_error_begin] */
   2798         SOC_IF_ERROR_RETURN
   2799             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_31r(unit, pc, arg[4]));
   2800     }
   2801 
   2802     SOC_IF_ERROR_RETURN
   2803         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, cmd));
   2804 
   2805     soc_timeout_init(&to, 7000000, 0);
   2806     do {
   2807         rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status);
   2808         if (PHY8481_IS_CMD_COMPLETE(pc, status) || SOC_FAILURE(rv)) {
   2809             break;
   2810         }
   2811     } while (!soc_timeout_check(&to));
   2812     if (status != PHY8481_CMD_COMPLETE_PASS) {
   2813         LOG_CLI((BSL_META_U(unit,
   2814                             "PHY84834_TOP_LEVEL_CMD_SET failed:<2> u=%d p=%d "
   2815                             "cmd=%04x status=%04x\n"), unit, pc->port, cmd, status));
   2816         return (SOC_E_FAIL);
   2817     }
   2818 
   2819     if (PHY_IS_BCM8483X(pc) || PHY_IS_BCM8484X(pc)) {
   2820     SOC_IF_ERROR_RETURN
   2821         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE));
   2822     }
   2823     return (SOC_E_NONE);
   2824 }
   2825 
   2826 /* STATIC */ int
   2827 _phy84834_top_level_cmd_get_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size)
   2828 {
   2829     soc_timeout_t  to;
   2830     int            rv;
   2831     uint16 status;
   2832 
   2833     if ((size < 1) || (size > 5)) {
   2834         return (SOC_E_PARAM);
   2835     }
   2836 
   2837     soc_timeout_init(&to, 7000000, 0);
   2838     do {
   2839         rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status);
   2840         if (PHY8481_IS_READY_FOR_CMD(pc, status) || SOC_FAILURE(rv)) {
   2841             break;
   2842         }
   2843     } while (!soc_timeout_check(&to));
   2844     if (!PHY8481_IS_OPEN_FOR_CMD(pc, status)) {
   2845         LOG_CLI((BSL_META_U(unit,
   2846                             "PHY84834_TOP_LEVEL_CMD_GET failed:<1> u=%d p=%d "
   2847                             "cmd=%04x status=%04x\n"), unit, pc->port, cmd, status));
   2848         return (SOC_E_FAIL);
   2849     }
   2850     SOC_IF_ERROR_RETURN
   2851         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, cmd));
   2852 
   2853     soc_timeout_init(&to, 1000000, 0);
   2854     do {
   2855         rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status);
   2856         if (PHY8481_IS_CMD_COMPLETE(pc, status) || SOC_FAILURE(rv)) {
   2857             break;
   2858         }
   2859     } while (!soc_timeout_check(&to));
   2860     if (status != PHY8481_CMD_COMPLETE_PASS) {
   2861         LOG_CLI((BSL_META_U(unit,
   2862                             "PHY84834_TOP_LEVEL_CMD_GET failed:<2> u=%d p=%d "
   2863                             "cmd=%04x status=%04x\n"), unit, pc->port, cmd, status));
   2864         return (SOC_E_FAIL);
   2865     }
   2866 
   2867     if (size-- > 0) {
   2868         if (cmd == PHY84834_DIAG_CMD_GET_PAIR_SWAP_V2 && !(PHY_IS_BCM8488X(pc)) ) {
   2869             SOC_IF_ERROR_RETURN
   2870                 (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &arg[0]));
   2871         } else {
   2872             SOC_IF_ERROR_RETURN
   2873                 (READ_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, &arg[0]));
   2874         }
   2875     }
   2876     if (size-- > 0) {
   2877         SOC_IF_ERROR_RETURN
   2878             (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &arg[1]));
   2879     }
   2880     /* coverity[dead_error_condition:FALSE] */
   2881     if (size-- > 0) {
   2882         /* coverity[dead_error_begin] */ 
   2883         SOC_IF_ERROR_RETURN
   2884             (READ_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, &arg[2]));
   2885     }
   2886     /* coverity[dead_error_condition:FALSE] */
   2887     if (size-- > 0) {
   2888         /* coverity[dead_error_begin] */
   2889         SOC_IF_ERROR_RETURN
   2890             (READ_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, &arg[3]));
   2891     }
   2892     /* coverity[dead_error_condition:FALSE] */
   2893     if (size-- > 0) {
   2894         /* coverity[dead_error_begin] */
   2895         SOC_IF_ERROR_RETURN
   2896             (READ_PHY84834_TOP_CONFIG_SCRATCH_31r(unit, pc, &arg[4]));
   2897     }
   2898 
   2899     if (PHY_IS_BCM8483X(pc) || PHY_IS_BCM8484X(pc)) {
   2900         SOC_IF_ERROR_RETURN
   2901             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE));
   2902     }
   2903 
   2904     return (SOC_E_NONE);
   2905 
   2906 }
   2907 
   2908 /* READ a register: 32-bit addressing mode */
   2909 int
   2910 _phy848xx_addr32_reg_read(int unit, phy_ctrl_t *pc, uint32 addr32, uint16 *val)
   2911 {
   2912     uint16       cmd_args[3];
   2913 
   2914     cmd_args[0] = ADDR32BIT_HIGH(addr32);
   2915     cmd_args[1] = ADDR32BIT_LOW( addr32);
   2916     cmd_args[2] = ADDR32BIT_READ;
   2917     SOC_IF_ERROR_RETURN(
   2918         PHY84834_TOP_LEVEL_CMD_SET(unit, pc,
   2919                                    PHY84834_DIAG_CMD_ACCESS_32BIT_XFI_ADDR,
   2920                                    cmd_args, 3) );
   2921     SOC_IF_ERROR_RETURN(    /* get the value from Command Handler Data 5 Reg. */
   2922                 READ_PHY84834_TOP_CONFIG_SCRATCH_31r(unit, pc, val) );
   2923     return SOC_E_NONE;
   2924 }
   2925 
   2926 /* WRITE a register: 32-bit addressing mode */
   2927 int
   2928 _phy848xx_addr32_reg_write(int unit, phy_ctrl_t *pc, uint32 addr32, uint16 val)
   2929 {
   2930     uint16       cmd_args[4];
   2931 
   2932     cmd_args[0] = ADDR32BIT_HIGH(addr32);
   2933     cmd_args[1] = ADDR32BIT_LOW( addr32);
   2934     cmd_args[2] = ADDR32BIT_WRITE;
   2935     cmd_args[3] = val;      /* 16-bit data to be written to the register */
   2936     SOC_IF_ERROR_RETURN(
   2937         PHY84834_TOP_LEVEL_CMD_SET(unit, pc,
   2938                                    PHY84834_DIAG_CMD_ACCESS_32BIT_XFI_ADDR,
   2939                                    cmd_args, 4) );
   2940     return SOC_E_NONE;
   2941 }
   2942 
   2943 /* MODIFY a register: 32-bit addressing mode */
   2944 int
   2945 _phy848xx_addr32_reg_modify(int unit, phy_ctrl_t *pc, uint32 addr32,
   2946                             uint16 val, uint16 mask)
   2947 {
   2948     uint16       data16;
   2949     SOC_IF_ERROR_RETURN( _phy848xx_addr32_reg_read(unit, pc, addr32, &data16) );
   2950     data16 =  (data16 & (~mask)) | val;
   2951     SOC_IF_ERROR_RETURN( _phy848xx_addr32_reg_write(unit, pc, addr32, data16) );
   2952     return SOC_E_NONE;
   2953 }
   2954 
   2955 #ifdef BCM_WARM_BOOT_SUPPORT
   2956 STATIC int
   2957 _phy84834_top_level_cmd_get_dispatch_v2(int unit,phy_ctrl_t *pc, uint16 cmd)
   2958 {
   2959     int            rv;
   2960     uint16 status;
   2961 
   2962     soc_timeout_init(&TO(pc), 7000000, 0);
   2963 
   2964     do {
   2965         rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status);
   2966         if (PHY8481_IS_READY_FOR_CMD(pc, status) ||SOC_FAILURE(rv)) {
   2967             break;
   2968         }
   2969     } while (!soc_timeout_check(&TO(pc)));
   2970     if (!PHY8481_IS_OPEN_FOR_CMD(pc, status)) {
   2971         LOG_CLI((BSL_META_U(unit,
   2972                             "PHY84834_TOP_LEVEL_CMD_GET (dispatch) failed:<1>"
   2973                             " u=%d p=%d cmd=%04x status=%04x\n"),
   2974                  unit, pc->port, cmd, status));
   2975         return SOC_E_FAIL;
   2976     }
   2977     SOC_IF_ERROR_RETURN
   2978         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, cmd));
   2979 
   2980     soc_timeout_init(&TO(pc), 1000000, 0);
   2981 
   2982     return SOC_E_NONE;
   2983 }
   2984 
   2985 STATIC int
   2986 _phy84834_top_level_cmd_get_retrive_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size)
   2987 {
   2988     int            rv;
   2989     uint16 status;
   2990 
   2991     do {
   2992         rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status);
   2993         if (PHY8481_IS_CMD_COMPLETE(pc, status) || SOC_FAILURE(rv)) {
   2994             break;
   2995         }
   2996     } while (!soc_timeout_check(&TO(pc)));
   2997     if (status != PHY8481_CMD_COMPLETE_PASS) {
   2998         LOG_CLI((BSL_META_U(unit,
   2999                             "PHY84834_TOP_LEVEL_CMD_GET failed:<2> u=%d p=%d"
   3000                             "cmd=%04x status=%04x\n"), unit, pc->port, cmd, status));
   3001         return SOC_E_FAIL;
   3002     }
   3003     if (size-- > 0) {
   3004         if (cmd == PHY84834_DIAG_CMD_GET_PAIR_SWAP_V2) {
   3005             SOC_IF_ERROR_RETURN
   3006                 (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &arg[0]));
   3007         } else {
   3008             SOC_IF_ERROR_RETURN
   3009                 (READ_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, &arg[0]));
   3010         }
   3011     }
   3012 
   3013     if (size-- > 0) {
   3014         SOC_IF_ERROR_RETURN
   3015             (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &arg[1]));
   3016     }
   3017     if (size-- > 0) {
   3018         SOC_IF_ERROR_RETURN
   3019             (READ_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, &arg[2]));
   3020     }
   3021     if (size-- > 0) {
   3022         SOC_IF_ERROR_RETURN
   3023             (READ_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, &arg[3]));
   3024     }
   3025     if (size-- > 0) {
   3026         SOC_IF_ERROR_RETURN
   3027             (READ_PHY84834_TOP_CONFIG_SCRATCH_31r(unit, pc, &arg[4]));
   3028     }
   3029 
   3030     if (PHY_IS_BCM8483X(pc) || PHY_IS_BCM8484X(pc)) {
   3031         SOC_IF_ERROR_RETURN
   3032             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE));
   3033     }
   3034 
   3035     return SOC_E_NONE;
   3036 }
   3037 #endif
   3038 
   3039 STATIC int
   3040 _phy84834_eee_mode_set(int unit,phy_ctrl_t *pc, uint16 mode, uint16 ag_th_high, uint16 ag_th_low, uint16 latency )
   3041 {
   3042     uint16 args[5];
   3043     args[0] = mode;
   3044     args[1] = ag_th_high;
   3045     args[2] = ag_th_low;
   3046     args[3] = latency;
   3047 
   3048     SOC_IF_ERROR_RETURN
   3049         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_EEE_MODE_GENERIC, args, 4));
   3050 
   3051     return (SOC_E_NONE);
   3052 }
   3053 
   3054 STATIC int
   3055 _phy84834_eee_mode_get(int unit,phy_ctrl_t *pc, uint16 *mode, uint16 *ag_th_high, uint16 *ag_th_low, uint16 *latency )
   3056 {
   3057     uint16 args[5];
   3058 
   3059     SOC_IF_ERROR_RETURN
   3060         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_EEE_MODE_GENERIC, args, 4));
   3061 
   3062     if (mode) {
   3063         *mode = args[0];
   3064     }
   3065     if (ag_th_high) {
   3066         *ag_th_high = args[1];
   3067     }
   3068     if (ag_th_low) {
   3069         *ag_th_low = args[2];
   3070     }
   3071     if (latency) {
   3072         *latency = args[3];
   3073     }
   3074 
   3075     return (SOC_E_NONE);
   3076 }
   3077 
   3078 STATIC int
   3079 _phy84834_jumbo_packet_set(int unit, phy_ctrl_t *pc, uint16 mode)
   3080 {
   3081     uint16 args[2];
   3082     args[0] = mode;
   3083 
   3084     SOC_IF_ERROR_RETURN
   3085         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY848x_DIAG_CMD_SET_JUMBO_FRAME_MODE, args, 1));
   3086 
   3087     return (SOC_E_NONE);
   3088 }
   3089 
   3090 #if 0
   3091 STATIC int
   3092 _phy84834_jumbo_packet_get(int unit,phy_ctrl_t *pc, uint16 *mode)
   3093 {
   3094     uint16 args[2];
   3095 
   3096     SOC_IF_ERROR_RETURN
   3097         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY848x_DIAG_CMD_GET_JUMBO_FRAME_MODE, args, 1));
   3098 
   3099     if (mode) {
   3100         *mode = args[0];
   3101     }
   3102 
   3103     return (SOC_E_NONE);
   3104 }
   3105 #endif
   3106 
   3107 STATIC int
   3108 _phy84834_chip_current_temp_get(int unit,phy_ctrl_t *pc, uint16 *digital_temp, uint16 *analog_temp )
   3109 {
   3110     uint16 args[3];
   3111 
   3112     SOC_IF_ERROR_RETURN
   3113         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_CURRENT_TEMP_GENERIC, args, 2));
   3114 
   3115     if (digital_temp) {
   3116         *digital_temp = args[0];
   3117     }
   3118     if (analog_temp) {
   3119         *analog_temp = args[1];
   3120     }
   3121 
   3122     return (SOC_E_NONE);
   3123 }
   3124 
   3125 STATIC int
   3126 _phy84834_xfi_reg_set(int unit,phy_ctrl_t *pc, uint16 bank, uint16 offset, uint16 value )
   3127 {
   3128     uint16 args[5];
   3129     uint16 cmd;
   3130     args[0] = bank;
   3131     args[1] = offset;
   3132     args[2] = value;
   3133 
   3134     if (pc->flags & PHYCTRL_SYS_SIDE_CTRL)
   3135         cmd = (uint16)PHY84834_DIAG_CMD_SET_XFI_M_REG_VALUES_GENERIC;
   3136     else
   3137         cmd = (uint16)PHY84834_DIAG_CMD_SET_XFI_L_REG_VALUES_GENERIC;
   3138  
   3139     SOC_IF_ERROR_RETURN
   3140         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)cmd, args, 3));
   3141 
   3142     return (SOC_E_NONE);
   3143 }
   3144 
   3145 STATIC int
   3146 _phy84834_xfi_reg_get(int unit,phy_ctrl_t *pc, uint16 bank, uint16 offset, uint16 *value )
   3147 {
   3148     uint16 args[5];
   3149     uint16 cmd;
   3150     args[0] = bank;
   3151     args[1] = offset;
   3152 
   3153     if (pc->flags & PHYCTRL_SYS_SIDE_CTRL)
   3154         cmd = (uint16)PHY84834_DIAG_CMD_GET_XFI_M_REG_VALUES_GENERIC;
   3155     else
   3156         cmd = (uint16)PHY84834_DIAG_CMD_GET_XFI_L_REG_VALUES_GENERIC;
   3157     
   3158     SOC_IF_ERROR_RETURN
   3159         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, args[0]));
   3160     SOC_IF_ERROR_RETURN
   3161         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, args[1]));
   3162 
   3163     SOC_IF_ERROR_RETURN
   3164         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)cmd, args, 3));
   3165 
   3166     if (value) {
   3167         *value = args[2];
   3168     }
   3169 
   3170     return (SOC_E_NONE);
   3171 }
   3172 
   3173 
   3174 STATIC int
   3175 _phy84834_xfi_reg_set_v2(int unit, phy_ctrl_t *pc, uint16 pre_tap, uint16 main_tap, uint16 post1_tap, uint16 post2_tap, uint16 HPF_en)
   3176 {
   3177     uint16  args[5];
   3178 
   3179     args[0] = pre_tap;
   3180     args[1] = main_tap;
   3181     args[2] = post1_tap;
   3182     args[3] = post2_tap;
   3183     args[4] = HPF_en;
   3184 
   3185     /* Koi BCM8485X only supports system side preemphasis  */
   3186     if ( pc->flags & PHYCTRL_SYS_SIDE_CTRL ) {
   3187         return  PHY84834_TOP_LEVEL_CMD_SET(unit, pc,
   3188                     (uint16) PHY84834_DIAG_CMD_SET_XFI_TX_FILTERS_GENERIC, args, 5);
   3189     }
   3190     return (SOC_E_UNAVAIL);
   3191 }
   3192 
   3193 STATIC int
   3194 _phy84834_xfi_reg_get_v2(int unit, phy_ctrl_t *pc, uint16 *pre_tap, uint16 *main_tap, uint16 *post1_tap, uint16 *post2_tap, uint16 *HPF_en )
   3195 {
   3196     uint16 args[5];
   3197     uint16 cmd = 0;
   3198 
   3199     /* Koi BCM8485X only supports system side preemphasis  */
   3200     if (pc->flags & PHYCTRL_SYS_SIDE_CTRL)
   3201         cmd = (uint16)PHY84834_DIAG_CMD_GET_XFI_TX_FILTERS_GENERIC;
   3202 
   3203     SOC_IF_ERROR_RETURN
   3204         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)cmd, args, 5));
   3205 
   3206     if (pre_tap) {
   3207         *pre_tap = args[0];
   3208     }
   3209     if (main_tap) {
   3210         *main_tap = args[1];
   3211     }
   3212     if (post1_tap) {
   3213         *post1_tap = args[2];
   3214     }
   3215     if (post2_tap) {
   3216         *post2_tap = args[3];
   3217     }
   3218     if (HPF_en) {
   3219         *HPF_en = args[4];
   3220     }
   3221 
   3222     return (SOC_E_NONE);
   3223 }
   3224 
   3225 
   3226 STATIC uint16
   3227 _sign_extend_16(uint16 val, uint8 ori_sz_in_bit)
   3228 {
   3229     uint16  neg_max =  0x1 << (ori_sz_in_bit - 1);
   3230     uint16  mask    =  (0x1 << ori_sz_in_bit) - 1;
   3231     /*
   3232      * example of ori_sz_in_bit = 5
   3233      *   neg_max = 0x0010 =  0x1 << (5 - 1)
   3234      *   mask    = 0x001f =  (0x1 << 5) - 1
   3235      *  ~mask    = 0xffe0 = ~0x001f    [extension prefix for negative num]
   3236      */
   3237 	val &= mask;
   3238     if ( val & neg_max ) {    /* if a negative number  */
   3239         val |= (~mask);       /* sign extension for 16-bit number */
   3240     }
   3241 
   3242     return  val;
   3243 }
   3244 
   3245 #define  BITMASK_7_0    (0xFF)
   3246 #define  XFIM           0
   3247 #define  XFIL           1
   3248 
   3249 STATIC int
   3250 _phy8488x_xfi_tx_filter_set(int unit, phy_ctrl_t *pc, uint16 pre_tap, uint16 main_tap,
   3251                             uint16 post1_tap, uint16 post2_tap, uint16 post3_tap)
   3252 {
   3253     uint16  args[5];
   3254 
   3255     /* 8488x supports XFI Config Type = 0 (XFIM) only */
   3256     args[0] =  0;       /* (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? XFIM : XFIL; */
   3257     /* get the current values of XFI_TX_FILTERS first */
   3258     PHY84834_TOP_LEVEL_CMD_GET(unit, pc,
   3259                     (uint16) PHY84834_DIAG_CMD_GET_XFI_TX_FILTERS_GENERIC, args, 5);
   3260     args[0]  =  0;
   3261     args[1]  = (main_tap  << 8) | (pre_tap   & BITMASK_7_0);
   3262     args[2]  = (post2_tap << 8) | (post1_tap & BITMASK_7_0);
   3263     args[3] &=  ~BITMASK_7_0;              /* retain the bit[15:8] of DATA4 */
   3264     args[3] |=  post3_tap & BITMASK_7_0;
   3265     args[4]  =  0;       /* amp_ctrl & driver_mode are always 0 for 8488x */
   3266 
   3267     return  PHY84834_TOP_LEVEL_CMD_SET(unit, pc,
   3268                     (uint16) PHY84834_DIAG_CMD_SET_XFI_TX_FILTERS_GENERIC, args, 5);
   3269 }
   3270 
   3271 STATIC int
   3272 _phy8488x_xfi_tx_filter_get(int unit, phy_ctrl_t *pc, uint16 *pre_tap, uint16 *main_tap,
   3273                             uint16 *post1_tap, uint16 *post2_tap, uint16 *post3_tap)
   3274 {
   3275     uint16  args[5];
   3276 
   3277     /* 8488x supports XFI Config Type = 0 (XFIM) only */
   3278     args[0] =  0;       /* (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? XFIM : XFIL; */
   3279     SOC_IF_ERROR_RETURN(
   3280         PHY84834_TOP_LEVEL_CMD_GET(unit, pc,
   3281                     (uint16) PHY84834_DIAG_CMD_GET_XFI_TX_FILTERS_GENERIC, args, 5) );
   3282     if ( pre_tap   ) {
   3283         *pre_tap   = args[1] & BITMASK_7_0;
   3284     }
   3285     if ( main_tap  ) {
   3286         *main_tap  = args[1] >> 8;
   3287     }
   3288     if ( post1_tap ) {
   3289         *post1_tap = args[2] & BITMASK_7_0;
   3290     }
   3291     if ( post2_tap ) {      /* -15 <= Post2 <= 15 */
   3292         *post2_tap = _sign_extend_16((args[2] >> 8), 8);
   3293     }
   3294     if ( post3_tap ) {      /*  -7 <= Post2 <= 7  */
   3295         *post3_tap = _sign_extend_16((args[3] & BITMASK_7_0), 8);
   3296     }
   3297 
   3298     return (SOC_E_NONE);
   3299 }
   3300 
   3301 STATIC int
   3302 _phy8485x_shadow_reg_write(int unit, phy_ctrl_t *pc, uint16 reg_group, uint16 reg_addr, uint16 bit_mask, uint16 bit_shift, uint16 value) 
   3303 {
   3304     uint16 args[5];
   3305     uint16 cmd;
   3306     args[0] = reg_group;
   3307     args[1] = reg_addr;
   3308     args[2] = bit_mask;
   3309     args[3] = bit_shift;
   3310     args[4] = value;
   3311 
   3312     cmd = (uint16)PHY8485X_DIAG_CMD_WRITE_SHADOW_REG;
   3313 
   3314     SOC_IF_ERROR_RETURN
   3315         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)cmd, args, 5));
   3316 
   3317     return (SOC_E_NONE);
   3318 }
   3319 
   3320 STATIC int
   3321 _phy8485x_shadow_reg_read(int unit, phy_ctrl_t *pc, uint16 reg_group, uint16 reg_addr, uint16 bit_mask, uint16 bit_shift, uint16 *value) 
   3322 {
   3323     uint16 args[5];
   3324     uint16 cmd;
   3325     args[0] = reg_group;
   3326     args[1] = reg_addr;
   3327     args[2] = bit_mask;
   3328     args[3] = bit_shift;
   3329 
   3330     cmd = (uint16)PHY8485X_DIAG_CMD_READ_SHADOW_REG;
   3331 
   3332     SOC_IF_ERROR_RETURN
   3333         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, args[0]));
   3334     SOC_IF_ERROR_RETURN
   3335         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, args[1]));
   3336     SOC_IF_ERROR_RETURN
   3337         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, args[2]));
   3338     SOC_IF_ERROR_RETURN
   3339         (WRITE_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, args[3]));
   3340 
   3341     SOC_IF_ERROR_RETURN
   3342         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)cmd, args, 5));
   3343 
   3344     if (value) {
   3345         *value = args[4];
   3346     }
   3347 
   3348     return (SOC_E_NONE);
   3349 }
   3350 
   3351 STATIC int
   3352 _phy8481_adjust_xfi_tx_preemphasis(int unit, int port, phy_ctrl_t *pc, uint32 phy_long_xfi)
   3353 {
   3354     uint16 pre_tap = 0;
   3355     uint16 main_tap = 0;
   3356     uint16 post_tap1 = 0;
   3357     uint16 post_tap2 = 0;
   3358     uint16 HPF_en = 0;
   3359 
   3360     switch(phy_long_xfi) {
   3361 
   3362         case 1:
   3363             if (PHY_IS_BCM8485X_AND_UP(pc)) {
   3364 
   3365              /* The value format:
   3366              * bit 16:18: post_tap2 value
   3367              * bit 15:  1 enable forced preemphasis ctrl, 0 auto config
   3368              * bit 14:10:  post_tap value
   3369              * bit 09:04:  main tap value
   3370              * bit 03:00:  pre_tap value
   3371              */
   3372 
   3373             /* main_tap = 32d, post_tap = 12d, pre_tap=8d for long channel on KOI */    
   3374             pre_tap = 0x8;
   3375             main_tap = 0x20;
   3376             post_tap1 = 0xC;
   3377             post_tap2 = 0x0;
   3378             HPF_en = 0x0;
   3379 
   3380                 SOC_IF_ERROR_RETURN(
   3381                     _phy84834_xfi_reg_set_v2(unit, pc, pre_tap, main_tap, post_tap1, post_tap2, HPF_en));
   3382             
   3383             } else {
   3384                /* Register bank = 0x2  offset = 0xC value = 0x3AF7  */
   3385                 SOC_IF_ERROR_RETURN(
   3386                     _phy84834_xfi_reg_set(unit, pc, 0x2, 0xC, 0x3AF7));
   3387 
   3388             }
   3389             break;
   3390 
   3391         default:
   3392             break;
   3393     }
   3394 
   3395     return SOC_E_NONE;
   3396 }
   3397 
   3398 /*
   3399  * Function:
   3400  *      _phy_8481_control_tx_driver_set
   3401  * Purpose:
   3402  *      Configure PHY device specific control function.
   3403  * Parameters:
   3404  *      unit  - StrataSwitch unit #.
   3405  *      port  - StrataSwitch port #.
   3406  *      type  - Control to update
   3407  *      value - New setting for the control
   3408  * Returns:
   3409  *      SOC_E_NONE
   3410  */
   3411 STATIC int
   3412 _phy_8481_control_tx_driver_set(int unit, soc_port_t port,
   3413                      soc_phy_control_t type, uint32 value)
   3414 {
   3415     int rv;
   3416     phy_ctrl_t    *pc;       /* PHY software state */
   3417     uint16       data;  /* Temporary holder of reg value to be written */
   3418     uint16       tmp ;  /* Temporary holder of reg value read */
   3419     uint16       mask;  /* Bit mask of reg value to be updated */
   3420     uint16       HPF_en    = 0;
   3421     uint16       pre_tap   = 0;
   3422     uint16       main_tap  = 0;
   3423     uint16       post1_tap = 0;
   3424     uint16       post2_tap = 0;
   3425     uint16       post3_tap = 0;
   3426 
   3427     pc = EXT_PHY_SW_STATE(unit, port);
   3428 
   3429 #if 0
   3430     /* Support only system side in copper mode - for now */
   3431     if (PHY_COPPER_MODE(unit, port) && !(pc->flags & PHYCTRL_SYS_SIDE_CTRL)) {
   3432         return SOC_E_UNAVAIL;
   3433     }
   3434 #endif
   3435 
   3436     rv = SOC_E_NONE;
   3437     switch ( type ) {
   3438     case SOC_PHY_CONTROL_PREEMPHASIS:
   3439         if ( PHY_IS_BCM8488X(pc) ) {
   3440            /* format of 'value':      Decimal   Hexadecimal
   3441             *   bit 27:24 post3       [-7,7]    [0x9 ,0x7]
   3442             *   bit 22:18 post2       [-15,15]  [0x11,0x0f]
   3443             *   bit 17:12 post1       [0,63]    [0x00,0x3f]
   3444             *   bit 11:05 main tap    [0,112]   [0x00,0x70]
   3445             *   bit 04:00 pre_tap     [0,31]    [0x00,0x1f]
   3446             * criterion A: ( main + 48 > pre + post1 + post2 + post3 )
   3447             * criterion B: ( main + pre + post1 + |post2| + |post3| <= 112 )
   3448             */
   3449             pre_tap   = PHY8488X_PREEMPH_GET_PRE_TAP(value);
   3450             main_tap  = PHY8488X_PREEMPH_GET_MAIN_TAP(value);
   3451             post1_tap = PHY8488X_PREEMPH_GET_POST1_TAP(value);
   3452             post2_tap = _sign_extend_16(PHY8488X_PREEMPH_GET_POST2_TAP(value), 5);
   3453             post3_tap = _sign_extend_16(PHY8488X_PREEMPH_GET_POST3_TAP(value), 4);
   3454             
   3455             /* Set Data 1 - Data 5 values  */
   3456             SOC_IF_ERROR_RETURN(
   3457                 _phy8488x_xfi_tx_filter_set(unit, pc, pre_tap, main_tap,
   3458                                             post1_tap, post2_tap, post3_tap));
   3459 
   3460         } else
   3461         if ( PHY_IS_BCM8485X_AND_UP(pc) ) {
   3462             /* The value format:
   3463             * bit 18:16: post_tap2 value
   3464             * bit 15:  1 enable forced preemphasis ctrl, 0 auto config
   3465             * bit 14:10:  post_tap value
   3466             * bit 09:04:  main tap value
   3467             * bit 03:00:  pre_tap value
   3468             */
   3469             pre_tap   = PHY8485X_PREEMPH_GET_PRE_TAP(value);
   3470             main_tap  = PHY8485X_PREEMPH_GET_MAIN_TAP(value);
   3471             post1_tap = PHY8485X_PREEMPH_GET_POST_TAP1(value);
   3472             post2_tap = PHY8485X_PREEMPH_GET_POST_TAP2(value);
   3473             HPF_en    = PHY8485X_PREEMPH_GET_HPF_EN(value);
   3474             /* Set Data 1 - Data 5 values  */
   3475             SOC_IF_ERROR_RETURN(
   3476                 _phy84834_xfi_reg_set_v2(unit, pc, pre_tap, main_tap, post1_tap, post2_tap, HPF_en));
   3477         }
   3478         else {
   3479             mask     = 0xf800; /* Main Tap */
   3480             /* Register bank = 0x2  offset = 0xB value */
   3481             SOC_IF_ERROR_RETURN(
   3482                 _phy84834_xfi_reg_set(unit, pc, 0x2, 0xB, (value & mask)));
   3483             mask     = 0x00f7; /* Pre/Post Cursor */
   3484             /* Register bank = 0x2  offset = 0xC value */
   3485             SOC_IF_ERROR_RETURN(
   3486                 _phy84834_xfi_reg_set(unit, pc, 0x2, 0xC, (value & mask)));
   3487         }
   3488         break;
   3489     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   3490         if (PHY_IS_BCM8485X_AND_UP(pc)) {
   3491             /* register bit fields idriver no longer exist in Merlin Core */
   3492             rv = SOC_E_UNAVAIL;      
   3493         }
   3494         else {
   3495             data = (uint16)(value & 0xf);
   3496             data = data << 12;
   3497             mask = 0xf000;
   3498             data = data & mask; /* Mask off other bits */
   3499             /* Register bank = 0x2  offset = 0xA value */
   3500             SOC_IF_ERROR_RETURN(
   3501                 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xA, &tmp));
   3502 
   3503             tmp &= ~(mask);
   3504             tmp |= data;
   3505 
   3506             /* Register bank = 0x2  offset = 0xA value */
   3507             SOC_IF_ERROR_RETURN(
   3508                 _phy84834_xfi_reg_set(unit, pc, 0x2, 0xA, tmp));
   3509         }
   3510         break;
   3511     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   3512         if (PHY_IS_BCM8485X_AND_UP(pc)) {
   3513             /* register bit fields ipredriver no longer exist in Merlin Core */
   3514             rv = SOC_E_UNAVAIL;
   3515         }
   3516         else {
   3517             data = (uint16)(value & 0xf);
   3518             data = data << 8;
   3519             mask = 0x0f00;
   3520             data = data & mask; /* Mask off other bits */
   3521             /* Register bank = 0x2  offset = 0xA value */
   3522             SOC_IF_ERROR_RETURN(
   3523                 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xA, &tmp));
   3524 
   3525             tmp &= ~(mask);
   3526             tmp |= data;
   3527 
   3528             /* Register bank = 0x2  offset = 0xA value */
   3529             SOC_IF_ERROR_RETURN(
   3530                 _phy84834_xfi_reg_set(unit, pc, 0x2, 0xA, tmp));
   3531         }
   3532         break;
   3533     default:
   3534         rv = SOC_E_PARAM;
   3535         break;
   3536     }
   3537     return rv;
   3538 }
   3539 
   3540 /*
   3541  * Function:
   3542  *      _phy_8481_control_tx_driver_get
   3543  * Purpose:
   3544  *      Configure PHY device specific control function.
   3545  * Parameters:
   3546  *      unit  - StrataSwitch unit #.
   3547  *      port  - StrataSwitch port #.
   3548  *      type  - Control to update
   3549  *      value - New setting for the control
   3550  * Returns:
   3551  *      SOC_E_NONE
   3552  */
   3553 STATIC int
   3554 _phy_8481_control_tx_driver_get(int unit, soc_port_t port,
   3555                      soc_phy_control_t type, uint32 *value)
   3556 {
   3557     int rv;
   3558     phy_ctrl_t  *pc;       /* PHY software state */
   3559     uint16       data;
   3560     uint32       temp = 0;
   3561     uint16       HPF_en    = 0;
   3562     uint16       pre_tap   = 0;
   3563     uint16       main_tap  = 0;
   3564     uint16       post1_tap = 0;
   3565     uint16       post2_tap = 0;
   3566     uint16       post3_tap = 0;
   3567 
   3568     pc = EXT_PHY_SW_STATE(unit, port);
   3569 #if 0
   3570     /* Support only system side in copper mode - for now */
   3571     if (PHY_COPPER_MODE(unit, port) && !(pc->flags & PHYCTRL_SYS_SIDE_CTRL)) {
   3572         return SOC_E_UNAVAIL;
   3573     }
   3574 #endif
   3575     rv = SOC_E_NONE;
   3576     switch(type) {
   3577     case SOC_PHY_CONTROL_PREEMPHASIS:
   3578         if ( PHY_IS_BCM8488X(pc) ) {
   3579            /* format of 'value':      Decimal   Hexadecimal
   3580             *   bit 27:24 post3       [-7,7]    [0x9 ,0x7]
   3581             *   bit 22:18 post2       [-15,15]  [0x11,0x0f]
   3582             *   bit 17:12 post1       [0,63]    [0x00,0x3f]
   3583             *   bit 11:05 main tap    [0,112]   [0x00,0x70]
   3584             *   bit 04:00 pre_tap     [0,31]    [0x00,0x1f]
   3585             */
   3586             SOC_IF_ERROR_RETURN(
   3587                 _phy8488x_xfi_tx_filter_get(unit, pc, &pre_tap, &main_tap,
   3588                                             &post1_tap, &post2_tap, &post3_tap));
   3589             *value = PHY8488X_PREEMPH_SET_PRE_TAP(pre_tap)
   3590                    | PHY8488X_PREEMPH_SET_MAIN_TAP(main_tap)
   3591                    | PHY8488X_PREEMPH_SET_POST1_TAP(post1_tap)
   3592                    | PHY8488X_PREEMPH_SET_POST2_TAP(post2_tap)
   3593                    | PHY8488X_PREEMPH_SET_POST3_TAP(post3_tap);
   3594 
   3595         } else
   3596         if (PHY_IS_BCM8485X_AND_UP(pc)) {
   3597             SOC_IF_ERROR_RETURN(
   3598                 _phy84834_xfi_reg_get_v2(unit, pc, &pre_tap, &main_tap, &post1_tap, &post2_tap, &HPF_en));
   3599         
   3600             *value = 0;
   3601             *value |= pre_tap;
   3602             main_tap = ((temp | main_tap) << 4);
   3603             post1_tap = ((temp | post1_tap) << 10);
   3604             HPF_en = ((temp | HPF_en) << 15);
   3605             post2_tap = ((temp | post2_tap) << 16);
   3606 
   3607             *value |= (main_tap | post1_tap | HPF_en | post2_tap);
   3608         }
   3609         else {
   3610             /* Register bank = 0x2  offset = 0xB value */
   3611             SOC_IF_ERROR_RETURN(
   3612                 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xB, &data));
   3613             *value = data & 0xf800; /* Main */
   3614             /* Register bank = 0x2  offset = 0xC value */
   3615             SOC_IF_ERROR_RETURN(
   3616                 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xC, &data));
   3617             *value |= (data & 0x00f7); /* Post and Pre cursor */
   3618         }
   3619         break;
   3620     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   3621         if (PHY_IS_BCM8485X_AND_UP(pc)) {
   3622             /* register bit fields idriver no longer exist in Merlin Core */            
   3623             rv = SOC_E_UNAVAIL;
   3624         }
   3625         else {
   3626             /* Register bank = 0x2  offset = 0xA value */
   3627             SOC_IF_ERROR_RETURN(
   3628                 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xA, &data));
   3629             *value = ((data & 0xf000) >> 12);    
   3630         }
   3631         break;
   3632     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   3633         if (PHY_IS_BCM8485X_AND_UP(pc)) {
   3634             /* register bit fields ipredriver no longer exist in Merlin Core */
   3635             rv = SOC_E_UNAVAIL;        
   3636         }
   3637         else {
   3638             /* Register bank = 0x2  offset = 0xA value */
   3639             SOC_IF_ERROR_RETURN(
   3640                 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xA, &data));
   3641             *value = ((data & 0x0f00) >> 8);    
   3642         }
   3643         break;
   3644     default:
   3645         rv = SOC_E_PARAM;
   3646         break;
   3647     }
   3648     return rv;
   3649 }
   3650 
   3651 STATIC int
   3652 _phy_8485x_force_cl72_config(int unit, phy_ctrl_t *pc, uint16 enable)
   3653 {
   3654     uint16 args[5]={0,};
   3655 
   3656     args[0] = enable;
   3657     SOC_IF_ERROR_RETURN
   3658         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_KR_MODE_ENABLE_V2, args, 1));
   3659 
   3660     return (SOC_E_NONE);
   3661 }
   3662 
   3663 int
   3664 _phy_8481_copper_control_driver_set(int unit, soc_port_t port,
   3665                                 soc_phy_control_t type, uint32 value)
   3666 {
   3667     phy_ctrl_t  *pc;    /* PHY software state */
   3668     uint16 temp;
   3669     int rv = SOC_E_NONE;
   3670     uint16 mode;
   3671     int intf;
   3672 
   3673     pc = EXT_PHY_SW_STATE(unit, port);
   3674 
   3675     switch(type) {
   3676     case SOC_PHY_CONTROL_PREEMPHASIS:
   3677         /* fall through */
   3678     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   3679         /* fall through */
   3680     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   3681         rv = _phy_8481_control_tx_driver_set(unit, port, type, value);
   3682         break;
   3683     case SOC_PHY_CONTROL_LOOPBACK_EXTERNAL:
   3684     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   3685         SOC_IF_ERROR_RETURN
   3686             (MODIFY_PHY8481_MII_AUX_CTRLr(unit, pc, value ? 1U<<15 : 0, 1U<<15));
   3687         break;
   3688     case SOC_PHY_CONTROL_EEE:
   3689         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   3690             return SOC_E_UNAVAIL;
   3691         }
   3692 
   3693         if (value) {
   3694             /* Clearing 10G/1G EEE stats */
   3695             SOC_IF_ERROR_RETURN( _phy_8481_clear_eee_stats(unit, pc) );
   3696 
   3697             if (PHY_IS_BCM8483X_AND_UP(pc)) {
   3698                 /* 1G IEEE EEE, 10G IEEE EEE */
   3699                 if (PHY_IS_BCM8484X_AND_UP(pc)) {
   3700                     mode = 5;
   3701                 } else {
   3702                     mode = 1;
   3703                 }
   3704                 SOC_IF_ERROR_RETURN
   3705                     (_phy84834_eee_mode_set(unit, pc, mode, 0x0000, 0x0000, 0x0000 ));
   3706             } else {
   3707                 /* Disable AUTO EEE if native is enabled */
   3708                 SOC_IF_ERROR_RETURN
   3709                    (MODIFY_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, 0, 0x1));
   3710             }
   3711             SOC_IF_ERROR_RETURN
   3712                 (MODIFY_PHY8481_EEE_ADVr(unit, pc, 0x000e, 0x000e));
   3713 
   3714             pc->copper.advert_ability.eee |= (SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX);
   3715             temp = pc->copper.autoneg_enable;
   3716             /* Initiate AN */
   3717             SOC_IF_ERROR_RETURN
   3718                 (_phy_8481_copper_an_set(unit, port, 1));
   3719             pc->copper.autoneg_enable = temp;
   3720             if (PHY_IS_BCM8483X_AND_UP(pc)) {
   3721                 SOC_IF_ERROR_RETURN
   3722                     (_phy84834_eee_mode_get(unit, pc, &temp, NULL, NULL, NULL));
   3723             } 
   3724             PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   3725             PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE);
   3726         } else {
   3727             if (PHY_IS_BCM8483X_AND_UP(pc)) {
   3728                 SOC_IF_ERROR_RETURN
   3729                     (_phy84834_eee_mode_set(unit, pc, 0, 0x0000, 0x0000, 0x0000 ));
   3730             }
   3731             SOC_IF_ERROR_RETURN
   3732                 (MODIFY_PHY8481_EEE_ADVr(unit, pc, 0x0000, 0x000e));
   3733             pc->copper.advert_ability.eee &= ~(SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX);
   3734             SOC_IF_ERROR_RETURN
   3735                 (_phy_8481_copper_an_set(unit, port, pc->copper.autoneg_enable ? 1 : 0));
   3736             PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   3737         }
   3738         break;
   3739 
   3740     case SOC_PHY_CONTROL_EEE_AUTO:
   3741         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   3742             return SOC_E_UNAVAIL;
   3743         }
   3744 
   3745         if (value) {
   3746             /* Clearing 10G/1G EEE stats */
   3747             SOC_IF_ERROR_RETURN( _phy_8481_clear_eee_stats(unit, pc) );
   3748 
   3749             if (PHY_IS_BCM8483X_AND_UP(pc)) {
   3750                 /* 1G IEEE EEE, 10G IEEE EEE */
   3751                 if (PHY_IS_BCM8484X_AND_UP(pc)) {
   3752                     mode = 0xa;
   3753                 } else {
   3754                     mode = 2;
   3755                 }
   3756                 SOC_IF_ERROR_RETURN
   3757                     (_phy84834_eee_mode_set(unit, pc, mode, 0x0000, 0x3d09, ((PHY_IS_BCM8488X(pc)) ? 0x0480 : 0x047e) ));
   3758 
   3759             } else {
   3760                 SOC_IF_ERROR_RETURN
   3761                     (MODIFY_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, 0x0001, 0x0001));
   3762             }
   3763             SOC_IF_ERROR_RETURN
   3764                 (MODIFY_PHY8481_EEE_ADVr(unit, pc, 0x000e, 0x000e));
   3765 
   3766             pc->copper.advert_ability.eee |= (SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX);
   3767             temp = pc->copper.autoneg_enable;
   3768             /* Initiate AN */
   3769             SOC_IF_ERROR_RETURN
   3770                 (_phy_8481_copper_an_set(unit, port, 1));
   3771             pc->copper.autoneg_enable = temp;
   3772             if (PHY_IS_BCM8483X_AND_UP(pc)) {
   3773                 SOC_IF_ERROR_RETURN
   3774                     (_phy84834_eee_mode_get(unit, pc, &temp, NULL, NULL, NULL));
   3775             } 
   3776             PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   3777             PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_MODE);
   3778         } else {
   3779             if (PHY_IS_BCM8483X_AND_UP(pc)) {
   3780                 SOC_IF_ERROR_RETURN
   3781                     (_phy84834_eee_mode_set(unit, pc, 0, 0x0000, 0x0000, 0x0000 ));
   3782             } else {
   3783                 SOC_IF_ERROR_RETURN
   3784                     (MODIFY_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, 0x0000, 0x0001));
   3785             }
   3786             SOC_IF_ERROR_RETURN
   3787                 (MODIFY_PHY8481_EEE_ADVr(unit, pc, 0x0000, 0x000e));
   3788             SOC_IF_ERROR_RETURN
   3789                 (WRITE_PHY8481_PHYC_CTL_AI_LPI_CTLr(unit, pc, 0x8000));
   3790             SOC_IF_ERROR_RETURN
   3791                 (WRITE_PHY8481_PHYC_CTL_AI_LPI_CTLr(unit, pc, 0x0000));
   3792             pc->copper.advert_ability.eee &= ~(SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX);
   3793             SOC_IF_ERROR_RETURN
   3794                 (_phy_8481_copper_an_set(unit, port, pc->copper.autoneg_enable ? 1 : 0));
   3795             PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED);
   3796         }
   3797         break;
   3798 
   3799     case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY:
   3800         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   3801             return SOC_E_UNAVAIL;
   3802         }
   3803         if (PHY_IS_BCM8483X_AND_UP(pc)) {
   3804             uint16 mode=0, latency=0, th_high=0, th_low=0;
   3805             SOC_IF_ERROR_RETURN
   3806                 (_phy84834_eee_mode_get(unit, pc, &mode, &th_high, &th_low, &latency ));
   3807             /* Fixed latency can have only 0 or 1 value  */
   3808             if ((value != FALSE) && (value != TRUE)) {
   3809                  return SOC_E_PARAM;
   3810             }
   3811             if (value == FALSE) {
   3812                 /* Variable latency  */
   3813                 SOC_IF_ERROR_RETURN
   3814                     (_phy84834_eee_mode_set(unit, pc, 3, th_high, th_low, latency ));
   3815             } else {
   3816                 /* Fixed latency  */ 
   3817                 SOC_IF_ERROR_RETURN
   3818                     (_phy84834_eee_mode_set(unit, pc, 2, th_high, th_low, latency ));
   3819             }
   3820         } else {
   3821             SOC_IF_ERROR_RETURN
   3822                (MODIFY_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, value ? 1U<<1 : 0, 1U<<1));
   3823         }
   3824         break;
   3825 
   3826     case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD:
   3827         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   3828             return SOC_E_UNAVAIL;
   3829         }
   3830         if (PHY_IS_BCM8483X_AND_UP(pc)) {
   3831             uint16 mode=0, buffer_len=0;
   3832             SOC_IF_ERROR_RETURN
   3833                 (_phy84834_eee_mode_get(unit, pc, &mode, NULL, NULL, &buffer_len ));
   3834             SOC_IF_ERROR_RETURN
   3835                 (_phy84834_eee_mode_set(unit, pc, mode, (uint16)((value >> 16) & 0xffff), (uint16)(value & 0xffff), buffer_len ));
   3836         } else {
   3837             SOC_IF_ERROR_RETURN
   3838                 (WRITE_PHY8481_TOP_CONFIG_AUTOGREEN_THRESHOLD_LOWr(unit, pc, (uint16)(value & 0xffff)));
   3839             SOC_IF_ERROR_RETURN
   3840                 (WRITE_PHY8481_TOP_CONFIG_AUTOGREEN_THRESHOLD_HIGHr(unit, pc, (uint16)((value >> 16) & 0xffff)));
   3841         }
   3842 
   3843         break;
   3844     case SOC_PHY_CONTROL_EEE_STATISTICS_CLEAR:
   3845         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   3846             return SOC_E_UNAVAIL;
   3847         }
   3848 
   3849         /* Clearing 10G EEE stats: Enable clear on Read  */
   3850         SOC_IF_ERROR_RETURN
   3851             (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x0003, 0x000f));
   3852         SOC_IF_ERROR_RETURN
   3853             (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x000f, 0x000f));
   3854         SOC_IF_ERROR_RETURN
   3855             (READ_PHY8481_EXP_EEE_TX_EVENTS_HIGHr(unit, pc, &temp));
   3856         SOC_IF_ERROR_RETURN
   3857             (READ_PHY8481_EXP_EEE_TX_EVENTS_LOWr(unit, pc, &temp));
   3858         /* Clearing 10G EEE stats: Disable clear on Read  */
   3859         SOC_IF_ERROR_RETURN
   3860             (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x0002, 0x000f));
   3861         
   3862         /* Clearing 1G EEE stats  */       
   3863         SOC_IF_ERROR_RETURN
   3864             (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8002, 0x8002));
   3865         SOC_IF_ERROR_RETURN
   3866             (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8000, 0x8002));
   3867         break;
   3868         
   3869     case SOC_PHY_CONTROL_EEE_AUTO_BUFFER_LIMIT:
   3870     case SOC_PHY_CONTROL_EEE_TRANSMIT_WAKE_TIME:
   3871     case SOC_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME:
   3872     case SOC_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME:
   3873     case SOC_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME:
   3874     case SOC_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME:
   3875     case SOC_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME:
   3876     case SOC_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME:
   3877             return SOC_E_UNAVAIL;
   3878 
   3879     case SOC_PHY_CONTROL_POWER:
   3880         if (PHY_IS_BCM8483X_AND_UP(pc)) {
   3881             SOC_IF_ERROR_RETURN
   3882                 (_phy_84834_power_mode_set(unit,port,value));
   3883         }
   3884         break;
   3885 
   3886     case SOC_PHY_CONTROL_CL72:
   3887         if ( PHY_IS_BCM8485X_AND_UP(pc) ) {
   3888             rv = _phy_8485x_force_cl72_config(unit, pc, value);
   3889             break;
   3890         } else {
   3891             return SOC_E_UNAVAIL;
   3892         }
   3893 
   3894     case SOC_PHY_CONTROL_MGBASET_802P3BZ_PRIORITY:
   3895         if ( PHY_IS_BCM8488X(pc) ) {
   3896             rv = _phy_848xx_mgbase_802_3bz_type_set(unit, pc, value, value);
   3897             break;
   3898         } else {
   3899             return SOC_E_UNAVAIL;
   3900         }
   3901     
   3902     case SOC_PHY_CONTROL_SUPER_ISOLATE :
   3903         rv = MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc,
   3904                                     (value) ? TOP_CONFIG_XGPHY_DISABLE : 0x0,
   3905                                     TOP_CONFIG_XGPHY_DISABLE);
   3906         break;
   3907 
   3908     default:
   3909         intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
   3910         SOC_IF_ERROR_RETURN
   3911             (_phy_84834_control_set(unit, port, intf, PHY_DIAG_LN_DFLT, type, value));
   3912         break; 
   3913     }
   3914 
   3915     return rv;
   3916 }
   3917 
   3918 
   3919 STATIC int
   3920 _phy_8485x_force_cl72_status(int unit, phy_ctrl_t *pc, uint16 *value)
   3921 {
   3922 	uint16 args[5] = {0,};
   3923 
   3924     args[0] = 0;
   3925     SOC_IF_ERROR_RETURN
   3926         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_KR_MODE_ENABLE_V2, args, 1));
   3927     *value = args[0];
   3928 
   3929     return SOC_E_NONE;
   3930 }
   3931 
   3932 int
   3933 _phy_8481_copper_control_driver_get(int unit, soc_port_t port,
   3934                                 soc_phy_control_t type, uint32 *value)
   3935 {
   3936     phy_ctrl_t    *pc;       /* PHY software state */
   3937     uint16 temp, temp1;
   3938     uint16 digital_temp = 0, analog_temp = 0, frame_priority = 0;
   3939     int rv = SOC_E_NONE;
   3940     int speed=0;
   3941     int intf;
   3942  
   3943     pc = EXT_PHY_SW_STATE(unit, port);
   3944 
   3945     switch(type) {
   3946     case SOC_PHY_CONTROL_PREEMPHASIS:
   3947         /* fall through */
   3948     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   3949         /* fall through */
   3950     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   3951         rv = _phy_8481_control_tx_driver_get(unit, port, type, value);
   3952         break;
   3953     case SOC_PHY_CONTROL_LOOPBACK_EXTERNAL:
   3954     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   3955          SOC_IF_ERROR_RETURN
   3956              (READ_PHY8481_MII_AUX_CTRLr(unit, pc, &temp));
   3957          *value = temp & (1U<<15) ? 1 : 0;
   3958          break;
   3959 
   3960     case SOC_PHY_CONTROL_EEE:
   3961         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   3962             return SOC_E_UNAVAIL;
   3963         }
   3964         *value = (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) && 
   3965                  !PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_MODE)) ? 1 : 0;
   3966         break;
   3967 
   3968     case SOC_PHY_CONTROL_EEE_AUTO:
   3969         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   3970             return SOC_E_UNAVAIL;
   3971         }
   3972         *value = (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) && 
   3973                   PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_MODE)) ? 1 : 0;
   3974         break;
   3975 
   3976     case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY:
   3977         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   3978             return SOC_E_UNAVAIL;
   3979         }
   3980         if (PHY_IS_BCM8483X_AND_UP(pc)) {
   3981             uint16 mode=0, latency=0;
   3982             SOC_IF_ERROR_RETURN 
   3983                 (_phy84834_eee_mode_get(unit, pc, &mode, NULL, NULL, &latency ));
   3984             if (mode == 2 || mode == 6 || mode == 0xa) {
   3985                 *value = 1;
   3986             }
   3987             else if (mode == 3 || mode == 7 || mode == 0xb) {
   3988                 *value = 0;
   3989             }
   3990         } else {
   3991             SOC_IF_ERROR_RETURN
   3992                 (READ_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, &temp));
   3993             *value = (temp>>1) & 0x1;
   3994         }
   3995         break;
   3996 
   3997     case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD:
   3998         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   3999             return SOC_E_UNAVAIL;
   4000         }
   4001         if (PHY_IS_BCM8483X_AND_UP(pc)) {
   4002             SOC_IF_ERROR_RETURN
   4003                 (_phy84834_eee_mode_get(unit, pc, NULL, &temp1, &temp, NULL));
   4004         } else {
   4005            SOC_IF_ERROR_RETURN
   4006               (READ_PHY8481_TOP_CONFIG_AUTOGREEN_THRESHOLD_LOWr(unit, pc, &temp));
   4007            SOC_IF_ERROR_RETURN
   4008               (READ_PHY8481_TOP_CONFIG_AUTOGREEN_THRESHOLD_HIGHr(unit, pc, &temp1));
   4009         }
   4010         *value = (((uint32) temp1) << 16) | temp;
   4011         break;
   4012 
   4013     case SOC_PHY_CONTROL_EEE_TRANSMIT_EVENTS:
   4014         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   4015             return SOC_E_UNAVAIL;
   4016         }
   4017 
   4018         SOC_IF_ERROR_RETURN
   4019             (phy_8481_speed_get(unit, port, &speed));
   4020 
   4021         if (PHY_IS_BCM8484X(pc) || PHY_IS_BCM8485X_AND_UP(pc)) {
   4022             if (speed == 10000) {
   4023                 /* Latch the stats: Write 1 to bit 2 and 3 */
   4024                 SOC_IF_ERROR_RETURN
   4025                     (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x000c, 0x000c));
   4026             }
   4027             else 
   4028                 if (speed == 1000) {
   4029                     SOC_IF_ERROR_RETURN
   4030                         (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8001, 0x4001));
   4031                 }
   4032         }
   4033 
   4034         /* Speed 1G */
   4035         if (speed == 1000 ) {
   4036             SOC_IF_ERROR_RETURN
   4037                 (READ_PHY8481_EXP_1G_TX_EVENT(unit, pc,(uint16 *) value));
   4038         }
   4039         /* Speed 10G */
   4040         else
   4041             if (speed == 10000 ) {
   4042                 SOC_IF_ERROR_RETURN
   4043                    (READ_PHY8481_EXP_EEE_TX_EVENTS_LOWr(unit, pc, &temp));
   4044                 SOC_IF_ERROR_RETURN
   4045                    (READ_PHY8481_EXP_EEE_TX_EVENTS_HIGHr(unit, pc, &temp1));
   4046                 *value = (((uint32) temp1) << 16) | temp;
   4047             }
   4048         break;
   4049 
   4050     case SOC_PHY_CONTROL_EEE_TRANSMIT_DURATION:
   4051         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   4052             return SOC_E_UNAVAIL;
   4053         }
   4054         
   4055         SOC_IF_ERROR_RETURN
   4056             (phy_8481_speed_get(unit, port, &speed));
   4057 
   4058         if (PHY_IS_BCM8484X(pc) || PHY_IS_BCM8485X_AND_UP(pc)) {
   4059             if (speed == 10000) {
   4060                 /* Latch the stats: Write 1 to bit 2 and 3 */
   4061                 SOC_IF_ERROR_RETURN
   4062                     (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x000c, 0x000c));
   4063             }
   4064             else
   4065                 if (speed == 1000) {
   4066                     SOC_IF_ERROR_RETURN
   4067                         (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8001, 0x4001));
   4068                }
   4069         }
   4070 
   4071         /* Speed 1G */
   4072         if (speed == 1000 ) {
   4073             SOC_IF_ERROR_RETURN
   4074                 (READ_PHY8481_EXP_1G_TX_DURATION(unit, pc,(uint16 *) value));
   4075         }    
   4076         /* Speed 10G */
   4077         else
   4078             if (speed == 10000 ) {
   4079                 SOC_IF_ERROR_RETURN
   4080                    (READ_PHY8481_EXP_EEE_TX_DURATION_LOWr(unit, pc, &temp));
   4081                 SOC_IF_ERROR_RETURN
   4082                    (READ_PHY8481_EXP_EEE_TX_DURATION_HIGHr(unit, pc, &temp1));
   4083                 *value = (((uint32) temp1) << 16) | temp;
   4084         }
   4085         break;
   4086 
   4087     case SOC_PHY_CONTROL_EEE_RECEIVE_EVENTS:
   4088         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   4089             return SOC_E_UNAVAIL;
   4090         }
   4091 
   4092         SOC_IF_ERROR_RETURN
   4093             (phy_8481_speed_get(unit, port, &speed));
   4094 
   4095         if (PHY_IS_BCM8484X(pc) || PHY_IS_BCM8485X_AND_UP(pc)) {
   4096             if (speed == 10000) {
   4097                 /* Latch the stats: Write 1 to bit 2 and 3 */
   4098                 SOC_IF_ERROR_RETURN
   4099                    (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x000c, 0x000c));
   4100             }   
   4101             else
   4102                 if (speed == 1000) {
   4103                     SOC_IF_ERROR_RETURN
   4104                         (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8001, 0x4001));
   4105                }
   4106         }
   4107 
   4108         /* Speed 1G */
   4109         if (speed == 1000 ) {
   4110             SOC_IF_ERROR_RETURN
   4111                 (READ_PHY8481_EXP_1G_RX_EVENT(unit, pc,(uint16 *) value));
   4112         }
   4113         /* Speed 10G */
   4114         else
   4115             if (speed == 10000 ) {
   4116                 SOC_IF_ERROR_RETURN
   4117                    (READ_PHY8481_EXP_EEE_RX_EVENTS_LOWr(unit, pc, &temp));
   4118                 SOC_IF_ERROR_RETURN
   4119                    (READ_PHY8481_EXP_EEE_RX_EVENTS_HIGHr(unit, pc, &temp1));
   4120                 *value = (((uint32) temp1) << 16) | temp;
   4121             }
   4122         break;
   4123 
   4124     case SOC_PHY_CONTROL_EEE_RECEIVE_DURATION:
   4125         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   4126             return SOC_E_UNAVAIL;
   4127         }
   4128   
   4129         SOC_IF_ERROR_RETURN
   4130             (phy_8481_speed_get(unit, port, &speed));
   4131   
   4132         if (PHY_IS_BCM8484X(pc) || PHY_IS_BCM8485X_AND_UP(pc)) {
   4133             if (speed == 10000) {
   4134                 /* Latch the stats: Write 1 to bit 2 and 3 */
   4135                 SOC_IF_ERROR_RETURN
   4136                     (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x000c, 0x000c));
   4137             }
   4138             else
   4139                 if (speed == 1000) {
   4140                     SOC_IF_ERROR_RETURN
   4141                         (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8001, 0x4001));
   4142                }
   4143         }
   4144 
   4145         /* Speed 1G */
   4146         if (speed == 1000 ) {
   4147             SOC_IF_ERROR_RETURN
   4148                 (READ_PHY8481_EXP_1G_RX_DURATION(unit, pc,(uint16 *) value));
   4149         }
   4150         /* Speed 10G */
   4151         else
   4152             if (speed == 10000 ) {
   4153                 SOC_IF_ERROR_RETURN
   4154                    (READ_PHY8481_EXP_EEE_RX_DURATION_LOWr(unit, pc, &temp));
   4155                 SOC_IF_ERROR_RETURN
   4156                    (READ_PHY8481_EXP_EEE_RX_DURATION_HIGHr(unit, pc, &temp1));
   4157                 *value = (((uint32) temp1) << 16) | temp;
   4158             }
   4159         break;
   4160 
   4161     case SOC_PHY_CONTROL_POWER:
   4162         if (PHY_IS_BCM8483X_AND_UP(pc)) {
   4163             SOC_IF_ERROR_RETURN
   4164                 (_phy_84834_power_mode_get(unit,port,value));
   4165         } else {
   4166             *value = pc->power_mode;
   4167         }
   4168         break;
   4169 
   4170     case SOC_PHY_CONTROL_DIGITAL_TEMP:
   4171         if (PHY_IS_BCM8483X_AND_UP(pc)) {
   4172             SOC_IF_ERROR_RETURN
   4173                 (_phy84834_chip_current_temp_get(unit, pc, &digital_temp, NULL));
   4174         }
   4175         *value = digital_temp;
   4176         break;
   4177 
   4178     case SOC_PHY_CONTROL_ANALOG_TEMP:
   4179         if (PHY_IS_BCM8483X_AND_UP(pc)) {
   4180             SOC_IF_ERROR_RETURN
   4181                 (_phy84834_chip_current_temp_get(unit, pc, NULL, &analog_temp));
   4182         }
   4183         *value = analog_temp;
   4184         /* Invalid analog temperature value is returned  */
   4185         rv=SOC_E_UNAVAIL;
   4186         break;
   4187    
   4188     case SOC_PHY_CONTROL_MGBASET_802P3BZ_PRIORITY:
   4189         if ( PHY_IS_BCM8488X(pc) ) {
   4190             rv = _phy_848xx_mgbase_802_3bz_type_get(unit, pc, NULL, &frame_priority);
   4191             *value = frame_priority;
   4192         } else {
   4193             rv=SOC_E_UNAVAIL;
   4194         }
   4195         break;
   4196 
   4197     case SOC_PHY_CONTROL_SUPER_ISOLATE :
   4198         SOC_IF_ERROR_RETURN(
   4199                 READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &temp) );
   4200         *value = (temp & TOP_CONFIG_XGPHY_DISABLE) ? TRUE : FALSE;
   4201         break;
   4202 
   4203     default:
   4204         intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE;
   4205         SOC_IF_ERROR_RETURN
   4206             (_phy_84834_control_get(unit, port, intf, PHY_DIAG_LN_DFLT, type, value));
   4207         break;
   4208     }
   4209 
   4210     return rv;
   4211 }
   4212 
   4213 int
   4214 _phy_8481_xaui_control_driver_set(int unit, soc_port_t port,
   4215                                 soc_phy_control_t type, uint32 value)
   4216 {
   4217     switch(type) {
   4218     case SOC_PHY_CONTROL_PREEMPHASIS:
   4219          /*Fall through*/
   4220     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   4221          /*Fall through*/
   4222     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   4223          _phy_8481_control_tx_driver_set(unit, port, type, value);
   4224          break;
   4225 
   4226     default:
   4227          /* should never get here */
   4228          return SOC_E_UNAVAIL;
   4229     }
   4230 
   4231 
   4232 
   4233     return SOC_E_NONE;
   4234 }
   4235 
   4236 int
   4237 _phy_8481_xaui_control_driver_get(int unit, soc_port_t port,
   4238                                 soc_phy_control_t type, uint32 *value)
   4239 {
   4240     switch(type) {
   4241     case SOC_PHY_CONTROL_PREEMPHASIS:
   4242          /*Fall through*/
   4243     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   4244          /*Fall through*/
   4245     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   4246          _phy_8481_control_tx_driver_get(unit, port, type, value);
   4247          break;
   4248 
   4249     default:
   4250          /* should never get here */
   4251          return SOC_E_UNAVAIL;
   4252     }
   4253 
   4254     return SOC_E_NONE;
   4255 }
   4256 
   4257 /*
   4258  * Function:
   4259  *      phy_8481_control_set
   4260  * Purpose:
   4261  *      Configure PHY device specific control fucntion.
   4262  * Parameters:
   4263  *      unit  - StrataSwitch unit #.
   4264  *      port  - StrataSwitch port #.
   4265  *      type  - Control to update
   4266  *      value - New setting for the control
   4267  * Returns:
   4268  *      SOC_E_NONE
   4269  */
   4270 STATIC int
   4271 phy_8481_control_set(int unit, soc_port_t port,
   4272                      soc_phy_control_t type, uint32 value)
   4273 {
   4274     phy_ctrl_t    *pc;       /* PHY software state */
   4275 
   4276     pc = EXT_PHY_SW_STATE(unit, port);
   4277 
   4278     if (PHY_COPPER_MODE(unit, port)) {
   4279         return(_phy_8481_copper_control_driver_set(unit, port, type, value));
   4280     } else {
   4281         if (NXT_PC(pc)) {
   4282             PHYDRV_CALL_ARG2(pc,PHY_CONTROL_SET,type,value);
   4283             return SOC_E_NONE;
   4284         }
   4285         return(_phy_8481_xaui_control_driver_set(unit, port, type, value));
   4286     }
   4287 
   4288 }
   4289 /*
   4290  * Function:
   4291  *      phy_8481_control_get
   4292  * Purpose:
   4293  *      Get current control settign of the PHY.
   4294  * Parameters:
   4295  *      unit  - StrataSwitch unit #.
   4296  *      port  - StrataSwitch port #.
   4297  *      type  - Control to update
   4298  *      value - (OUT)Current setting for the control
   4299  * Returns:
   4300  *      SOC_E_NONE
   4301  */
   4302 STATIC int
   4303 phy_8481_control_get(int unit, soc_port_t port,
   4304                      soc_phy_control_t type, uint32 *value)
   4305 {
   4306     phy_ctrl_t    *pc;       /* PHY software state */
   4307 
   4308     pc = EXT_PHY_SW_STATE(unit, port);
   4309 
   4310     if (PHY_COPPER_MODE(unit, port)) {
   4311         return(_phy_8481_copper_control_driver_get(unit, port, type, value));
   4312     } else {
   4313         if (NXT_PC(pc)) {
   4314             PHYDRV_CALL_ARG2(pc,PHY_CONTROL_GET,type,value);
   4315             return SOC_E_NONE;
   4316         }
   4317         return(_phy_8481_xaui_control_driver_get(unit, port, type, value));
   4318     }
   4319 
   4320 }
   4321 
   4322 /*
   4323  * Function:
   4324  *      phy_8481_probe
   4325  * Purpose:
   4326  *      Complement the generic phy probe routine to identify this phy when its
   4327  *      phy id0 and id1 is same as some other phy's.  
   4328  * Parameters:
   4329  *      unit - StrataSwitch unit #.
   4330  *      pc   - phy ctrl descriptor.
   4331  * Returns:
   4332  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   4333  */
   4334                                                                                       
   4335 
   4336 STATIC int
   4337 phy_8481_probe(int unit, phy_ctrl_t *pc)
   4338 {
   4339     uint16 id0, id1;
   4340 
   4341     if ( READ_PHY8481_TOPLVL1_ID0r(unit, pc, &id0) < 0 ) {
   4342         return SOC_E_NOT_FOUND;
   4343     }
   4344 
   4345     if ( READ_PHY8481_TOPLVL1_ID1r(unit, pc, &id1) < 0 ) {
   4346         return SOC_E_NOT_FOUND;
   4347     }
   4348 
   4349     /* check OUI & MODEL ID to identify the PHY chip */
   4350     switch ( PHY_OUI_MODEL(PHY_OUI(id0, id1), PHY_MODEL(id0, id1)) ) {
   4351 
   4352     case  PHY_OUI_MODEL(PHY_BCM8481X_OUI, PHY_BCM8481X_MODEL) :
   4353         if ( PHY_REV(id0, id1) == 0x7)  {
   4354             /* 84812 detected */
   4355             PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4356             PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_XAUI);
   4357             pc->dev_name = "BCM84812";
   4358         }
   4359     break;
   4360 
   4361     case  PHY_OUI_MODEL(PHY_BCM84822_OUI, PHY_BCM84822_MODEL) :
   4362         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4363         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_XAUI);
   4364         if ( PHY_REV(id0, id1) != 0x0)  {
   4365             /* A0 does not support EEE */
   4366             PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE);
   4367         }
   4368     break;
   4369 
   4370     case  PHY_OUI_MODEL(PHY_BCM84823_OUI, PHY_BCM84823_MODEL) :
   4371         if ( PHY_REV(id0, id1) != 0x0)  {
   4372             /* A0 does not support EEE */
   4373             PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE);
   4374         }
   4375     break;
   4376 
   4377     case  PHY_OUI_MODEL(PHY_BCM84833_OUI, PHY_BCM84833_MODEL) :
   4378         if ( id1 & 0x8 ) {
   4379 #ifdef INCLUDE_MACSEC
   4380             if ( soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0) ) {
   4381                 return SOC_E_NOT_FOUND;
   4382             }
   4383 #endif
   4384             pc->dev_name = "BCM84333";
   4385         }
   4386     break;
   4387 
   4388     case  PHY_OUI_MODEL(PHY_BCM84836_OUI, PHY_BCM84836_MODEL) :
   4389         if ( id1 & 0x8 ) {
   4390 #ifdef INCLUDE_MACSEC
   4391             if ( soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0) ) {
   4392                 return SOC_E_NOT_FOUND;
   4393             }
   4394 #endif
   4395             pc->dev_name = "BCM84336";
   4396         }
   4397     break;
   4398 
   4399     case  PHY_OUI_MODEL(PHY_BCM84834_OUI, PHY_BCM84834_MODEL) :
   4400         if ( id1 & 0x8 ) {
   4401 #ifdef INCLUDE_MACSEC
   4402             if ( soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0) ) {
   4403                 return SOC_E_NOT_FOUND;
   4404             }
   4405 #endif
   4406             pc->dev_name = "BCM84334";
   4407         }
   4408         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4409         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER);
   4410     break;
   4411 
   4412     case  PHY_OUI_MODEL(PHY_BCM84835_OUI, PHY_BCM84835_MODEL) :
   4413         if ( id1 & 0x8 ) {
   4414             return SOC_E_NOT_FOUND;
   4415         }
   4416     break;
   4417 
   4418     case  PHY_OUI_MODEL(PHY_BCM84846_OUI, PHY_BCM84846_MODEL) :
   4419 #ifdef INCLUDE_MACSEC
   4420         if ( soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0) ) {
   4421             return SOC_E_NOT_FOUND;
   4422         }
   4423 #endif
   4424     break;
   4425 
   4426     case  PHY_OUI_MODEL(PHY_BCM84844_OUI, PHY_BCM84844_MODEL) :
   4427     case  PHY_OUI_MODEL(PHY_BCM84848_OUI, PHY_BCM84848_MODEL) :
   4428 #ifdef INCLUDE_MACSEC
   4429         if ( soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0) ) {
   4430             return SOC_E_NOT_FOUND;
   4431         }
   4432 #endif
   4433         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4434         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER);
   4435     break;
   4436 
   4437     case  PHY_OUI_MODEL(PHY_BCM84856_OUI, PHY_BCM84856_MODEL) :
   4438         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4439         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER);
   4440         pc->dev_name = "BCM84856";
   4441     break;
   4442     case  PHY_OUI_MODEL(PHY_BCM84858_OUI, PHY_BCM84858_MODEL) :
   4443         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4444         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER);
   4445         pc->dev_name = "BCM84858";
   4446     break;
   4447 
   4448     case  PHY_OUI_MODEL(PHY_BCM84860_OUI, PHY_BCM84860_MODEL) |
   4449           PHY_OUI_MODEL(PHY_BCM84861_OUI, PHY_BCM84861_MODEL) :
   4450         if ( PHY_REV(id0, id1) == 0x0)  {
   4451             pc->dev_name = "BCM84861";
   4452         }
   4453         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4454         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER);
   4455     break;
   4456 
   4457     case  PHY_OUI_MODEL(PHY_BCM84864_OUI, PHY_BCM84864_MODEL) |
   4458           PHY_OUI_MODEL(PHY_BCM84868_OUI, PHY_BCM84868_MODEL) :
   4459         if ( PHY_REV(id0, id1) == 0x0)  {
   4460             pc->dev_name = "BCM84868";
   4461         }
   4462         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4463         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER);
   4464     break;
   4465     
   4466     case  PHY_OUI_MODEL(PHY_BCM84888_OUI, PHY_BCM84888_MODEL) |
   4467           PHY_OUI_MODEL(PHY_BCM84887_OUI, PHY_BCM84887_MODEL) |
   4468           PHY_OUI_MODEL(PHY_BCM84884_OUI, PHY_BCM84884_MODEL) :
   4469         if ( (PHY_REV(id0, id1) == 0x0) || (PHY_REV(id0, id1) == 0x1) )  {
   4470             pc->dev_name = "BCM84888";
   4471         } else
   4472         if ( (PHY_REV(id0, id1) == 0x8) || (PHY_REV(id0, id1) == 0x9) )  {
   4473             pc->dev_name = "BCM84884";
   4474         } else
   4475         if ( (PHY_REV(id0, id1) == 0x4) || (PHY_REV(id0, id1) == 0x5) )  {
   4476             pc->dev_name = "BCM84887";
   4477         }
   4478         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4479         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER);
   4480     break;
   4481 
   4482     case  PHY_OUI_MODEL(PHY_BCM84888E_OUI, PHY_BCM84888E_MODEL) |
   4483           PHY_OUI_MODEL(PHY_BCM84884E_OUI, PHY_BCM84884E_MODEL) :
   4484         if ( (PHY_REV(id0, id1) == 0x0) || (PHY_REV(id0, id1) == 0x1) )  {
   4485             pc->dev_name = "BCM84888E";
   4486         } else
   4487         if ( (PHY_REV(id0, id1) == 0x8) || (PHY_REV(id0, id1) == 0x9) )  {
   4488             pc->dev_name = "BCM84884E";
   4489         }
   4490         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4491         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER);
   4492     break;       
   4493 
   4494     case  PHY_OUI_MODEL(PHY_BCM84881_OUI, PHY_BCM84881_MODEL) |
   4495           PHY_OUI_MODEL(PHY_BCM84880_OUI, PHY_BCM84880_MODEL) :
   4496         if ( (PHY_REV(id0, id1) == 0x0) || (PHY_REV(id0, id1) == 0x1) )  {
   4497             pc->dev_name = "BCM84881";
   4498         } else
   4499         if ( (PHY_REV(id0, id1) == 0x8) || (PHY_REV(id0, id1) == 0x9) )  {
   4500             pc->dev_name = "BCM84880";
   4501         }
   4502         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4503         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER);
   4504     break;
   4505 
   4506     case  PHY_OUI_MODEL(PHY_BCM84888S_OUI, PHY_BCM84888S_MODEL) |
   4507           PHY_OUI_MODEL(PHY_BCM84886_OUI, PHY_BCM84886_MODEL) |
   4508           PHY_OUI_MODEL(PHY_BCM84885_OUI, PHY_BCM84885_MODEL) :
   4509         if ( (PHY_REV(id0, id1) == 0x0) || (PHY_REV(id0, id1) == 0x1) )  {
   4510             pc->dev_name = "BCM84886";
   4511         } else
   4512         if ( (PHY_REV(id0, id1) == 0x8) || (PHY_REV(id0, id1) == 0x9) )  {
   4513             pc->dev_name = "BCM84885";
   4514         } else
   4515         if ( (PHY_REV(id0, id1) == 0x4) || (PHY_REV(id0, id1) == 0x5) )  {
   4516             pc->dev_name = "BCM84888S";
   4517         }
   4518         PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER);
   4519         PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER);
   4520     break;
   4521 
   4522     case  PHY_OUI_MODEL(PHY_BCM84812CE_OUI, PHY_BCM84812CE_MODEL) :
   4523     case  PHY_OUI_MODEL(PHY_BCM84821_OUI, PHY_BCM84821_MODEL) :
   4524 
   4525     break;
   4526 
   4527     default:
   4528         return SOC_E_NOT_FOUND;
   4529 
   4530     }
   4531     pc->size = sizeof(PHY8481_PRIV_t);
   4532 
   4533     return SOC_E_NONE;
   4534 
   4535 }
   4536 
   4537 /*
   4538  * Function:
   4539  *      phy_8481_speed_set
   4540  * Purpose:
   4541  *      Set PHY speed
   4542  * Parameters:
   4543  *      unit - StrataSwitch unit #.
   4544  *      port - StrataSwitch port #.
   4545  *      speed - link speed in Mbps
   4546  * Returns:
   4547  *      SOC_E_NONE
   4548  */
   4549 
   4550 STATIC int
   4551 _phy_8481_copper_speed_set(int unit, soc_port_t port, int speed)
   4552 {
   4553     phy_ctrl_t  *pc;
   4554     phy_ctrl_t  *int_pc;
   4555     uint16       speed_c45 = 0, speed_c22 = 0, speed_mg = 0;
   4556     int          lb_enable = 0, rv = SOC_E_NONE;
   4557 
   4558     LOG_INFO(BSL_LS_SOC_PHY,
   4559              (BSL_META_U(unit, "phy_8481_speed_set: u=%d p=%d speed=%d\n"),
   4560                                 unit, port, speed));
   4561     pc = EXT_PHY_SW_STATE(unit, port);
   4562     /* coverity[dead_error_condition:FALSE] */
   4563     int_pc = INT_PHY_SW_STATE(unit, port);
   4564     switch ( speed ) {
   4565         case 5000:
   4566             speed_mg = MGBASE_AN_CTRL_MG_ENABLE | MGBASE_AN_CTRL_SPEED_5G;
   4567             break;
   4568 
   4569         case 2500:
   4570             speed_mg = MGBASE_AN_CTRL_MG_ENABLE | MGBASE_AN_CTRL_SPEED_2P5G;
   4571             break;
   4572 
   4573         case 10000:
   4574             speed_c45 = IEEE_CTRLr_SPEED_10G;
   4575             speed_c22 = PMAD_MII_CTRL_SS_MSB | PMAD_MII_CTRL_SS_LSB;
   4576             break;
   4577 
   4578         case 1000:
   4579             speed_c45 = 0;
   4580             speed_c22 = PMAD_MII_CTRL_SS_1000;
   4581             break;
   4582 
   4583         case 100:
   4584             speed_c45 = 0;
   4585             speed_c22 = PMAD_MII_CTRL_SS_100;
   4586             break;
   4587 
   4588         case 10:
   4589             speed_c45 = 0;
   4590             speed_c22 = PMAD_MII_CTRL_SS_10;
   4591             break;
   4592 
   4593         default:
   4594             return SOC_E_PARAM;
   4595 
   4596     }
   4597 
   4598     if ( PHY_IS_BCM8486X_AND_UP(pc) ) {   /* Mako support 5G/2.5G */
   4599         /* MGBASE-T AN Control Reg.(30.0x0000), Speed_Select_5G/2.5G[6:5] */
   4600         SOC_IF_ERROR_RETURN(
   4601             MODIFY_PHY8481_MGBASET_AN_CTRLr(unit, pc, speed_mg,
   4602                 (MGBASE_AN_CTRL_SPEED_MASK | MGBASE_AN_CTRL_ADV_MASK)) );
   4603     }
   4604 
   4605     /* XFI PMA/PMD Control 1 Reg. (1.0x0000), speed_10G[5:2] speed_sel[13,6] */
   4606     SOC_IF_ERROR_RETURN
   4607         (MODIFY_PHY8481_PMAD_CTRLr(unit, pc,  speed_c45 | speed_c22, 
   4608                         IEEE_CTRLr_SPEED_10G_MASK | PMAD_MII_CTRL_SS_MASK ));
   4609 
   4610     if ( ! PHY_IS_BCM8486X_AND_UP(pc)) {
   4611         /* Only allow forced 100M in case of no loopback and AN off */
   4612         SOC_IF_ERROR_RETURN(_phy_8481_copper_lb_get(unit, port, &lb_enable));
   4613         if(!lb_enable) {
   4614              speed_c22 = PMAD_MII_CTRL_SS_100;
   4615         }
   4616     }
   4617 
   4618     if ( PHY_IS_BCM8483X_AND_UP(pc) ) {
   4619         /* 1000/100BASE-T MII Control Reg. (7.0xFFE0), speed_select[13,6] */
   4620         SOC_IF_ERROR_RETURN
   4621             (MODIFY_PHY8481_MII_CTRLr(unit, pc, speed_c22, PMAD_MII_CTRL_SS_MASK));
   4622     } else {
   4623         /* Sync the speed bits with the GPHY MII CTRL reg. */
   4624         SOC_IF_ERROR_RETURN
   4625             (MODIFY_PHY8481_AN_REG(unit, pc, 0x8000, (1U<<13), (1U << 13)));
   4626     }
   4627     /* coverity[dead_error_condition:FALSE] */
   4628     /* need to set the internal phy's speed accordingly */
   4629     if ( NULL != int_pc ) {
   4630         /* coverity[dead_error_begin] */
   4631         rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed);
   4632     }
   4633     LB_SPEED(pc) = speed;
   4634 
   4635     return rv;
   4636 }
   4637 
   4638 STATIC int
   4639 _phy_8481_xaui_speed_set(int unit, soc_port_t port, int speed)
   4640 {
   4641     phy_ctrl_t *pc;
   4642     uint16      strap1 = 0;
   4643 
   4644     pc = EXT_PHY_SW_STATE(unit, port);
   4645     /* Select 1G Fiber */
   4646     if ( speed == 1000 ) {
   4647         strap1 = (1U << 12);
   4648     }
   4649     PHY_FW_HANDSHAKE(unit, port);
   4650     SOC_IF_ERROR_RETURN
   4651         (MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, strap1, (1U << 12)));
   4652     PHY_FW_HANDSHAKE(unit, port);
   4653 
   4654     return (SOC_E_NONE);
   4655 }
   4656 
   4657 
   4658 STATIC int
   4659 phy_8481_speed_set(int unit, soc_port_t port, int speed)
   4660 {
   4661     phy_ctrl_t *pc;
   4662 
   4663     pc = EXT_PHY_SW_STATE(unit, port);
   4664     
   4665     if ( PHY_COPPER_MODE(unit, port)) {
   4666         SOC_IF_ERROR_RETURN(_phy_8481_copper_speed_set(unit, port, speed));
   4667         pc->copper.force_speed = speed;
   4668     } else {
   4669         PHYDRV_CALL_ARG1(pc,PHY_SPEED_SET,speed);
   4670         SOC_IF_ERROR_RETURN(_phy_8481_xaui_speed_set(unit, port, speed));
   4671         pc->fiber.force_speed = speed;
   4672     }
   4673 
   4674     return SOC_E_NONE;
   4675 }
   4676 
   4677 /*
   4678  * Function:
   4679  *      phy_8481_speed_get
   4680  * Purpose:
   4681  *      Get PHY speed
   4682  * Parameters:
   4683  *      unit - StrataSwitch unit #.
   4684  *      port - StrataSwitch port #.
   4685  *      speed - current link speed in Mbps
   4686  * Returns:
   4687  *      SOC_E_NONE
   4688  */
   4689 STATIC int
   4690 _phy_8481_copper_speed_get(int unit, soc_port_t port, int *speed)
   4691 {
   4692     phy_ctrl_t *pc;
   4693     uint16 ctrl, status, speed_c45;
   4694     int an = 0;
   4695     int an_done = 0;
   4696 
   4697     pc = EXT_PHY_SW_STATE(unit, port);
   4698 
   4699     if ( PHY_IS_BCM8484X_AND_UP(pc) ) {
   4700         /* Core Config Status Register (30.0x400D), Copper_Speed[2,4:3] */
   4701         SOC_IF_ERROR_RETURN(
   4702             READ_PHY84834_CORE_CFG_LINK_STATUSr(unit, pc, &status) );
   4703         
   4704         if (PHY_IS_BCM8484X(pc)) {
   4705             /* Do not include Status Register bit 2 for speed determination
   4706              * on BCM8484X, because bit 2 is priority bit other than speed MSB.*/
   4707             status &= ~CORE_CFG_LINK_STAT_SPEED_MSB;
   4708         }
   4709 
   4710         speed_c45 =  (status & CORE_CFG_LINK_STAT_SPEED_MSB) |
   4711                     ((status & CORE_CFG_LINK_STAT_SPEED_LSB)
   4712                             >> CORE_CFG_LINK_STAT_SPEED_LSB_SHIFT);
   4713     	switch ( speed_c45 ) {
   4714     	case 1 :
   4715             *speed = 100;     break;
   4716     	case 2 :
   4717             *speed = 1000;    break;
   4718     	case 3 :
   4719             *speed = 10000;   break;
   4720     	case 4 :
   4721             *speed = 2500;    break;
   4722     	case 5 :
   4723             *speed = 5000;    break;
   4724     	default:
   4725             *speed = 0;       break;
   4726     	}
   4727         if( *speed != 0) {
   4728             return SOC_E_NONE;
   4729         }
   4730     }
   4731 
   4732     /* legacy way for determining current link-down speed */
   4733     SOC_IF_ERROR_RETURN
   4734         (phy_8481_an_get(unit, port, &an, &an_done));
   4735 
   4736     if ( an ) { /* autoneg is enabled */
   4737         if ( an_done ) {
   4738             SOC_IF_ERROR_RETURN
   4739                 (READ_PHY8481_TENG_AN_CTRLr(unit, pc, &ctrl));
   4740             SOC_IF_ERROR_RETURN
   4741                 (READ_PHY8481_TENG_AN_STATr(unit, pc, &status));
   4742             if ( (ctrl   & TENG_IEEE_AN_CTRL_10GBT   ) &&
   4743                  (status & TENG_IEEE_AN_STAT_LP_10GBT) ) {
   4744                 *speed = 10000;
   4745             } else {
   4746                 /* look at the CL22 regs and determine the gcd */
   4747                 SOC_IF_ERROR_RETURN
   4748                     (_phy8481_auto_negotiate_gcd(unit, port, speed, NULL));
   4749             }
   4750         } else {
   4751             *speed = 0;
   4752             return(SOC_E_NONE);
   4753         }
   4754 
   4755     } else {   /* autoNego is no t enabled, forced speed */
   4756         /* read the MII Ctrl reg. */
   4757 
   4758         SOC_IF_ERROR_RETURN
   4759             (READ_PHY8481_PMAD_CTRLr(unit, pc, &speed_c45));
   4760         switch(MII_CTRL_SS(speed_c45)) {
   4761         case PMAD_MII_CTRL_SS_10:
   4762             *speed = 10;
   4763             break;
   4764         case PMAD_MII_CTRL_SS_100:
   4765             *speed = 100;
   4766             break;
   4767         case PMAD_MII_CTRL_SS_1000:
   4768             *speed = 1000;
   4769             break;
   4770         default:
   4771             if ( (speed_c45 & (IEEE_CTRLr_SPEED_10G_MASK|PMAD_MII_CTRL_SS_MASK))
   4772                             == IEEE_CTRLr_SPEED_10G ) {
   4773                 *speed = 10000;
   4774                 break;
   4775             } else {
   4776                 *speed = 0;
   4777                 return(SOC_E_NONE);
   4778             }
   4779         }
   4780     }
   4781 
   4782     return SOC_E_NONE;
   4783 }
   4784 
   4785 STATIC int
   4786 _phy_8481_xaui_speed_get(int unit, soc_port_t port, int *speed)
   4787 {
   4788     phy_ctrl_t *pc;
   4789     uint16      strap1;
   4790     pc = EXT_PHY_SW_STATE(unit, port);
   4791 
   4792     SOC_IF_ERROR_RETURN
   4793         (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &strap1));
   4794 
   4795     if ( strap1 & (1U << 12)) {
   4796                 *speed = 1000;
   4797     } else {
   4798                 *speed = 10000;
   4799     }
   4800     return (SOC_E_NONE);
   4801 }
   4802 
   4803 STATIC int
   4804 phy_8481_speed_get(int unit, soc_port_t port, int *speed)
   4805 {
   4806     phy_ctrl_t *pc;
   4807 
   4808     pc = EXT_PHY_SW_STATE(unit, port);
   4809 
   4810     if ( PHY_COPPER_MODE(unit, port)) {
   4811         SOC_IF_ERROR_RETURN(_phy_8481_copper_speed_get(unit, port, speed));
   4812     } else {
   4813         if ( NXT_PC(pc)) {
   4814             PHYDRV_CALL_ARG1(pc,PHY_SPEED_GET,speed);
   4815             return SOC_E_NONE;
   4816         }
   4817         SOC_IF_ERROR_RETURN(_phy_8481_xaui_speed_get(unit, port, speed));
   4818     }
   4819 
   4820     return SOC_E_NONE;
   4821 }
   4822 
   4823 STATIC int
   4824 _phy_8481_copper_duplex_set(int unit, soc_port_t port, int duplex)
   4825 {
   4826     uint16      mii_ctrl;
   4827     phy_ctrl_t  *pc;
   4828 
   4829     pc = EXT_PHY_SW_STATE(unit, port);
   4830 
   4831     SOC_IF_ERROR_RETURN
   4832         (READ_PHY8481_MII_CTRLr(unit, pc, &mii_ctrl));
   4833 
   4834     if ( duplex) {
   4835         mii_ctrl |= MII_CTRL_FD;
   4836     } else {
   4837         mii_ctrl &= ~MII_CTRL_FD;
   4838     }
   4839 
   4840     SOC_IF_ERROR_RETURN
   4841         (WRITE_PHY8481_MII_CTRLr(unit, pc, mii_ctrl));
   4842 
   4843     pc->copper.force_duplex = duplex;
   4844 
   4845     return(SOC_E_NONE);
   4846 }
   4847 
   4848 STATIC int
   4849 _phy_8481_xaui_duplex_set(int unit, soc_port_t port, int duplex)
   4850 {
   4851     uint16      mii_ctrl;
   4852     phy_ctrl_t  *pc;
   4853 
   4854     pc = EXT_PHY_SW_STATE(unit, port);
   4855 
   4856     SOC_IF_ERROR_RETURN
   4857         (READ_PHY8481_PHYXS_L_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl));
   4858 
   4859     if ( duplex) {
   4860         mii_ctrl |= MII_CTRL_FD;
   4861     } else {
   4862         mii_ctrl &= ~MII_CTRL_FD;
   4863     }
   4864 
   4865     SOC_IF_ERROR_RETURN
   4866         (WRITE_PHY8481_PHYXS_L_COMBO_IEEE0_MIICNTLr(unit, pc, mii_ctrl));
   4867 
   4868     pc->fiber.force_duplex = duplex;
   4869 
   4870     return SOC_E_NONE;
   4871 }
   4872 
   4873 STATIC int
   4874 phy_8481_duplex_set(int unit, soc_port_t port, int duplex)
   4875 {
   4876     phy_ctrl_t  *pc;
   4877 
   4878     pc = EXT_PHY_SW_STATE(unit, port);
   4879 
   4880     if ( PHY_COPPER_MODE(unit, port)) {
   4881         SOC_IF_ERROR_RETURN(_phy_8481_copper_duplex_set(unit, port, duplex));
   4882     } else {
   4883         PHYDRV_CALL_ARG1(pc,PHY_DUPLEX_SET,duplex);
   4884         SOC_IF_ERROR_RETURN(_phy_8481_xaui_duplex_set(unit, port, duplex));
   4885     }
   4886 
   4887     return SOC_E_NONE;
   4888 }
   4889 
   4890 
   4891 STATIC int
   4892 _phy_8481_copper_duplex_get(int unit, soc_port_t port, int *duplex)
   4893 {
   4894     int         rv, speed, lbmode;
   4895     uint16      mii_ctrl;
   4896     phy_ctrl_t  *pc;
   4897 
   4898     pc = EXT_PHY_SW_STATE(unit, port);
   4899 
   4900     /* check if it's under PHY loopback mode ? */
   4901     SOC_IF_ERROR_RETURN(_phy_8481_copper_lb_get(unit, port, &lbmode));
   4902     /* if under loopback & lb_speed is set, use the intended loopback speed */
   4903     if ( (! lbmode) || (0 == (speed = LB_SPEED(pc))) ) {  /* 0 means LB_SPEED not set */
   4904         /* not loopback mode or don't know the intended speed for loopback, *\
   4905         \* call _phy_8481_copper_speed_get() to get the current speed       */
   4906         SOC_IF_ERROR_RETURN(_phy_8481_copper_speed_get(unit, port, &speed));
   4907     }
   4908 
   4909     if ( ( speed == 10000 ) || ( speed == 0 ) ||
   4910          ( speed == 5000  ) || ( speed == 2500 ) ) {
   4911         *duplex =  TRUE;
   4912         return SOC_E_NONE;
   4913     }
   4914 
   4915     SOC_IF_ERROR_RETURN
   4916         (READ_PHY8481_MII_CTRLr(unit, pc, &mii_ctrl));
   4917 
   4918     rv = SOC_E_NONE;
   4919     if ( mii_ctrl & MII_CTRL_AE) {     /* Auto-negotiation enabled */
   4920         if ( !(pc->mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */
   4921             *duplex = FALSE;
   4922         } else {
   4923             rv = _phy8481_auto_negotiate_gcd(unit, port, NULL, duplex);
   4924         }
   4925     } else {                /* Auto-negotiation disabled */
   4926         *duplex = (mii_ctrl & MII_CTRL_FD) ? TRUE : FALSE;
   4927     }
   4928 
   4929     return(rv);
   4930 }
   4931 
   4932 STATIC int
   4933 _phy_8481_xaui_duplex_get(int unit, soc_port_t port, int *duplex)
   4934 {
   4935     uint16       reg0_16;
   4936     uint16       mii_ctrl;
   4937     phy_ctrl_t  *pc;
   4938 
   4939     pc = EXT_PHY_SW_STATE(unit, port);
   4940 
   4941     *duplex = TRUE;
   4942 
   4943     SOC_IF_ERROR_RETURN
   4944         (READ_PHY8481_PHYXS_L_GP_STATUS_STATUS1000X1r(unit, pc, &reg0_16));
   4945 
   4946     if ( reg0_16 & GP_STATUS_STATUS1000X1_SGMII_MODE_MASK) {
   4947 
   4948     /* retrieve the duplex setting in SGMII mode */
   4949         SOC_IF_ERROR_RETURN
   4950             (READ_PHY8481_PHYXS_L_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl));
   4951 
   4952         if ( mii_ctrl & MII_CTRL_AE) {
   4953             SOC_IF_ERROR_RETURN
   4954                 (READ_PHY8481_PHYXS_L_COMBO_IEEE0_AUTONEGLPABILr(unit,pc,&reg0_16));
   4955 
   4956             /* make sure link partner is also in SGMII mode
   4957              * otherwise fall through to use the FD bit in MII_CTRL reg
   4958              */
   4959             if ( reg0_16 & MII_ANP_SGMII_MODE) {
   4960                 if ( reg0_16 & MII_ANP_SGMII_FD) {
   4961                     *duplex = TRUE;
   4962                 } else {
   4963                     *duplex = FALSE;
   4964                 }
   4965 
   4966                 return SOC_E_NONE;
   4967             }
   4968         }
   4969         *duplex = (mii_ctrl & MII_CTRL_FD) ? TRUE : FALSE;
   4970     }
   4971 
   4972     return SOC_E_NONE;
   4973 }
   4974 
   4975 STATIC int
   4976 phy_8481_duplex_get(int unit, soc_port_t port, int *duplex)
   4977 {
   4978     phy_ctrl_t  *pc;
   4979     int          tmp = 0;
   4980 
   4981     pc = EXT_PHY_SW_STATE(unit, port);
   4982 
   4983     if ( PHY_COPPER_MODE(unit, port)) {
   4984         SOC_IF_ERROR_RETURN(_phy_8481_copper_duplex_get(unit, port, duplex));
   4985     } else {
   4986         SOC_IF_ERROR_RETURN(_phy_8481_xaui_duplex_get(unit, port, duplex));
   4987         if ( NXT_PC(pc)) {
   4988             tmp = *duplex;
   4989             PHYDRV_CALL_ARG1(pc,PHY_DUPLEX_GET,duplex);
   4990             *duplex = (tmp == TRUE && *duplex == TRUE) ? TRUE : FALSE;
   4991         }
   4992     }
   4993 
   4994     return SOC_E_NONE;
   4995 }
   4996 
   4997 /*
   4998  * Function:
   4999  *      phy_8481_an_get
   5000  * Purpose:
   5001  *      Get the current auto-negotiation status (enabled/busy)
   5002  * Parameters:
   5003  *      unit - StrataSwitch unit #.
   5004  *      port - StrataSwitch port #.
   5005  *      an   - (OUT) if true, auto-negotiation is enabled.
   5006  *      an_done - (OUT) if true, auto-negotiation is complete. This
   5007  *              value is undefined if an == false.
   5008  * Returns:
   5009  *      SOC_E_XXX
   5010  */
   5011 STATIC int
   5012 _phy_8481_copper_an_get(int unit, soc_port_t port, int *an, int *an_done)
   5013 {
   5014     phy_ctrl_t *pc;
   5015     uint16 mii_ctrl;
   5016 
   5017     pc = EXT_PHY_SW_STATE(unit, port);
   5018 
   5019     SOC_IF_ERROR_RETURN
   5020         (READ_PHY8481_MII_STATr(unit, pc, &pc->mii_stat));
   5021 
   5022     SOC_IF_ERROR_RETURN
   5023         (READ_PHY8481_MII_CTRLr(unit, pc, &mii_ctrl));
   5024 
   5025     /* Looking at the MII regs would suffice */
   5026     *an = (mii_ctrl & MII_CTRL_AE) ? TRUE : FALSE;
   5027 
   5028     if (NULL != an_done) {
   5029         *an_done = (pc->mii_stat & MII_STAT_AN_DONE) ? TRUE : FALSE;
   5030     }
   5031 
   5032     return SOC_E_NONE;
   5033 }
   5034 
   5035 STATIC int
   5036 _phy_8481_xaui_an_get(int unit, soc_port_t port, int *an, int *an_done)
   5037 {
   5038     COMPILER_REFERENCE(unit);
   5039     COMPILER_REFERENCE(port);
   5040 
   5041     *an      = FALSE;
   5042     if (NULL != an_done) {
   5043         *an_done = FALSE;
   5044     }
   5045 
   5046     return (SOC_E_NONE);
   5047 }
   5048 
   5049 STATIC int
   5050 phy_8481_an_get(int unit, soc_port_t port, int *an, int *an_done)
   5051 {
   5052     phy_ctrl_t *pc;
   5053 
   5054     pc = EXT_PHY_SW_STATE(unit, port);
   5055 
   5056     if (PHY_COPPER_MODE(unit, port)) {
   5057         SOC_IF_ERROR_RETURN(_phy_8481_copper_an_get(unit, port, an, an_done));
   5058     } else {
   5059         if (NXT_PC(pc)) {
   5060             PHYDRV_CALL_ARG2(pc,PHY_AUTO_NEGOTIATE_GET,an,an_done);
   5061             return SOC_E_NONE;
   5062         }
   5063 
   5064         SOC_IF_ERROR_RETURN(_phy_8481_xaui_an_get(unit, port, an, an_done));
   5065     }
   5066 
   5067     return SOC_E_NONE;
   5068 }
   5069 
   5070 /*
   5071  * Function:
   5072  *      phy_8481_an_set
   5073  * Purpose:
   5074  *      Enable or disabled auto-negotiation on the specified port.
   5075  * Parameters:
   5076  *      unit - StrataSwitch unit #.
   5077  *      port - StrataSwitch port #.
   5078  *      an   - Boolean, if true, auto-negotiation is enabled
   5079  *              (and/or restarted). If false, autonegotiation is disabled.
   5080  * Returns:
   5081  *      SOC_E_XXX
   5082  */
   5083 STATIC int
   5084 _phy_8481_copper_an_set(int unit, soc_port_t port, int an)
   5085 {
   5086     phy_ctrl_t  *pc;
   5087     int pan = 0;
   5088     int pan_done = 0;
   5089 
   5090     SOC_IF_ERROR_RETURN
   5091         (phy_8481_an_get(unit, port, &pan, &pan_done));
   5092 
   5093     pc = EXT_PHY_SW_STATE(unit, port);
   5094 
   5095     if (pan != 0 && an == 0) {
   5096         /* Workaround to avoid  1000BASET force mode which is causing    *\
   5097         \* the PHY to misbehave  (0x2100 puts PHY in 100BT force mode )  */
   5098         SOC_IF_ERROR_RETURN
   5099             (WRITE_PHY8481_MII_CTRLr(unit, pc, 0x2100));
   5100     }
   5101 
   5102     /* 1000T/100TX MII Control Reg.(7.0xFFE0), AN_Enable[12] Restart_AN[9] */
   5103     SOC_IF_ERROR_RETURN(
   5104         MODIFY_PHY8481_MII_CTRLr(unit, pc,
   5105                                  (an ? (MII_CTRL_AE | MII_CTRL_RAN) : 0),
   5106                                         MII_CTRL_AE | MII_CTRL_RAN) );
   5107     /* 10GBASE-T AutoNeg Control Reg.(7.0x0000), AN_Enable[12] Restart_AN[9] */
   5108     SOC_IF_ERROR_RETURN(
   5109         MODIFY_PHY8481_AN_CTRLr( unit, pc, 
   5110                                  (an ? (AN_IEEE_CTRL_REG_AN_ENA_RESTART) : 0),
   5111                                         AN_IEEE_CTRL_REG_AN_ENA_RESTART) );
   5112     pc->copper.autoneg_enable = an;
   5113     return SOC_E_NONE;
   5114 }
   5115 
   5116 STATIC int
   5117 _phy_8481_xaui_an_set(int unit, soc_port_t port, int an)
   5118 {
   5119     COMPILER_REFERENCE(unit);
   5120     COMPILER_REFERENCE(port);
   5121     COMPILER_REFERENCE(an);
   5122 
   5123     return SOC_E_NONE;
   5124 }
   5125 
   5126 STATIC int
   5127 phy_8481_an_set(int unit, soc_port_t port, int an)
   5128 {
   5129     phy_ctrl_t  *pc, *int_pc;
   5130 
   5131     pc = EXT_PHY_SW_STATE(unit, port);
   5132     int_pc = INT_PHY_SW_STATE(unit, port);
   5133 
   5134     if ( PHY_COPPER_MODE(unit, port) ) {
   5135         SOC_IF_ERROR_RETURN(_phy_8481_copper_an_set(unit, port, an));
   5136     #if 1
   5137         if ( SYS_FORCED_CL72(pc) )  {
   5138             SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an));
   5139         }
   5140     #endif
   5141     } else {
   5142         if ( NXT_PC(pc) ) {
   5143             PHYDRV_CALL_ARG1(pc,PHY_AUTO_NEGOTIATE_SET,an);
   5144             SOC_IF_ERROR_RETURN(_phy_8481_xaui_an_set(unit, port, FALSE));
   5145             return SOC_E_NONE;
   5146         }
   5147         SOC_IF_ERROR_RETURN(_phy_8481_xaui_an_set(unit, port, an));
   5148     }
   5149 
   5150     return SOC_E_NONE;
   5151 }
   5152 
   5153 
   5154 /*
   5155  * Function:
   5156  *      phy_8481_ability_advert_get
   5157  * Purpose:
   5158  *      Get the current advertisement for auto-negotiation.
   5159  * Parameters:
   5160  *      unit - StrataSwitch unit #.
   5161  *      port - StrataSwitch port #.
   5162  *      ability - (OUT) Port ability masks indicating supported options/speeds.
   5163  * Returns:
   5164  *      SOC_E_XXX
   5165  * Notes:
   5166  *      The advertisement is retrieved for the ACTIVE medium.
   5167  *      No synchronization performed at this level.
   5168  */
   5169 STATIC int
   5170 _phy_8481_copper_ability_advert_get(int unit, soc_port_t port,
   5171                                     soc_port_ability_t *ability)
   5172 {
   5173     phy_ctrl_t  *pc;
   5174     uint16       data16;
   5175     int          rv;
   5176 
   5177     pc = EXT_PHY_SW_STATE(unit, port);
   5178     rv = SOC_E_NONE;
   5179 
   5180     sal_memset(ability, 0, sizeof(*ability));
   5181 
   5182     /* Copper AutoNeg Advertisement Reg.(7.0xFFE4) */
   5183     SOC_IF_ERROR_RETURN
   5184         (READ_PHY8481_MII_ANAr(unit, pc, &data16));
   5185     if ( data16 & MII_ANA_HD_100 ) { 
   5186         ability->speed_half_duplex |= SOC_PA_SPEED_100MB;
   5187     }
   5188     if ( data16 & MII_ANA_FD_100 ) {
   5189         ability->speed_full_duplex |= SOC_PA_SPEED_100MB;
   5190     }
   5191 
   5192     if ( ! PHY_IS_BCM8483X_AND_UP(pc) ) {   /* only 8481/8482x support 10M */
   5193         if ( data16 & MII_ANA_HD_10 ) { 
   5194             ability->speed_half_duplex |= SOC_PA_SPEED_10MB;
   5195         }
   5196         if ( data16 & MII_ANA_FD_10 ) {
   5197             ability->speed_full_duplex |= SOC_PA_SPEED_10MB;
   5198         }
   5199     }
   5200 
   5201     switch ( data16 & (MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE) ) {
   5202     case MII_ANA_PAUSE:
   5203         ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   5204         break;
   5205     case MII_ANA_ASYM_PAUSE:
   5206         ability->pause = SOC_PA_PAUSE_TX;
   5207         break;
   5208     case MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE:
   5209         ability->pause = SOC_PA_PAUSE_RX;
   5210         break;
   5211     }
   5212 
   5213     /* 1000BASE-T Control Reg.(7.0xFFE9) */
   5214     SOC_IF_ERROR_RETURN
   5215         (READ_PHY8481_MII_GB_CTRLr(unit, pc, &data16));
   5216     /* GE Specific values */
   5217     if ( data16 & MII_GB_CTRL_ADV_1000HD ) {
   5218        ability->speed_half_duplex |= SOC_PA_SPEED_1000MB;
   5219     }
   5220     if ( data16 & MII_GB_CTRL_ADV_1000FD ) {
   5221        ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   5222     }
   5223 
   5224     /* 10GBASE-T AN Control Reg.(7.0x0020) */
   5225     SOC_IF_ERROR_RETURN
   5226         (READ_PHY8481_TENG_AN_CTRLr(unit, pc, &data16));
   5227     /* 10G Specific values */
   5228     if ( data16 & TENG_IEEE_AN_CTRL_10GBT ) {
   5229        ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   5230     }
   5231 
   5232     if (PHY_IS_BCM8486X_AND_UP(pc)) {
   5233         if ( PHY_IS_BCM8488X(pc) ) {
   5234             /* check bit[8:7] of 10GBASE-T AN Control Reg.(7.0x0020) *\
   5235             \* for 5GBASE-T / 2.5GBASE-T support                     */
   5236             if ( data16 & TENG_IEEE_AN_CTRL_2p5GBT ) {
   5237                 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB;
   5238             }
   5239             if ( data16 & TENG_IEEE_AN_CTRL_5GBT   ) {
   5240                 ability->speed_full_duplex |= SOC_PA_SPEED_5000MB;
   5241             }
   5242         }/* if PHY_IS_BCM8488X */
   5243 
   5244         /* Broadcom MGBASE-T  5G / 2.5G Specific values                        *\
   5245         \* MGBASE-T AN Control Reg.(30.0x0000), Advert_5G/2.5G_capability[2:1] */
   5246         SOC_IF_ERROR_RETURN(
   5247             READ_PHY8481_MGBASET_AN_CTRLr(unit, pc, &data16) );
   5248         if ( data16 & MGBASE_AN_CTRL_ADV_2P5G ) {
   5249             ability->speed_full_duplex |= SOC_PA_SPEED_2500MB;
   5250         }
   5251         if ( data16 & MGBASE_AN_CTRL_ADV_5G ) {
   5252             ability->speed_full_duplex |= SOC_PA_SPEED_5000MB;
   5253         }
   5254     }/* if PHY_IS_BCM8486X_AND_UP */
   5255 
   5256     /* EEE settings */
   5257     if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   5258         SOC_IF_ERROR_RETURN
   5259             (READ_PHY8481_EEE_ADVr(unit, pc, &data16));
   5260         if ( data16 & 0x08 ) {
   5261             ability->eee |= SOC_PA_EEE_10GB_BASET;
   5262         }
   5263         if ( data16 & 0x04 ) {
   5264             ability->eee |= SOC_PA_EEE_1GB_BASET;
   5265         }
   5266         if ( data16 & 0x02 ) {
   5267             ability->eee |= SOC_PA_EEE_100MB_BASETX;
   5268         }
   5269     }
   5270 
   5271     return rv;
   5272 }
   5273 
   5274 STATIC int
   5275 _phy_8481_xaui_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   5276 {
   5277     phy_ctrl_t  *pc;
   5278     uint16      an_adv;
   5279     uint16      adv_over1g;
   5280 
   5281     pc = EXT_PHY_SW_STATE(unit, port);
   5282 
   5283     sal_memset(ability, 0, sizeof(*ability));
   5284 
   5285     SOC_IF_ERROR_RETURN
   5286         (READ_PHY8481_PHYXS_L_COMBO_IEEE0_AUTONEGADVr(unit, pc, &an_adv));
   5287 
   5288     switch (an_adv & (MII_ANP_C37_ASYM_PAUSE | MII_ANP_C37_PAUSE)) {
   5289     case MII_ANP_C37_ASYM_PAUSE:
   5290         ability->pause |= SOC_PA_PAUSE_TX;
   5291         break;
   5292     case (MII_ANP_C37_ASYM_PAUSE | MII_ANP_C37_PAUSE):
   5293         ability->pause |= SOC_PA_PAUSE_RX;
   5294         break;
   5295     case MII_ANP_C37_PAUSE:
   5296         ability->pause |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   5297         break;
   5298     }
   5299 
   5300     ability->speed_full_duplex |= (an_adv & MII_ANP_C37_FD) ? SOC_PA_SPEED_1000MB : 0;
   5301 
   5302     SOC_IF_ERROR_RETURN
   5303         (READ_PHY8481_PHYXS_L_OVER1G_UP1r(unit, pc, &adv_over1g));
   5304     ability->speed_full_duplex |= (adv_over1g & OVER1G_UP1_DATARATE_10GCX4_MASK) ?
   5305                                   SOC_PA_SPEED_10GB : 0;
   5306 
   5307     return SOC_E_NONE;
   5308 }
   5309 
   5310 STATIC int
   5311 phy_8481_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   5312 {
   5313     phy_ctrl_t      *pc;
   5314 
   5315     pc = EXT_PHY_SW_STATE(unit, port);
   5316 
   5317     if (NULL == ability) {
   5318         return (SOC_E_PARAM);
   5319     }
   5320 
   5321     if (PHY_COPPER_MODE(unit, port)) {
   5322         SOC_IF_ERROR_RETURN(_phy_8481_copper_ability_advert_get(unit, port, ability));
   5323     } else {
   5324         if (NXT_PC(pc)) {
   5325             PHYDRV_CALL_ARG1(pc,PHY_ABILITY_ADVERT_GET,ability);
   5326             return SOC_E_NONE;
   5327         }
   5328         SOC_IF_ERROR_RETURN(_phy_8481_xaui_ability_advert_get(unit, port, ability));
   5329     }
   5330 
   5331     return SOC_E_NONE;
   5332 }
   5333 
   5334 
   5335 /*
   5336  * Function:
   5337  *      phy_8481_ability_advert_set
   5338  * Purpose:
   5339  *      Set the current advertisement for auto-negotiation.
   5340  * Parameters:
   5341  *      unit - StrataSwitch unit #.
   5342  *      port - StrataSwitch port #.
   5343  *      ability - Port ability masks indicating supported options/speeds.
   5344  * Returns:
   5345  *      SOC_E_XXX
   5346  * Notes:
   5347  *      The advertisement is set only for the ACTIVE medium.
   5348  *      No synchronization performed at this level.
   5349  */
   5350 
   5351 
   5352 STATIC int
   5353 _phy_8481_copper_ability_advert_set(int unit, soc_port_t port,
   5354                                     soc_port_ability_t *ability)
   5355 {
   5356     phy_ctrl_t  *pc;
   5357     uint16       mii_adv, mii_gb_ctrl, mask;
   5358     int          rv;
   5359 
   5360     pc = EXT_PHY_SW_STATE(unit, port);
   5361     rv = SOC_E_NONE;
   5362 
   5363     mii_adv     = MII_ANA_ASF_802_3;
   5364     
   5365     SOC_IF_ERROR_RETURN
   5366         (READ_PHY8481_MII_GB_CTRLr(unit, pc,  &mii_gb_ctrl));
   5367 
   5368     mii_gb_ctrl &= ~(MII_GB_CTRL_ADV_1000HD | MII_GB_CTRL_ADV_1000FD);
   5369     if ( PHY_IS_BCM8484X(pc) ) {
   5370         mii_gb_ctrl &= ~MII_GB_CTRL_PT;  /* DTE device (JIRA PHY-1772) */
   5371     } else {
   5372         mii_gb_ctrl |=  MII_GB_CTRL_PT;  /* repeater / switch port */
   5373     }
   5374 
   5375     if ( ! PHY_IS_BCM8483X_AND_UP(pc) ) {   /* only 8481/8482x support 10M */
   5376         if ( ability->speed_half_duplex & SOC_PA_SPEED_10MB ) {
   5377             mii_adv |= MII_ANA_HD_10;
   5378             LB_SPEED(pc) = 10;
   5379         }
   5380         if ( ability->speed_full_duplex & SOC_PA_SPEED_10MB  ) {
   5381             mii_adv |= MII_ANA_FD_10;
   5382             LB_SPEED(pc) = 10;
   5383         }
   5384     }
   5385 
   5386     if ( ability->speed_half_duplex & SOC_PA_SPEED_100MB  ) {
   5387         mii_adv |= MII_ANA_HD_100;
   5388         LB_SPEED(pc) = 100;
   5389     }
   5390     if ( ability->speed_full_duplex & SOC_PA_SPEED_100MB  ) {
   5391         mii_adv |= MII_ANA_FD_100;
   5392         LB_SPEED(pc) = 100;
   5393     }
   5394     if ( ability->speed_half_duplex & SOC_PA_SPEED_1000MB ) {
   5395         mii_gb_ctrl |= MII_GB_CTRL_ADV_1000HD;
   5396         LB_SPEED(pc) = 1000;
   5397     }
   5398     if ( ability->speed_full_duplex & SOC_PA_SPEED_1000MB ) {
   5399         mii_gb_ctrl |= MII_GB_CTRL_ADV_1000FD;
   5400         LB_SPEED(pc) = 1000;
   5401     }
   5402     if ( (ability->speed_half_duplex & SOC_PA_SPEED_2500MB) ||
   5403          (ability->speed_full_duplex & SOC_PA_SPEED_2500MB) ) {
   5404         LB_SPEED(pc) = 2500;
   5405     }
   5406     if ( (ability->speed_half_duplex & SOC_PA_SPEED_5000MB) ||
   5407          (ability->speed_full_duplex & SOC_PA_SPEED_5000MB) ) {
   5408         LB_SPEED(pc) = 5000;
   5409     }
   5410     if ( (ability->speed_half_duplex & SOC_PA_SPEED_10GB) ||
   5411          (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ) {
   5412         LB_SPEED(pc) = 10000;
   5413     }
   5414 
   5415     if ( (ability->speed_half_duplex & SOC_PA_SPEED_10MB) ||
   5416          (ability->speed_full_duplex & SOC_PA_SPEED_10MB) ) {
   5417         if ( ! PHY_IS_BCM8483X_AND_UP(pc) ) {  /* only 8481/8482x support 10M */
   5418             LB_SPEED(pc) = 10;
   5419         }
   5420     }
   5421 
   5422     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   5423     case SOC_PA_PAUSE_TX:
   5424         mii_adv |= MII_ANA_ASYM_PAUSE;
   5425         break;
   5426     case SOC_PA_PAUSE_RX:
   5427         mii_adv |= MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE;
   5428         break;
   5429     case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   5430         mii_adv |= MII_ANA_PAUSE;
   5431         break;
   5432     }
   5433 
   5434     mask = MII_ANA_PAUSE  | MII_ANA_ASYM_PAUSE |
   5435            MII_ANA_FD_100 | MII_ANA_HD_100     | MII_ANA_ASF_802_3;
   5436     if ( ! PHY_IS_BCM8483X_AND_UP(pc) ) {   /* only 8481/8482x support 10M */
   5437         mask |=  (MII_ANA_FD_10 | MII_ANA_HD_10);
   5438     }
   5439     SOC_IF_ERROR_RETURN
   5440         (MODIFY_PHY8481_MII_ANAr(unit, pc, mii_adv, mask));
   5441 
   5442     SOC_IF_ERROR_RETURN
   5443         (MODIFY_PHY8481_MII_GB_CTRLr(unit, pc, mii_gb_ctrl, 
   5444              MII_GB_CTRL_PT | MII_GB_CTRL_ADV_1000FD | MII_GB_CTRL_ADV_1000HD));
   5445 
   5446     if ( PHY_IS_BCM8486X_AND_UP(pc) ) {
   5447         /* 5G / 2.5G Specific values */
   5448         mii_gb_ctrl  = (ability->speed_full_duplex & SOC_PA_SPEED_5000MB)
   5449                      ? (MGBASE_AN_CTRL_ADV_5G   | MGBASE_AN_CTRL_MG_ENABLE) : 0;
   5450         mii_gb_ctrl |= (ability->speed_full_duplex & SOC_PA_SPEED_2500MB)
   5451                      ? (MGBASE_AN_CTRL_ADV_2P5G | MGBASE_AN_CTRL_MG_ENABLE) : 0;
   5452         /* MGBASE-T AN Control Reg.(30.0x0000), Advert_5G/2.5G_capability[2:1] */
   5453         SOC_IF_ERROR_RETURN(
   5454             MODIFY_PHY8481_MGBASET_AN_CTRLr(unit, pc, mii_gb_ctrl,
   5455                                                       MGBASE_AN_CTRL_ADV_MASK) );
   5456     }
   5457 
   5458     /* 10G Specific values            ( 7.0x0020 bit[12] )  */
   5459     mii_gb_ctrl      = (ability->speed_full_duplex & SOC_PA_SPEED_10GB)
   5460                      ? TENG_IEEE_AN_CTRL_10GBT  : 0;
   5461     if ( PHY_IS_BCM8488X(pc) ) {
   5462         /* 5G / 2.5G Specific values  ( 7.0x0020 bit[8:7] ) */
   5463         mii_gb_ctrl |= (ability->speed_full_duplex & SOC_PA_SPEED_5000MB)
   5464                      ? TENG_IEEE_AN_CTRL_5GBT   : 0;
   5465         mii_gb_ctrl |= (ability->speed_full_duplex & SOC_PA_SPEED_2500MB)
   5466                      ? TENG_IEEE_AN_CTRL_2p5GBT : 0;
   5467     }
   5468     /* 10GBASE-T AN Control Reg.(7.0x0020), Advert_10G/5G/2.5G_capability */
   5469     SOC_IF_ERROR_RETURN(
   5470         MODIFY_PHY8481_TENG_AN_CTRLr(unit, pc, mii_gb_ctrl,
   5471                                      TENG_IEEE_AN_CTRL_10GBT |
   5472                                      TENG_IEEE_AN_CTRL_5GBT  |
   5473                                      TENG_IEEE_AN_CTRL_2p5GBT) );
   5474 
   5475     /* EEE settings */
   5476     if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   5477         uint16 eee_ability = 0;
   5478         if (ability->eee & SOC_PA_EEE_10GB_BASET) {
   5479             eee_ability |= 0x8;
   5480         }
   5481         if (ability->eee & SOC_PA_EEE_1GB_BASET) {
   5482             eee_ability |= 0x4;
   5483         }
   5484         if (ability->eee & SOC_PA_EEE_100MB_BASETX) {
   5485             eee_ability |= 0x2;
   5486         }
   5487         SOC_IF_ERROR_RETURN
   5488             (MODIFY_PHY8481_EEE_ADVr(unit, pc, eee_ability, 0xe));
   5489     }
   5490 
   5491     return rv;
   5492 }
   5493 
   5494 STATIC int
   5495 _phy_8481_xaui_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability)
   5496 {
   5497     phy_ctrl_t  *pc;
   5498     uint16      an_adv;
   5499 
   5500     pc = EXT_PHY_SW_STATE(unit, port);
   5501 
   5502     /* Support only full duplex */
   5503     an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? MII_ANP_C37_FD : 0;
   5504     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   5505     case SOC_PA_PAUSE_TX:
   5506         an_adv |= MII_ANP_C37_ASYM_PAUSE;
   5507         break;
   5508     case SOC_PA_PAUSE_RX:
   5509         an_adv |= MII_ANP_C37_ASYM_PAUSE | MII_ANP_C37_PAUSE;
   5510         break;
   5511     case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   5512         an_adv |= MII_ANP_C37_PAUSE;
   5513         break;
   5514     }
   5515     SOC_IF_ERROR_RETURN
   5516         (WRITE_PHY8481_PHYXS_L_COMBO_IEEE0_AUTONEGADVr(unit, pc, an_adv));
   5517 
   5518     if (ability->speed_full_duplex & SOC_PA_SPEED_10GB) {
   5519         SOC_IF_ERROR_RETURN
   5520             (WRITE_PHY8481_PHYXS_L_OVER1G_UP1r(unit, pc, OVER1G_UP1_DATARATE_10GCX4_MASK));
   5521     } else {
   5522         SOC_IF_ERROR_RETURN
   5523             (WRITE_PHY8481_PHYXS_L_OVER1G_UP1r(unit, pc, 0));
   5524     }
   5525 
   5526     return SOC_E_NONE;
   5527 }
   5528 
   5529 
   5530 STATIC int
   5531 phy_8481_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability)
   5532 {
   5533     phy_ctrl_t *pc;
   5534 
   5535     pc = EXT_PHY_SW_STATE(unit, port);
   5536 
   5537     if (NULL == ability) {
   5538         return (SOC_E_PARAM);
   5539     }
   5540 
   5541     if (PHY_COPPER_MODE(unit, port)) {
   5542         SOC_IF_ERROR_RETURN(_phy_8481_copper_ability_advert_set(unit, port, ability));
   5543         pc->copper.advert_ability = *ability;
   5544     } else {
   5545         pc->fiber.advert_ability = *ability;
   5546         if (NXT_PC(pc)) {
   5547             PHYDRV_CALL_ARG1(pc,PHY_ABILITY_ADVERT_SET,ability);
   5548             return SOC_E_NONE;
   5549         }
   5550         SOC_IF_ERROR_RETURN(_phy_8481_xaui_ability_advert_set(unit, port, ability));
   5551     }
   5552 
   5553     return SOC_E_NONE;
   5554 }
   5555 
   5556 STATIC int
   5557 _phy_8481_xaui_nxt_dev_probe(int unit, soc_port_t port)
   5558 {
   5559     phy_ctrl_t  *pc;
   5560     phy_ctrl_t phy_ctrl;
   5561     soc_phy_info_t phy_info;
   5562     extern int _ext_phy_probe(int unit, soc_port_t port,soc_phy_info_t *pi, 
   5563                               phy_ctrl_t *ext_pc);
   5564 
   5565     pc = EXT_PHY_SW_STATE(unit, port);
   5566 
   5567     /* initialize the phy_ctrl for the next device connected to the xaui port */
   5568     sal_memset(&phy_ctrl, 0, sizeof(phy_ctrl_t));
   5569     phy_ctrl.unit = unit;
   5570     phy_ctrl.port = port;
   5571     phy_ctrl.speed_max = pc->speed_max;
   5572     phy_ctrl.read = pc->read;    /* use same MDIO read routine as this device's */
   5573     phy_ctrl.write = pc->write;  /* use same MDIO write routine as this device's */ 
   5574 
   5575     /* coverity[overrun-call] */
   5576     /* get the mdio address of the next device */
   5577     phy_ctrl.phy_id = soc_property_port_get(unit, port,
   5578                                      spn_PORT_PHY_ADDR1, 
   5579                         port < sizeof(ext_phy_dft_addr1)/sizeof(ext_phy_dft_addr1[0])?
   5580                         ext_phy_dft_addr1[port]:0);
   5581 
   5582     /* probe the next device at the given address */
   5583     SOC_IF_ERROR_RETURN
   5584         (_ext_phy_probe(unit, port, &phy_info, &phy_ctrl));
   5585 
   5586     if ((phy_ctrl.pd == NULL) || ((phy_ctrl.phy_model == pc->phy_model) &&
   5587                                   (phy_ctrl.phy_oui == pc->phy_oui))) {
   5588         pc->driver_data = NULL;
   5589         /* device not found */
   5590         return SOC_E_NONE;
   5591     }
   5592     LOG_INFO(BSL_LS_SOC_PHY,
   5593              (BSL_META_U(unit,
   5594                          "_phy_8481_xaui_nxt_dev_probe: found phy device"
   5595                          " u=%d p=%d id0=0x%x id1=0x%x\n"), 
   5596               unit, port,phy_ctrl.phy_id0,phy_ctrl.phy_id1));
   5597     /* set the chained flag */
   5598     PHY_FLAGS_SET(phy_ctrl.unit, phy_ctrl.port, PHY_FLAGS_CHAINED);
   5599 
   5600     /* Found device, allocate control structure */
   5601     pc->driver_data = (void *)sal_alloc ((sizeof (phy_ctrl_t) + phy_ctrl.size), phy_ctrl.pd->drv_name);
   5602     if (pc->driver_data == NULL) {
   5603         return SOC_E_MEMORY;
   5604     }
   5605     sal_memcpy(pc->driver_data, &phy_ctrl, sizeof(phy_ctrl_t));
   5606     return SOC_E_NONE;
   5607 }
   5608 
   5609 /*
   5610  * Function:
   5611  *      phy_8481_ability_remote_get
   5612  * Purpose:
   5613  *      Get the current remoteisement for auto-negotiation.
   5614  * Parameters:
   5615  *      unit - StrataSwitch unit #.
   5616  *      port - StrataSwitch port #.
   5617  *      ability - (OUT) Port ability masks indicating supported options/speeds.
   5618  * Returns:
   5619  *      SOC_E_XXX
   5620  * Notes:
   5621  *      The remoteisement is retrieved for the ACTIVE medium.
   5622  *      No synchronization performed at this level.
   5623  */
   5624 
   5625 STATIC int
   5626 _phy_8481_copper_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   5627 {
   5628     phy_ctrl_t      *pc;
   5629     uint16      mii_anp, mii_gb_stat, teng_an_stat;
   5630     int rv;
   5631 
   5632     pc = EXT_PHY_SW_STATE(unit, port);
   5633     rv = SOC_E_NONE;
   5634 
   5635     sal_memset(ability, 0, sizeof(*ability));
   5636 
   5637     if ((pc->mii_stat & (MII_STAT_AN_DONE | MII_STAT_LA))
   5638                    == (MII_STAT_AN_DONE | MII_STAT_LA)) {
   5639         /* Decode remote advertisement only when link is up  *\
   5640         \* and autoneg is completed.                         */
   5641 
   5642         /* Copper AutoNeg Link Partner ability (7.0xFFE5) */
   5643         SOC_IF_ERROR_RETURN
   5644             (READ_PHY8481_MII_ANPr(unit, pc, &mii_anp));
   5645         /* 1000BASE-T Status (7.0xFFEA) */
   5646         SOC_IF_ERROR_RETURN
   5647             (READ_PHY8481_MII_GB_STATr(unit, pc, &mii_gb_stat));
   5648         /* 10GBASE-T Status (7.0x0021), LP_10G_Capability[11] */
   5649         SOC_IF_ERROR_RETURN
   5650             (READ_PHY8481_TENG_AN_STATr(unit, pc, &teng_an_stat));
   5651 
   5652         if (mii_anp & MII_ANA_HD_10) { 
   5653             ability->speed_half_duplex  |= SOC_PA_SPEED_10MB;
   5654         }
   5655         if (mii_anp & MII_ANA_FD_10) {
   5656             ability->speed_full_duplex  |= SOC_PA_SPEED_10MB;
   5657         }
   5658         if (mii_anp & MII_ANA_HD_100) { 
   5659             ability->speed_half_duplex  |= SOC_PA_SPEED_100MB;
   5660         }
   5661         if (mii_anp & MII_ANA_FD_100) {
   5662             ability->speed_full_duplex  |= SOC_PA_SPEED_100MB;
   5663         }
   5664 
   5665         ability->pause     = 0;
   5666         switch (mii_anp & (MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE)) {
   5667             case MII_ANA_PAUSE:
   5668                 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   5669                 break;
   5670             case MII_ANA_ASYM_PAUSE:
   5671                 ability->pause = SOC_PA_PAUSE_TX;
   5672                 break;
   5673             case MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE:
   5674                 ability->pause = SOC_PA_PAUSE_RX;
   5675                 break;
   5676         }
   5677 
   5678         /* GE Specific values */
   5679 
   5680         if (mii_gb_stat & MII_GB_STAT_LP_1000HD) {
   5681            ability->speed_half_duplex |= SOC_PA_SPEED_1000MB;
   5682         }
   5683         if (mii_gb_stat & MII_GB_STAT_LP_1000FD) {
   5684            ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   5685         }
   5686 
   5687         /* 10G Specific values */
   5688         if (teng_an_stat & TENG_IEEE_AN_STAT_LP_10GBT) {
   5689            ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   5690         }
   5691 
   5692         /* EEE settings */
   5693         if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   5694             uint16 eee_ability;
   5695             SOC_IF_ERROR_RETURN
   5696                 (READ_PHY8481_EEE_LPABILr(unit, pc, &eee_ability));
   5697             if (eee_ability & 0x08) {
   5698                 ability->eee |= SOC_PA_EEE_10GB_BASET;
   5699             }
   5700             if (eee_ability & 0x04) {
   5701                 ability->eee |= SOC_PA_EEE_1GB_BASET;
   5702             }
   5703             if (eee_ability & 0x02) {
   5704                 ability->eee |= SOC_PA_EEE_100MB_BASETX;
   5705             }
   5706         }
   5707     } else {
   5708         return (SOC_E_FAIL);        
   5709     }
   5710 
   5711     return rv;
   5712 }
   5713 
   5714 STATIC int
   5715 _phy_8481_xaui_ability_remote_get(int unit, soc_port_t port,
   5716                                soc_port_ability_t *ability)
   5717 {
   5718     uint16            mii_stat_combo;
   5719     uint16            link_stat_gp;
   5720     uint16            an_adv;
   5721     soc_port_mode_t   mode;
   5722     phy_ctrl_t       *pc;
   5723 
   5724     pc = EXT_PHY_SW_STATE(unit, port);
   5725 
   5726     sal_memset(ability, 0, sizeof(*ability));
   5727 
   5728     SOC_IF_ERROR_RETURN
   5729         (READ_PHY8481_PHYXS_L_COMBO_IEEE0_MIISTATr(unit, pc, &mii_stat_combo));
   5730     SOC_IF_ERROR_RETURN
   5731         (READ_PHY8481_PHYXS_L_GP_STATUS_XGXSSTATUS3r(unit, pc, &link_stat_gp));
   5732      
   5733     LOG_INFO(BSL_LS_SOC_PHY,
   5734              (BSL_META_U(unit,
   5735                          "u=%d p=%d mii_stat_combo=%04x link_stat_gp=%04x\n"),
   5736               unit, port, mii_stat_combo, link_stat_gp));
   5737 
   5738 
   5739     mode = 0;
   5740     if ((link_stat_gp & GP_STATUS_XGXSSTATUS3_LINK_MASK) &&
   5741         (mii_stat_combo & MII_STAT_AN_DONE)) {
   5742         /* Decode remote advertisement only when link is up and autoneg is
   5743          * completed.
   5744          */
   5745 
   5746         SOC_IF_ERROR_RETURN
   5747             (READ_PHY8481_PHYXS_L_GP_STATUS_LP_UP1r(unit, pc, &an_adv));
   5748 
   5749         mode |= (an_adv & OVER1G_LP_UP1_DATARATE_10GCX4_MASK) ?
   5750                  SOC_PA_SPEED_10GB : 0;
   5751 
   5752         LOG_INFO(BSL_LS_SOC_PHY,
   5753                  (BSL_META_U(unit,
   5754                              "u=%d p=%d over1G an_adv=%04x\n"),
   5755                   unit, port, an_adv));
   5756         SOC_IF_ERROR_RETURN
   5757             (READ_PHY8481_PHYXS_L_COMBO_IEEE0_AUTONEGLPABILr(unit, pc, &an_adv));
   5758         LOG_INFO(BSL_LS_SOC_PHY,
   5759                  (BSL_META_U(unit,
   5760                              "u=%d p=%d combo an_adv=%04x\n"),
   5761                   unit, port, an_adv));
   5762 
   5763         mode |= (an_adv & MII_ANP_C37_FD) ? SOC_PA_SPEED_1000MB : 0;
   5764         ability->speed_full_duplex = mode;
   5765 
   5766         mode = 0; 
   5767         switch (an_adv & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) {
   5768             case MII_ANP_C37_PAUSE:
   5769                 mode |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   5770                 break;
   5771             case MII_ANP_C37_ASYM_PAUSE:
   5772                 mode |= SOC_PA_PAUSE_TX;
   5773                 break;
   5774             case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE:
   5775                 mode |= SOC_PA_PAUSE_RX;
   5776                 break;
   5777         }
   5778         ability->pause = mode;
   5779 
   5780         if (PHY_CLAUSE73_MODE(unit, port)) {
   5781             
   5782         }
   5783     } else {
   5784         return (SOC_E_FAIL);
   5785     }
   5786     LOG_INFO(BSL_LS_SOC_PHY,
   5787              (BSL_META_U(unit,
   5788                          "phy_8481_xaui_ability_remote_get:unit=%d p=%d pause=%08x sp=%08x\n"),
   5789               unit, port, ability->pause, ability->speed_full_duplex));
   5790 
   5791     return (SOC_E_NONE);
   5792 }
   5793 
   5794 STATIC int
   5795 phy_8481_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   5796 {
   5797     phy_ctrl_t      *pc;
   5798 
   5799     pc = EXT_PHY_SW_STATE(unit, port);
   5800 
   5801     if (NULL == ability) {
   5802         return (SOC_E_PARAM);
   5803     }
   5804 
   5805     if (PHY_COPPER_MODE(unit, port)) {
   5806         SOC_IF_ERROR_RETURN(_phy_8481_copper_ability_remote_get(unit, port, ability));
   5807     } else {
   5808         if (NXT_PC(pc)) {
   5809             PHYDRV_CALL_ARG1(pc,PHY_ABILITY_REMOTE_GET,ability);
   5810             return SOC_E_NONE;
   5811         }
   5812         SOC_IF_ERROR_RETURN(_phy_8481_xaui_ability_remote_get(unit, port, ability));
   5813     }
   5814 
   5815     return SOC_E_NONE;
   5816 }
   5817 
   5818 /*
   5819  * Function:
   5820  *      phy_8481_ability_local_get
   5821  * Purpose:
   5822  *      Get the device's complete abilities.
   5823  * Parameters:
   5824  *      unit - StrataSwitch unit #.
   5825  *      port - StrataSwitch port #.
   5826  *      ability - return device's abilities.
   5827  * Returns:
   5828  *      SOC_E_XXX
   5829  */
   5830 
   5831 STATIC int
   5832 _phy_8481_copper_ability_local_get(int unit, soc_port_t port,
   5833                                    soc_port_ability_t *ability)
   5834 {
   5835     phy_ctrl_t      *pc;
   5836 
   5837     pc = EXT_PHY_SW_STATE(unit, port);
   5838 
   5839     if ( PHY_IS_BCM8483X_AND_UP(pc) ) {
   5840         ability->speed_half_duplex  = SOC_PA_SPEED_100MB;
   5841         ability->speed_full_duplex  = SOC_PA_SPEED_10GB  | SOC_PA_SPEED_1000MB |
   5842                                       SOC_PA_SPEED_100MB;
   5843     } else {
   5844         ability->speed_half_duplex  = SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB;
   5845         ability->speed_full_duplex  = SOC_PA_SPEED_10GB  | SOC_PA_SPEED_1000MB |
   5846                                       SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB;
   5847     }
   5848 
   5849     ability->interface = SOC_PA_INTF_XGMII;
   5850     if ( PHY_IS_BCM8486X_AND_UP(pc) ) {    /* Mako supports 5G/2.5G speed     */
   5851         if ( PHY_REPEATER(unit, port) ) {  /* check MAC interface mode */
   5852             /* 5G/2.5G over XFI mode (XGMII) support both speed */
   5853             ability->speed_full_duplex |= (SOC_PA_SPEED_5000MB |
   5854                                            SOC_PA_SPEED_2500MB);
   5855         } else {
   5856             /* 2500BASE-X mode (SGMII) supports 2.5G only */
   5857             ability->speed_full_duplex |= (SOC_PA_SPEED_2500MB | SOC_PA_SPEED_5000MB);
   5858             ability->interface = SOC_PA_INTF_SGMII;
   5859 
   5860         }
   5861     }
   5862 
   5863     if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) &&
   5864          PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) ) {
   5865         ability->eee = SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET |
   5866                        SOC_PA_EEE_100MB_BASETX;
   5867     }
   5868 
   5869     ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   5870     ability->medium    = SOC_PA_MEDIUM_COPPER;
   5871     ability->loopback  = SOC_PA_LB_PHY;
   5872     ability->flags     = SOC_PA_AUTONEG;
   5873 
   5874     return (SOC_E_NONE);
   5875 }
   5876 
   5877 STATIC int
   5878 _phy_8481_xaui_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   5879 {
   5880 
   5881     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   5882     ability->speed_full_duplex  = SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB;
   5883 
   5884     ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   5885     ability->interface = SOC_PA_INTF_XGMII;
   5886     ability->medium    = SOC_PA_MEDIUM_XAUI;
   5887     ability->loopback  = SOC_PA_LB_PHY;
   5888     ability->flags     = SOC_PA_ABILITY_NONE;
   5889 
   5890     return (SOC_E_NONE);
   5891 }
   5892 
   5893 STATIC int
   5894 phy_8481_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   5895 {
   5896     if (NULL == ability) {
   5897         return SOC_E_PARAM;
   5898     }
   5899 
   5900     sal_memset(ability, 0, sizeof(*ability));
   5901 
   5902     if (PHY_COPPER_MODE(unit, port)) {
   5903         SOC_IF_ERROR_RETURN(_phy_8481_copper_ability_local_get(unit, port, ability));
   5904     } else {
   5905         SOC_IF_ERROR_RETURN(_phy_8481_xaui_ability_local_get(unit, port, ability));
   5906     }
   5907 
   5908     return (SOC_E_NONE);
   5909 }
   5910 
   5911 STATIC int
   5912 phy_8481_link_up(int unit, soc_port_t port)
   5913 {
   5914     int         lbmode, speed_line, speed_sys, an, an_done;
   5915     phy_ctrl_t  *pc;
   5916     phy_ctrl_t  *int_pc;
   5917 
   5918     int_pc = INT_PHY_SW_STATE(unit, port);
   5919     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_NO_SYS_LINE_SPD_SYNC);
   5920 
   5921     pc = EXT_PHY_SW_STATE(unit, port);
   5922     SOC_IF_ERROR_RETURN
   5923         (phy_8481_an_get(unit,port,&an,&an_done));
   5924 
   5925     SOC_IF_ERROR_RETURN
   5926         (_phy_8481_copper_lb_get(unit, port, &lbmode));
   5927     /* if the intended loopback speed was set, use the LB_SPEED */
   5928     if ( (! (lbmode) ) || (0 == (speed_line = LB_SPEED(pc))) ) { /* 0 means LB_SPEED not set */
   5929         /* don't know the intended speed for loopback,        *\
   5930         \* call phy_8481_speed_get() to get the current speed */
   5931         SOC_IF_ERROR_RETURN( phy_8481_speed_get(unit, port, &speed_line) );
   5932     }
   5933 
   5934     /* notify parameters to the system side */
   5935     switch ( speed_line ) {
   5936 
   5937     case 10000:
   5938     case 5000:
   5939     case 2500:
   5940         if ( ! LAST_IN_CHAIN(pc) ) {
   5941             /* MAC side interface type -- XGMII: 5G/2.5G over XFI mode *\
   5942             \*                         -- 2500X: 2500BASE-X mode       */
   5943             SOC_IF_ERROR_RETURN(
   5944                 soc_phyctrl_notify(unit, port, phyEventInterface,
   5945                             (PHY_REPEATER(unit, port)) ? SOC_PORT_IF_XFI  :
   5946                                  ((speed_line == 2500) ? SOC_PORT_IF_2500X
   5947                                                        : SOC_PORT_IF_5000X)) );
   5948             /* if MAC side in 5G/2.5G over XFI mode, force it to 10G speed */
   5949             if ( PHY_REPEATER(unit, port) ) {
   5950                 if ( 10000 != speed_line ) {
   5951                     /* system side is in 5G/2.5G over XFI (idle stuffing) *\
   5952                     |* mode when line side speed is 5G/2.5G, notify       *|
   5953                     \* the system side of 10G speed and set this flag     */
   5954                     PHY_FLAGS_SET(unit, port, PHY_FLAGS_NO_SYS_LINE_SPD_SYNC);
   5955                 }
   5956                 /* if MAC side in 5G/2.5G over XFI mode,  *\
   5957                 \* always notify system side of 10G speed */
   5958                 speed_sys = 10000;
   5959             } else {
   5960                 /* not 5G/2.5G over XFI mode, system side speed is same as line side */
   5961                 speed_sys = speed_line;
   5962             }
   5963             /* notify internal SerDes of system side speed */
   5964             SOC_IF_ERROR_RETURN
   5965                 (soc_phyctrl_notify(unit, port, phyEventSpeed    , speed_sys));
   5966             /* notify internal SerDes of line side speed */
   5967             SOC_IF_ERROR_RETURN
   5968                 (soc_phyctrl_notify(unit, port, phyEventSpeedLine, speed_line));
   5969             /* notify internal SerDes of Resume event */
   5970             SOC_IF_ERROR_RETURN
   5971                 (soc_phyctrl_notify(unit, port, phyEventResume, 1));
   5972         }
   5973         break;
   5974 
   5975     case 1000:
   5976         if ( ! LAST_IN_CHAIN(pc) ) {
   5977             if ( PHY_COPPER_MODE(unit, port) ) {
   5978                 SOC_IF_ERROR_RETURN
   5979                     (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII));
   5980                 SOC_IF_ERROR_RETURN
   5981                     (soc_phyctrl_notify(unit, port, phyEventSpeed    , 1000));
   5982                 SOC_IF_ERROR_RETURN
   5983                     (soc_phyctrl_notify(unit, port, phyEventSpeedLine, 1000));
   5984             } else {
   5985                 SOC_IF_ERROR_RETURN
   5986                     (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_XAUI));
   5987             }
   5988             SOC_IF_ERROR_RETURN
   5989                 (MODIFY_PHY8481_MII_AUX_CTRLr(unit, pc, (1U << 14), (1U << 14)));
   5990         }
   5991         break;
   5992 
   5993     case 100:
   5994     case 10:
   5995         if ( ! LAST_IN_CHAIN(pc) ) {
   5996             SOC_IF_ERROR_RETURN
   5997                 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII));
   5998             SOC_IF_ERROR_RETURN
   5999                 (soc_phyctrl_notify(unit, port, phyEventSpeed    , speed_line));
   6000             SOC_IF_ERROR_RETURN
   6001                 (soc_phyctrl_notify(unit, port, phyEventSpeedLine, speed_line));
   6002         }
   6003         SOC_IF_ERROR_RETURN
   6004             (MODIFY_PHY8481_MII_AUX_CTRLr(unit, pc, (1U << 14), (1U << 14)));
   6005         break;
   6006 
   6007     default:
   6008         break;
   6009     }
   6010 
   6011     /* misc. settings */
   6012     if ( PHY_IS_BCM84836(pc) || PHY_IS_BCM84846(pc) || PHY_IS_BCM84856(pc) ) {
   6013         /* for fiber media */
   6014         SOC_IF_ERROR_RETURN
   6015             (MODIFY_PHY8481_PHYXS_M_REG(unit, pc, 0x8061, 0, (1U << 5)));
   6016         SOC_IF_ERROR_RETURN
   6017             (MODIFY_PHY8481_PHYXS_M_REG(unit, pc, 0x80ba, 0, (3U << 2)));
   6018     }
   6019     if ( PHY_IS_BCM84834(pc) || PHY_IS_BCM84836(pc) ||
   6020          PHY_IS_BCM84844(pc) || PHY_IS_BCM84846(pc) || PHY_IS_BCM84848(pc) ) {
   6021         /* XFI LPI pass-thru for native mode EEE */
   6022         SOC_IF_ERROR_RETURN
   6023             (WRITE_PHY8481_PHYXS_M_REG(unit, pc, 0x8390, 0x007c));
   6024     }
   6025     #if 1
   6026         if ( SYS_FORCED_CL72(pc) )  {
   6027             SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an));
   6028         }
   6029     #endif
   6030    
   6031     /* Workaround for PHY-1570 Runt pkts on 84844 ports */    
   6032     if ( FLAGS(pc) & PHY8483X_ATOMIC_ACCESS_SHD ) {    
   6033         if ( (speed_line == 100) && (an == FALSE) ) {
   6034             _phy8485x_shadow_reg_write(unit, pc, REG_GROUP_SHADOW_MISC_REG, 0x0018, 0xffff, 0, 0x9c00);
   6035             _phy8485x_shadow_reg_write(unit, pc, REG_GROUP_SHADOW_MISC_REG, 0x0019, 0xffff, 0, 0x1000);
   6036             _phy8485x_shadow_reg_write(unit, pc, REG_GROUP_SHADOW_MISC_REG, 0x0018, 0xffff, 0, 0x0000);
   6037             _phy8485x_shadow_reg_write(unit, pc, REG_GROUP_SHADOW_MISC_REG, 0x0019, 0xffff, 0, 0x0000);
   6038         }
   6039     }
   6040 
   6041     LINK_DOWN(pc) = FALSE;
   6042     return (SOC_E_NONE);
   6043 }
   6044 
   6045 STATIC int
   6046 phy_8481_link_down(int unit, soc_port_t port)
   6047 {
   6048     phy_ctrl_t  *pc;
   6049 
   6050     pc = EXT_PHY_SW_STATE(unit, port);
   6051 
   6052     LB_SPEED(pc)  = 0;      /* clear the intended speed for loopback */
   6053     LINK_DOWN(pc) = TRUE;   /* set link-down flag */
   6054     return (SOC_E_NONE);
   6055 }
   6056 
   6057 /*
   6058  * Function:
   6059  *      phy_8481_mdix_set
   6060  * Description:
   6061  *      Set the Auto-MDIX mode of a port/PHY
   6062  * Parameters:
   6063  *      unit - Device number
   6064  *      port - Port number
   6065  *      mode - One of:
   6066  *              SOC_PORT_MDIX_AUTO
   6067  *                      Enable auto-MDIX when autonegotiation is enabled
   6068  *              SOC_PORT_MDIX_FORCE_AUTO
   6069  *                      Enable auto-MDIX always
   6070  *              SOC_PORT_MDIX_NORMAL
   6071  *                      Disable auto-MDIX
   6072  *              SOC_PORT_MDIX_XOVER
   6073  *                      Disable auto-MDIX, and swap cable pairs
   6074  * Return Value:
   6075  *      SOC_E_XXX
   6076  */
   6077 STATIC int
   6078 phy_8481_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode)
   6079 {
   6080     phy_ctrl_t    *pc;
   6081     int            speed;
   6082 
   6083     pc = EXT_PHY_SW_STATE(unit, port);
   6084 
   6085     if (!PHY_COPPER_MODE(unit, port)) {
   6086             return SOC_E_NONE;
   6087     }
   6088 
   6089     switch (mode) {
   6090     case SOC_PORT_MDIX_AUTO:
   6091         /* Clear bit 14 for automatic MDI crossover */
   6092         SOC_IF_ERROR_RETURN
   6093             (MODIFY_PHY8481_PHY_ECRr(unit, pc, 0, 0x4000));
   6094 
   6095         /*
   6096          * Write the result in the register 0x18, shadow copy 7
   6097          */
   6098         /* Clear bit 9 to disable forced auto MDI xover */
   6099         SOC_IF_ERROR_RETURN
   6100             (MODIFY_PHY8481_MII_MISC_CTRLr(unit, pc, 0, 0x0200));
   6101         break;
   6102 
   6103     case SOC_PORT_MDIX_FORCE_AUTO:
   6104         /* Clear bit 14 for automatic MDI crossover */
   6105         SOC_IF_ERROR_RETURN
   6106             (MODIFY_PHY8481_PHY_ECRr(unit, pc, 0, 0x4000));
   6107 
   6108         /*
   6109          * Write the result in the register 0x18, shadow copy 7
   6110          */
   6111         /* Set bit 9 to force automatic MDI crossover */
   6112         SOC_IF_ERROR_RETURN
   6113             (MODIFY_PHY8481_MII_MISC_CTRLr(unit, pc, 0x0200, 0x0200));
   6114         break;
   6115 
   6116     case SOC_PORT_MDIX_NORMAL:
   6117         SOC_IF_ERROR_RETURN(phy_8481_speed_get(unit, port, &speed));
   6118         if (speed == 0 || speed == 10 || speed == 100) {
   6119             /* Set bit 14 for manual MDI crossover */
   6120             SOC_IF_ERROR_RETURN
   6121                 (MODIFY_PHY8481_PHY_ECRr(unit, pc, 0x4000, 0x4000));
   6122 
   6123             SOC_IF_ERROR_RETURN
   6124                 (WRITE_PHY8481_TEST1r(unit, pc, 0));
   6125         } else {
   6126             return SOC_E_UNAVAIL;
   6127         }
   6128         break;
   6129 
   6130     case SOC_PORT_MDIX_XOVER:
   6131         SOC_IF_ERROR_RETURN(phy_8481_speed_get(unit, port, &speed));
   6132         if (speed == 0 || speed == 10 || speed == 100) {
   6133              /* Set bit 14 for manual MDI crossover */
   6134             SOC_IF_ERROR_RETURN
   6135                 (MODIFY_PHY8481_PHY_ECRr(unit, pc, 0x4000, 0x4000));
   6136 
   6137             SOC_IF_ERROR_RETURN
   6138                 (WRITE_PHY8481_TEST1r(unit, pc, 0x0080));
   6139         } else {
   6140             return SOC_E_UNAVAIL;
   6141         }
   6142         break;
   6143 
   6144     default:
   6145         return SOC_E_PARAM;
   6146     }
   6147 
   6148     pc->copper.mdix = mode;
   6149     return SOC_E_NONE;
   6150 
   6151 }        
   6152 
   6153 /*
   6154  * Function:
   6155  *      phy_8481_mdix_get
   6156  * Description:
   6157  *      Get the Auto-MDIX mode of a port/PHY
   6158  * Parameters:
   6159  *      unit - Device number
   6160  *      port - Port number
   6161  *      mode - (Out) One of:
   6162  *              SOC_PORT_MDIX_AUTO
   6163  *                      Enable auto-MDIX when autonegotiation is enabled
   6164  *              SOC_PORT_MDIX_FORCE_AUTO
   6165  *                      Enable auto-MDIX always
   6166  *              SOC_PORT_MDIX_NORMAL
   6167  *                      Disable auto-MDIX
   6168  *              SOC_PORT_MDIX_XOVER
   6169  *                      Disable auto-MDIX, and swap cable pairs
   6170  * Return Value:
   6171  *      SOC_E_XXX
   6172  */
   6173 STATIC int
   6174 phy_8481_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode)
   6175 {
   6176     phy_ctrl_t    *pc;
   6177     int            speed;
   6178 
   6179     pc = EXT_PHY_SW_STATE(unit, port);
   6180 
   6181     if (!PHY_COPPER_MODE(unit, port)) {
   6182         *mode = SOC_PORT_MDIX_NORMAL;
   6183         return SOC_E_NONE;
   6184     }
   6185 
   6186     SOC_IF_ERROR_RETURN(phy_8481_speed_get(unit, port, &speed));
   6187     if (speed == 1000) {
   6188        *mode = SOC_PORT_MDIX_AUTO;
   6189     } else {
   6190         *mode = pc->copper.mdix;
   6191     }
   6192 
   6193     return SOC_E_NONE;
   6194 }    
   6195 
   6196 /*
   6197  * Function:
   6198  *      phy_8481_mdix_status_get
   6199  * Description:
   6200  *      Get the current MDIX status on a port/PHY
   6201  * Parameters:
   6202  *      unit    - Device number
   6203  *      port    - Port number
   6204  *      status  - (OUT) One of:
   6205  *              SOC_PORT_MDIX_STATUS_NORMAL
   6206  *                      Straight connection
   6207  *              SOC_PORT_MDIX_STATUS_XOVER
   6208  *                      Crossover has been performed
   6209  * Return Value:
   6210  *      SOC_E_XXX
   6211  */
   6212 STATIC int
   6213 phy_8481_mdix_status_get(int unit, soc_port_t port,
   6214                          soc_port_mdix_status_t *status)
   6215 {
   6216     phy_ctrl_t    *pc;
   6217     uint16               tmp;
   6218 
   6219     pc = EXT_PHY_SW_STATE(unit, port);
   6220 
   6221     if (!PHY_COPPER_MODE(unit, port)) {
   6222         *status = SOC_PORT_MDIX_STATUS_NORMAL;
   6223         return SOC_E_NONE;
   6224     }
   6225     SOC_IF_ERROR_RETURN
   6226         (READ_PHY8481_PHY_ESRr(unit, pc, &tmp));
   6227     if (tmp & 0x2000) {
   6228         *status = SOC_PORT_MDIX_STATUS_XOVER;
   6229     } else {
   6230         *status = SOC_PORT_MDIX_STATUS_NORMAL;
   6231     }
   6232 
   6233     return SOC_E_NONE;
   6234 }
   6235 
   6236 /*
   6237  * Function:
   6238  *      phy_8481_master_set
   6239  * Purpose:
   6240  *      Set the master mode for the PHY.
   6241  * Parameters:
   6242  *      unit - StrataSwitch unit #.
   6243  *      port - StrataSwitch port #.
   6244  *      master - SOC_PORT_MS_*
   6245  * Returns:
   6246  *      SOC_E_XXX
   6247  * Notes:
   6248  *      No synchronization performed at this level. Autonegotiation is
   6249  *      not manipulated.
   6250  */
   6251 
   6252 STATIC int
   6253 phy_8481_master_set(int unit, soc_port_t port, int master)
   6254 {
   6255     uint16      mii_gb_ctrl;
   6256     phy_ctrl_t  *pc;
   6257 
   6258     pc = EXT_PHY_SW_STATE(unit, port);
   6259 
   6260     if (!PHY_COPPER_MODE(unit, port)) {
   6261             return SOC_E_NONE;
   6262     }
   6263 
   6264     SOC_IF_ERROR_RETURN
   6265         (READ_PHY8481_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl));
   6266 
   6267     switch (master) {
   6268     case SOC_PORT_MS_SLAVE:
   6269         mii_gb_ctrl |=  MII_GB_CTRL_MS_MAN;
   6270         mii_gb_ctrl &= ~MII_GB_CTRL_MS;
   6271         break;
   6272     case SOC_PORT_MS_MASTER:
   6273         mii_gb_ctrl |= MII_GB_CTRL_MS_MAN;
   6274         mii_gb_ctrl |= MII_GB_CTRL_MS;
   6275         break;
   6276     case SOC_PORT_MS_AUTO:
   6277         mii_gb_ctrl &= ~MII_GB_CTRL_MS_MAN;
   6278         break;
   6279     }
   6280 
   6281     SOC_IF_ERROR_RETURN
   6282         (WRITE_PHY8481_MII_GB_CTRLr(unit, pc, mii_gb_ctrl));
   6283 
   6284     pc->copper.master = master;
   6285 
   6286     return(SOC_E_NONE);
   6287 }
   6288 
   6289 /*
   6290  * Function:
   6291  *      phy_8481_master_get
   6292  * Purpose:
   6293  *      Get the master mode for the PHY.  If mode is forced, then
   6294  *      forced mode is returned; otherwise operating mode is returned.
   6295  * Parameters:
   6296  *      unit - StrataSwitch unit #.
   6297  *      port - StrataSwitch port #.
   6298  *      master - (OUT) SOC_PORT_MS_*
   6299  * Returns:
   6300  *      SOC_E_XXX
   6301  * Notes:
   6302  *      No synchronization performed at this level. Autonegotiation is
   6303  *      not manipulated.
   6304  */
   6305 
   6306 STATIC int
   6307 phy_8481_master_get(int unit, soc_port_t port, int *master)
   6308 {
   6309     uint16      mii_gb_ctrl;
   6310     phy_ctrl_t  *pc;
   6311 
   6312     pc = EXT_PHY_SW_STATE(unit, port);
   6313 
   6314     if (!PHY_COPPER_MODE(unit, port)) {
   6315         *master = SOC_PORT_MS_NONE;
   6316         return SOC_E_NONE;
   6317     }
   6318     SOC_IF_ERROR_RETURN
   6319         (READ_PHY8481_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl));
   6320 
   6321     if (!(mii_gb_ctrl & MII_GB_CTRL_MS_MAN)) {
   6322          *master = SOC_PORT_MS_AUTO;
   6323     }
   6324     else if (mii_gb_ctrl & MII_GB_CTRL_MS) {
   6325         *master = SOC_PORT_MS_MASTER;
   6326     } else {
   6327         *master = SOC_PORT_MS_SLAVE;
   6328     }
   6329 
   6330     return SOC_E_NONE;
   6331 }
   6332 
   6333 
   6334 
   6335 STATIC int
   6336 _phy_8481_halt(int unit, phy_ctrl_t *pc)
   6337 {
   6338     uint16 data16;
   6339 
   6340     /* LED control stuff */
   6341     SOC_IF_ERROR_RETURN
   6342         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa82c,0xffff));
   6343     SOC_IF_ERROR_RETURN
   6344         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa82d,0x0000));
   6345     SOC_IF_ERROR_RETURN
   6346         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa82e,0x0000));
   6347     SOC_IF_ERROR_RETURN
   6348         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa82f,0x0000));
   6349     SOC_IF_ERROR_RETURN
   6350         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa830,0x0000));
   6351     SOC_IF_ERROR_RETURN
   6352         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa831,0x0000));
   6353     SOC_IF_ERROR_RETURN
   6354         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa832,0x0000));
   6355     SOC_IF_ERROR_RETURN
   6356         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa833,0x0000));
   6357     SOC_IF_ERROR_RETURN
   6358         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa834,0x0000));
   6359     SOC_IF_ERROR_RETURN
   6360         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa835,0x0000));
   6361     SOC_IF_ERROR_RETURN
   6362         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa836,0x0000));
   6363     SOC_IF_ERROR_RETURN
   6364         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa837,0x0000));
   6365     SOC_IF_ERROR_RETURN
   6366         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa838,0x0000));
   6367     SOC_IF_ERROR_RETURN
   6368         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa839,0x0000));
   6369     SOC_IF_ERROR_RETURN
   6370         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa83a,0x0000));
   6371     SOC_IF_ERROR_RETURN
   6372         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa83b,0xb6db));
   6373     SOC_IF_ERROR_RETURN
   6374         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa83c,0xffff));
   6375     SOC_IF_ERROR_RETURN
   6376         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa83d,0x0000));
   6377     
   6378     if (PHY_IS_BCM8485X_AND_UP(pc)) {
   6379         if ( PHY_EXT_ROM_BOOT(pc) ) {
   6380             /* SPI ROM firmware download */
   6381             SOC_IF_ERROR_RETURN
   6382                 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x418c, 0x0000));
   6383         } else {
   6384             if (PHY_IS_BCM8488X(pc)) {
   6385                 SOC_IF_ERROR_RETURN
   6386                     (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x418c, 0x0000));
   6387             }
   6388             /* MDIO    firmware download */
   6389             data16 = (PHY_IS_BCM8486X_AND_UP(pc)) ? 0x48f0 : 0x0040;
   6390             SOC_IF_ERROR_RETURN
   6391                 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4188, data16));
   6392         }
   6393     }
   6394 
   6395     SOC_IF_ERROR_RETURN
   6396         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x017c)); /* assert reset for the whole ARM system */
   6397     SOC_IF_ERROR_RETURN
   6398         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4186,0x8000)); /* enable global reset */
   6399     SOC_IF_ERROR_RETURN
   6400         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0040)); /* deassert reset for the whole ARM system 
   6401                                                                  but the ARM processor */
   6402 
   6403     if (PHY_IS_BCM8488X(pc)) {
   6404         SOC_IF_ERROR_RETURN
   6405             (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4186,0x8000)); /* enable global reset */
   6406     }
   6407     /* write_addr=0xc300_0000, data=0x0000_001e, remove bottom write protection 
   6408        and set VINITHI signal to 1 in order to have the ARM processor start executing 
   6409        bootrom space 0xffff 0000 */
   6410 
   6411     if (!PHY_IS_BCM8485X_AND_UP(pc)) {
   6412         SOC_IF_ERROR_RETURN
   6413             (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0000));
   6414         SOC_IF_ERROR_RETURN
   6415             (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xc300));
   6416     }
   6417     else {
   6418         if (PHY_IS_BCM8488X(pc)) {
   6419             SOC_IF_ERROR_RETURN
   6420                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0000)); 
   6421             SOC_IF_ERROR_RETURN
   6422                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xc300)); 
   6423             SOC_IF_ERROR_RETURN
   6424                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0001));
   6425             SOC_IF_ERROR_RETURN
   6426                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0x0000)); 
   6427             SOC_IF_ERROR_RETURN
   6428                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6429         } else {    
   6430             SOC_IF_ERROR_RETURN
   6431                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0000)); 
   6432             SOC_IF_ERROR_RETURN
   6433                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xc300)); 
   6434             SOC_IF_ERROR_RETURN
   6435                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0010)); 
   6436             SOC_IF_ERROR_RETURN
   6437                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0x0000)); 
   6438             SOC_IF_ERROR_RETURN
   6439                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6440             SOC_IF_ERROR_RETURN
   6441                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0000)); 
   6442             SOC_IF_ERROR_RETURN
   6443                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 
   6444             SOC_IF_ERROR_RETURN
   6445                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x1018)); 
   6446             SOC_IF_ERROR_RETURN
   6447                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xe59f)); 
   6448             SOC_IF_ERROR_RETURN
   6449                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6450             SOC_IF_ERROR_RETURN
   6451                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0004)); 
   6452             SOC_IF_ERROR_RETURN
   6453                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 
   6454             SOC_IF_ERROR_RETURN
   6455                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x1f11)); 
   6456             SOC_IF_ERROR_RETURN
   6457                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xee09)); 
   6458             SOC_IF_ERROR_RETURN
   6459                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6460             SOC_IF_ERROR_RETURN
   6461                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0008)); 
   6462             SOC_IF_ERROR_RETURN
   6463                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 
   6464             SOC_IF_ERROR_RETURN
   6465                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0000)); 
   6466             SOC_IF_ERROR_RETURN
   6467                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xe3a0)); 
   6468             SOC_IF_ERROR_RETURN
   6469                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6470             SOC_IF_ERROR_RETURN
   6471                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x000c)); 
   6472             SOC_IF_ERROR_RETURN
   6473                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 
   6474             SOC_IF_ERROR_RETURN
   6475                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x1806)); 
   6476             SOC_IF_ERROR_RETURN
   6477                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xe3a0)); 
   6478             SOC_IF_ERROR_RETURN
   6479                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6480             SOC_IF_ERROR_RETURN
   6481                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0010)); 
   6482             SOC_IF_ERROR_RETURN
   6483                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 
   6484             SOC_IF_ERROR_RETURN
   6485                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0002)); 
   6486             SOC_IF_ERROR_RETURN
   6487                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xe8a0)); 
   6488             SOC_IF_ERROR_RETURN
   6489                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6490             SOC_IF_ERROR_RETURN
   6491                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0014)); 
   6492             SOC_IF_ERROR_RETURN
   6493                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 
   6494             SOC_IF_ERROR_RETURN
   6495                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0001)); 
   6496             SOC_IF_ERROR_RETURN
   6497                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xe150)); 
   6498             SOC_IF_ERROR_RETURN
   6499                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6500             SOC_IF_ERROR_RETURN
   6501                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0018)); 
   6502             SOC_IF_ERROR_RETURN
   6503                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 
   6504             SOC_IF_ERROR_RETURN
   6505                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0xfffc)); 
   6506             SOC_IF_ERROR_RETURN
   6507                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0x3aff)); 
   6508             SOC_IF_ERROR_RETURN
   6509                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6510             SOC_IF_ERROR_RETURN
   6511                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x001c)); 
   6512             SOC_IF_ERROR_RETURN
   6513                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 
   6514             SOC_IF_ERROR_RETURN
   6515                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0xfffe)); 
   6516             SOC_IF_ERROR_RETURN
   6517                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xeaff)); 
   6518             SOC_IF_ERROR_RETURN
   6519                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6520             SOC_IF_ERROR_RETURN
   6521                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0020)); 
   6522             SOC_IF_ERROR_RETURN
   6523                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 
   6524             SOC_IF_ERROR_RETURN
   6525                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0021)); 
   6526            SOC_IF_ERROR_RETURN
   6527                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0x0004)); 
   6528            SOC_IF_ERROR_RETURN
   6529                 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 
   6530         }
   6531     }
   6532     if (!PHY_IS_BCM8488X(pc)) {
   6533         SOC_IF_ERROR_RETURN
   6534             (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16));
   6535         if (data16 & (1U << 13)) {
   6536             SOC_IF_ERROR_RETURN
   6537                (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0x001e));
   6538         } else {
   6539             /* Halt CPU if doing PMA/PMD reset. */ 
   6540             if ( ! (PHY_IS_BCM8485X_AND_UP(pc)) ) {
   6541                 SOC_IF_ERROR_RETURN
   6542                     (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0x001f));
   6543             }
   6544         }
   6545     }
   6546     if ( ! (PHY_IS_BCM8485X_AND_UP(pc)) ) {
   6547         SOC_IF_ERROR_RETURN
   6548             (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 0x0000));
   6549         SOC_IF_ERROR_RETURN
   6550             (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 
   6551                 (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT)));
   6552     }
   6553 
   6554     /* write_addr=0xffff_0000, data=0xeaff_fffe, replace the first 32 bits of bootrom
   6555        at 0xffff0000 with the instruction "B 0xffff0000" to loop the processor in the
   6556        bootrom address space */
   6557     if (!PHY_IS_BCM8485X_AND_UP(pc)) {
   6558         SOC_IF_ERROR_RETURN
   6559             (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0000));
   6560         SOC_IF_ERROR_RETURN
   6561             (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xffff));
   6562         SOC_IF_ERROR_RETURN
   6563             (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0xfffe));
   6564         SOC_IF_ERROR_RETURN
   6565             (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 0xeaff));
   6566         SOC_IF_ERROR_RETURN
   6567             (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 
   6568                 (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT)));
   6569     }
   6570 
   6571     SOC_IF_ERROR_RETURN
   6572         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0000)); /* deassert reset */ 
   6573 
   6574     return (SOC_E_NONE);
   6575 }
   6576 
   6577 STATIC int
   6578 _phy_8481_prog_eeprom(int unit, phy_ctrl_t *pc)
   6579 {
   6580     soc_timeout_t  to_prog;
   6581 
   6582     /* write_addr=0xc300_0000, data=0x0000_002c, enable bottom write protection 
   6583        and set VINITHI signal to 0 */
   6584 
   6585     SOC_IF_ERROR_RETURN
   6586         (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0000));
   6587     SOC_IF_ERROR_RETURN
   6588         (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xc300));
   6589     SOC_IF_ERROR_RETURN
   6590         (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0x002c));
   6591     SOC_IF_ERROR_RETURN
   6592         (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 0x0000));
   6593     SOC_IF_ERROR_RETURN
   6594         (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 
   6595             (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT)));
   6596 
   6597     SOC_IF_ERROR_RETURN
   6598         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0040));
   6599     SOC_IF_ERROR_RETURN
   6600         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0000));
   6601 
   6602     soc_timeout_init(&to_prog, 10000000, 0);
   6603 
   6604     do {
   6605         soc_timeout_t  to_status;
   6606         int            rv;
   6607         uint16 status, data_low, data_high;
   6608 
   6609         SOC_IF_ERROR_RETURN
   6610             (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0010));
   6611         SOC_IF_ERROR_RETURN
   6612             (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xc300));
   6613         SOC_IF_ERROR_RETURN
   6614             (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 
   6615                 (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_RD_SHIFT)));
   6616 
   6617         soc_timeout_init(&to_status, 10000, 0);
   6618 
   6619         do {
   6620             rv = READ_PHY8481_MDIO2ARM_STS_REG(unit, pc, &status);
   6621             if (((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) != 0) ||
   6622                 SOC_FAILURE(rv)) {
   6623                 break;
   6624             }
   6625         } while (!soc_timeout_check(&to_status));
   6626 
   6627         if ((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) == 0) {
   6628             SOC_IF_ERROR_RETURN
   6629                 (WRITE_PHY8481_MDIO2ARM_CTL_REG( unit, pc, 0 )); 
   6630             LOG_WARN(BSL_LS_SOC_PHY,
   6631                      (BSL_META_U(unit,
   6632                                  "PHY8481 MDIO2ARM read failed: u=%d p=%d\n"), unit, pc->port ));
   6633             return (SOC_E_FAIL);
   6634         }
   6635 
   6636         SOC_IF_ERROR_RETURN
   6637             (READ_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, &data_low));
   6638         SOC_IF_ERROR_RETURN
   6639             (READ_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, &data_high));
   6640 
   6641         if ( (data_low == 0x600d) || (data_high == 0x600d) ) {
   6642             return (SOC_E_NONE);
   6643         }
   6644 
   6645         if ( (data_low == 0xdead) || (data_high == 0xdead) ) {
   6646             return (SOC_E_FAIL);
   6647         }
   6648 
   6649       } while(!soc_timeout_check(&to_prog));
   6650 
   6651     LOG_WARN(BSL_LS_SOC_PHY,
   6652              (BSL_META_U(unit,
   6653                          "PHY8481 firmware programming timed out !.: u=%d p=%d\n"), unit, pc->port ));
   6654 
   6655     return (SOC_E_FAIL);
   6656 }
   6657 
   6658 STATIC int
   6659 _phy_8481_restart(int unit, phy_ctrl_t *pc)
   6660 {
   6661     SOC_IF_ERROR_RETURN
   6662         (MODIFY_PHY8481_PMAD_CTRLr(unit, pc, MII_CTRL_RESET, MII_CTRL_RESET));
   6663 
   6664     return (SOC_E_NONE);
   6665 }
   6666 
   6667 #define WRITE_BLK_SIZE 4
   6668 
   6669 /* This routine should be used only when the ARM CPU is halted/looping. */
   6670 
   6671 STATIC int
   6672 _phy_8481_write_to_arm(int unit, phy_ctrl_t *pc, uint32 addr, uint8 *data,int len)
   6673 {
   6674     int n_writes, i;
   6675 
   6676 #ifdef PHY8481_MEASSURE_DOWNLOAD_TIME
   6677     sal_usecs_t t;
   6678     t = sal_time_usecs();
   6679 #endif
   6680 
   6681     n_writes = (len + WRITE_BLK_SIZE -1) / WRITE_BLK_SIZE;
   6682 
   6683     SOC_IF_ERROR_RETURN
   6684         (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 
   6685             (1U << MDIO2ARM_CTL_MDIO2ARM_SELF_INC_ADDR_SHIFT)
   6686           | (1U << MDIO2ARM_CTL_MDIO2ARM_BURST_SHIFT)
   6687           | (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)
   6688           | (1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT)));
   6689 
   6690     SOC_IF_ERROR_RETURN
   6691         (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, ((addr>>16) & 0xffff)));
   6692     SOC_IF_ERROR_RETURN
   6693         (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, (addr & 0xffff)));
   6694 
   6695     for ( i = 0; i < n_writes; i++ ) {
   6696 
   6697         SOC_IF_ERROR_RETURN
   6698             (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 
   6699                 ((*( data + WRITE_BLK_SIZE/2 + 1 ))<<8)|( *( data + WRITE_BLK_SIZE/2 ))));
   6700         SOC_IF_ERROR_RETURN
   6701             (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, ((*( data + 1 ))<<8)|(*( data + 0 ))));
   6702 
   6703         data += WRITE_BLK_SIZE;
   6704 
   6705     }
   6706     SOC_IF_ERROR_RETURN
   6707         (WRITE_PHY8481_MDIO2ARM_CTL_REG( unit, pc, 0 )); 
   6708 
   6709 #ifdef PHY8481_MEASSURE_DOWNLOAD_TIME
   6710     LOG_CLI((BSL_META_U(unit,
   6711                         "u=%d p=%d raw download took %u us\n"), unit, pc->port, SAL_USECS_SUB(sal_time_usecs(), t)));
   6712 #endif
   6713 
   6714     return (SOC_E_NONE);
   6715 }
   6716 
   6717 #ifdef BCM848XX_STATE_MFG_DIAG_SUPPORT
   6718 
   6719 #define READ_BLK_SIZE 4
   6720 
   6721 STATIC int
   6722 _phy_8481_read_from_arm(int unit, phy_ctrl_t *pc, uint32 addr, uint8 *data, int len)
   6723 {
   6724     soc_timeout_t  to;
   6725     int            rv;
   6726     int n_reads, i;
   6727     uint16 data16_high, data16_low, status;
   6728 
   6729     n_reads = (len + READ_BLK_SIZE -1) / READ_BLK_SIZE;
   6730 
   6731     SOC_IF_ERROR_RETURN
   6732         (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, (1U << MDIO2ARM_CTL_MDIO2ARM_SELF_INC_ADDR_SHIFT) |
   6733                                                   (1U << MDIO2ARM_CTL_MDIO2ARM_BURST_SHIFT) |
   6734                                                   (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT) |
   6735                                                   (1U << MDIO2ARM_CTL_MDIO2ARM_RD_SHIFT)));
   6736 
   6737     SOC_IF_ERROR_RETURN
   6738         (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, ((addr>>16) & 0xffff)));
   6739     SOC_IF_ERROR_RETURN
   6740         (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, (addr & 0xffff)));
   6741 
   6742     SOC_IF_ERROR_RETURN
   6743         (READ_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, &data16_low)); /* dummy read */
   6744 
   6745     for ( i = 0; i < n_reads; i++ ) {
   6746 
   6747         soc_timeout_init(&to, 10000, 0);
   6748         do {
   6749             rv = READ_PHY8481_MDIO2ARM_STS_REG(unit, pc, &status);
   6750             if (((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) != 0) ||
   6751                 SOC_FAILURE(rv)) {
   6752                 break;
   6753             }
   6754         } while (!soc_timeout_check(&to));
   6755         if ((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) == 0) {
   6756             LOG_WARN(BSL_LS_SOC_PHY,
   6757                      (BSL_META_U(unit,
   6758                                  "PHY8481 MDIO2ARM read failed: u=%d p=%d addr=%08x\n"), unit, pc->port, addr));
   6759             return (SOC_E_FAIL);
   6760         }
   6761         SOC_IF_ERROR_RETURN
   6762             (READ_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, &data16_high));
   6763         SOC_IF_ERROR_RETURN
   6764             (READ_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, &data16_low)); /* causes auto inc of addr */
   6765 
   6766         *(data++) = data16_low & 0xff;
   6767         *(data++) = (data16_low>>8) & 0xff;
   6768         *(data++) = data16_high & 0xff;
   6769         *(data++) = (data16_high>>8) & 0xff;
   6770     }
   6771 
   6772     SOC_IF_ERROR_RETURN
   6773         (WRITE_PHY8481_MDIO2ARM_CTL_REG( unit, pc, 0 )); 
   6774 
   6775     return (SOC_E_NONE);
   6776 }
   6777 #endif  /* BCM848XX_STATE_MFG_DIAG_SUPPORT */
   6778 
   6779 /* This routine could be used while the ARM CPU is running. */
   6780 
   6781 STATIC int
   6782 _phy_8481_mdio2arm_read(int unit, soc_port_t port, uint32 addr, uint32 *val, int access32)
   6783 {
   6784     soc_timeout_t  to;
   6785     int            rv;
   6786     uint16 data_low = 0, data_high = 0, status;
   6787     phy_ctrl_t *pc;
   6788 
   6789     pc = EXT_PHY_SW_STATE(unit, port);
   6790 
   6791     SOC_IF_ERROR_RETURN
   6792         (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, (addr & 0xffff)));
   6793     SOC_IF_ERROR_RETURN
   6794         (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, ((addr>>16) & 0xffff)));
   6795 
   6796     SOC_IF_ERROR_RETURN
   6797         (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 
   6798             ((access32 ? 2U : 1U) << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT) |
   6799             (1U << MDIO2ARM_CTL_MDIO2ARM_RD_SHIFT)));
   6800 
   6801     soc_timeout_init(&to, 10000, 0);
   6802 
   6803     do {
   6804         rv = READ_PHY8481_MDIO2ARM_STS_REG(unit, pc, &status);
   6805         if (((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) != 0) ||
   6806             SOC_FAILURE(rv)) {
   6807             break;
   6808         }
   6809     } while (!soc_timeout_check(&to));
   6810     if ((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) == 0) {
   6811         LOG_WARN(BSL_LS_SOC_PHY,
   6812                  (BSL_META_U(unit,
   6813                              "PHY8481 MDIO2ARM read failed: u=%d p=%d addr=%08x\n"), unit, port, addr));
   6814         return (SOC_E_FAIL);
   6815     }
   6816 
   6817     SOC_IF_ERROR_RETURN
   6818         (READ_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, &data_low));
   6819 
   6820     if (access32) {
   6821         SOC_IF_ERROR_RETURN
   6822             (READ_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, &data_high));
   6823     }
   6824 
   6825     *val = (data_high<<16)|data_low; 
   6826 
   6827     return (SOC_E_NONE);
   6828 
   6829 }
   6830 
   6831 /* This routine could be used while the ARM CPU is running. */
   6832 
   6833 STATIC int
   6834 _phy_8481_mdio2arm_write(int unit, soc_port_t port, uint32 addr, uint32 val, int access32)
   6835 {
   6836     soc_timeout_t  to;
   6837     int            rv;
   6838     uint16 status;
   6839     phy_ctrl_t *pc;
   6840 
   6841     pc = EXT_PHY_SW_STATE(unit, port);
   6842 
   6843     SOC_IF_ERROR_RETURN
   6844         (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, (addr & 0xffff)));
   6845     SOC_IF_ERROR_RETURN
   6846         (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, ((addr>>16) & 0xffff)));
   6847 
   6848     SOC_IF_ERROR_RETURN
   6849         (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, (val & 0xffff)));
   6850 
   6851     if (access32) {
   6852         SOC_IF_ERROR_RETURN
   6853             (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, ((val>>16) & 0xffff)));
   6854     }
   6855 
   6856     SOC_IF_ERROR_RETURN
   6857         (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 
   6858             ((access32 ? 2U : 1U) << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|
   6859             (1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT)));
   6860 
   6861     soc_timeout_init(&to, 10000, 0);
   6862 
   6863     do {
   6864         rv = READ_PHY8481_MDIO2ARM_STS_REG(unit, pc, &status);
   6865         if (((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) != 0) ||
   6866             SOC_FAILURE(rv)) {
   6867             break;
   6868         }
   6869     } while (!soc_timeout_check(&to));
   6870     if ((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) == 0) {
   6871         LOG_WARN(BSL_LS_SOC_PHY,
   6872                  (BSL_META_U(unit,
   6873                              "PHY8481 MDIO2ARM write failed: u=%d p=%d addr=%08x\n"), unit, port, addr));
   6874         return (SOC_E_FAIL);
   6875     }
   6876 
   6877     return (SOC_E_NONE);
   6878 
   6879 }
   6880 
   6881 int
   6882 _phy_8481_mdio2arm_read32(int unit, soc_port_t port, uint32 addr, uint32 *val)
   6883 {
   6884     SOC_IF_ERROR_RETURN
   6885         (_phy_8481_mdio2arm_read(unit, port, addr, val, TRUE));
   6886     return (SOC_E_NONE);
   6887 }
   6888 
   6889 int
   6890 _phy_8481_mdio2arm_write32(int unit, soc_port_t port, uint32 addr, uint32 val)
   6891 {
   6892     SOC_IF_ERROR_RETURN
   6893         (_phy_8481_mdio2arm_write(unit, port, addr, val, TRUE));
   6894     return (SOC_E_NONE);
   6895 }
   6896 
   6897 #ifdef PHY8481_ARM_MEM_DEBUG
   6898 
   6899 int
   6900 _phy_8481_mdio2arm_read16(int unit, soc_port_t port, uint32 addr, uint16 *val)
   6901 {
   6902     uint32 data;
   6903 
   6904     SOC_IF_ERROR_RETURN
   6905         (_phy_8481_mdio2arm_read(unit, port, addr, &data, FALSE));
   6906     *val = data;
   6907 
   6908     return (SOC_E_NONE);
   6909 }
   6910 
   6911 int
   6912 _phy_8481_mdio2arm_write16(int unit, soc_port_t port, uint32 addr, uint16 val)
   6913 {
   6914     SOC_IF_ERROR_RETURN
   6915         (_phy_8481_mdio2arm_write(unit, port, addr, (uint32)val, FALSE));
   6916     return (SOC_E_NONE);
   6917 }
   6918 
   6919 
   6920 int
   6921 _phy_8481_show_arm16(int unit, soc_port_t port, uint32 addr)
   6922 {
   6923     uint16 data;
   6924 
   6925     SOC_IF_ERROR_RETURN
   6926         (_phy_8481_mdio2arm_read16(unit, port, addr, &data));
   6927 
   6928     LOG_CLI((BSL_META_U(unit,
   6929                         "Value = %04x\n"), data)); 
   6930 
   6931     return (SOC_E_NONE);
   6932 }
   6933 
   6934 int
   6935 _phy_8481_show_arm32(int unit, soc_port_t port, uint32 addr)
   6936 {
   6937     uint32 data;
   6938 
   6939     SOC_IF_ERROR_RETURN
   6940         (_phy_8481_mdio2arm_read32(unit, port, addr, &data));
   6941 
   6942     LOG_CLI((BSL_META_U(unit,
   6943                         "Value = %08x\n"), data)); 
   6944 
   6945     return (SOC_E_NONE);
   6946 }
   6947 
   6948 #endif
   6949 
   6950 /*
   6951  * Function:
   6952  *      phy_8481_firmware_set
   6953  * Purpose:
   6954  *      program the given firmware into the SPI-ROM
   6955  * Parameters:
   6956  *      unit - StrataSwitch unit #.
   6957  *      port - StrataSwitch port #.
   6958  *      offset - offset to the data stream
   6959  *      array  - the given data
   6960  *      datalen- the data length
   6961  * Returns:
   6962  *      SOC_E_NONE
   6963  */
   6964 
   6965 STATIC int
   6966 phy_8481_firmware_set(int unit, int port, int offset, uint8 *data,int len)
   6967 {
   6968     phy_ctrl_t *pc;
   6969     uint16 saved_phy_addr, data16;
   6970     int dividend, divisor, rv = SOC_E_FAIL;
   6971     uint16 temp1, temp2;
   6972 
   6973     pc = EXT_PHY_SW_STATE(unit, port);
   6974 
   6975     if (data) {
   6976         if ((!PHY_COPPER_MODE(unit, port)) && NXT_PC(pc)) {
   6977             /* there is a PHY device connected to this XAUI port. Always program the
   6978              * outmost PHY device. To program the next external device in the chain,
   6979              * detach/remove the outmost phy device first
   6980              */
   6981             PHYDRV_CALL_ARG3(pc,PHY_FIRMWARE_SET,offset,data,len);
   6982             return SOC_E_NONE;
   6983         }
   6984         LOG_CLI((BSL_META_U(unit,
   6985                             "Step 1: Halting the system.\n")));
   6986     
   6987         SOC_IF_ERROR_RETURN
   6988             (_phy_8481_halt(unit, pc));
   6989     
   6990         LOG_CLI((BSL_META_U(unit,
   6991                             "Step 2: Uploading the SPI loader and data"
   6992                             " into main memory.\n")));
   6993     
   6994         SOC_IF_ERROR_RETURN
   6995             (_phy_8481_write_to_arm(unit, pc, (uint32) offset, data, len));
   6996     
   6997         LOG_CLI((BSL_META_U(unit,
   6998                             "Step 3: Waiting for the Programming phase"
   6999                             " to be completed.\n")));
   7000     
   7001         SOC_IF_ERROR_RETURN
   7002             (_phy_8481_prog_eeprom(unit, pc));
   7003     
   7004         LOG_CLI((BSL_META_U(unit,
   7005                             "Step 4: Restarting system.\n")));
   7006     
   7007         SOC_IF_ERROR_RETURN
   7008             (_phy_8481_restart(unit, pc));
   7009     } else {
   7010         switch (offset) {
   7011         case PHYCTRL_UCODE_BCST_SETUP:
   7012             if ( ! PHY_IS_BCM8485X_AND_UP(pc) ) {
   7013                 /* Turn on broadcast mode */
   7014                 SOC_IF_ERROR_RETURN
   7015                     (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x411e,0xf003));
   7016                 SOC_IF_ERROR_RETURN
   7017                     (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x410e,0x0401));
   7018             }
   7019             /* halt the system */
   7020             SOC_IF_ERROR_RETURN( _phy_8481_halt(unit, pc) );
   7021             break;
   7022         case PHYCTRL_UCODE_BCST_uC_SETUP:
   7023             break;
   7024         case PHYCTRL_UCODE_BCST_ENABLE:
   7025             if ( PHY_IS_BCM8485X_AND_UP(pc) ) {
   7026                 /* Turn on broadcast mode after halting system */
   7027                 SOC_IF_ERROR_RETURN
   7028                     (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4117, 0xf003));
   7029                 SOC_IF_ERROR_RETURN
   7030                     (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4107, 0x0401));
   7031             }
   7032             break;
   7033         case PHYCTRL_UCODE_BCST_LOAD:
   7034             saved_phy_addr = pc->phy_id;
   7035             pc->phy_id &= ~0x1f;
   7036             SOC_IF_ERROR_RETURN
   7037                 (READ_PHY8481_PMAD_REG(unit, pc, 0x2, &temp1));
   7038             SOC_IF_ERROR_RETURN
   7039                 (READ_PHY8481_PMAD_REG(unit, pc, 0x3, &temp2));
   7040             if(temp1 != 0xffff) {
   7041                 if((temp1 != pc->phy_id0) || (temp2 != pc->phy_id1)) {
   7042                     LOG_WARN(BSL_LS_SOC_PHY,
   7043                              (BSL_META_U(unit,
   7044                                          "Another PHY already exist on same boradcast MDIO address.\n")));
   7045                 }    
   7046             }
   7047 
   7048             if (DL_DIVIDEND(pc) && DL_DIVISOR(pc)) {
   7049                  rv = soc_cmic_rate_param_get(unit, &dividend, &divisor);
   7050                 if (SOC_SUCCESS(rv)) {
   7051                     rv = soc_cmic_rate_param_set(unit, DL_DIVIDEND(pc), DL_DIVISOR(pc));
   7052                 }
   7053             }
   7054 
   7055             SOC_IF_ERROR_RETURN
   7056                 (_phy_8481_write_to_arm(unit, pc, 0, FIRMWARE(pc), FIRMWARE_LEN(pc)));
   7057             /* write_addr=0xc300_0000, data=0x0000_000c, enable bottom write protection 
   7058                and set VINITHI signal to 0 (reset vector at 0x0000_0000) */
   7059 
   7060             data16 = (PHY_IS_BCM8485X_AND_UP(pc)) ? 0x0000 : 0x000c;
   7061             SOC_IF_ERROR_RETURN
   7062                 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 0x0000));
   7063             SOC_IF_ERROR_RETURN
   7064                 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0000));
   7065             SOC_IF_ERROR_RETURN
   7066                 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xc300));
   7067             SOC_IF_ERROR_RETURN
   7068                 (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, data16));
   7069             SOC_IF_ERROR_RETURN
   7070                 (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 0x0000));
   7071             SOC_IF_ERROR_RETURN
   7072                 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc,
   7073                     (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT)));
   7074 
   7075             if (SOC_SUCCESS(rv)) {
   7076                 /* rv contains the return value of previous soc_cmic_rate_param_set() */
   7077                 SOC_IF_ERROR_RETURN
   7078                     (soc_cmic_rate_param_set(unit, dividend, divisor));
   7079             }
   7080             pc->phy_id = saved_phy_addr;
   7081             break;
   7082         case PHYCTRL_UCODE_BCST_END:
   7083             /* Turn off broadcast mode */
   7084             if (PHY_IS_BCM8485X_AND_UP(pc)) {
   7085                 /* Before reset the processor, add OSF setting for all ports  */
   7086                 SOC_IF_ERROR_RETURN
   7087                     (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0000));
   7088                 SOC_IF_ERROR_RETURN
   7089                     (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA008 , 0x0000));
   7090                 SOC_IF_ERROR_RETURN
   7091                     (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x8004,0x5555));
   7092                 if ( PHY_IS_BCM8488X(pc) ) {
   7093                     SOC_IF_ERROR_RETURN
   7094                         (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA003 , 0x0000));
   7095                     SOC_IF_ERROR_RETURN
   7096                         (WRITE_PHY8481_PMAD_REG(unit, pc, 0x0000 , 0x8000));
   7097                 } else {
   7098                     SOC_IF_ERROR_RETURN
   7099                         (WRITE_PHY8481_PMAD_REG(unit, pc, 0x0000 , 0x8000));
   7100                     SOC_IF_ERROR_RETURN
   7101                         (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4107,0x0000));
   7102                 }
   7103             } else {
   7104                 SOC_IF_ERROR_RETURN
   7105                     (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x410e,0x0000));
   7106             }
   7107 
   7108             SOC_IF_ERROR_RETURN
   7109                 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16));
   7110             if (data16 & (1U << 13)) {
   7111                 /* Now reset only the ARM core */
   7112                 SOC_IF_ERROR_RETURN
   7113                     (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0040));
   7114                 SOC_IF_ERROR_RETURN
   7115                     (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0000));
   7116             } else {
   7117                 SOC_IF_ERROR_RETURN
   7118                     (MODIFY_PHY8481_PMAD_CTRLr(unit, pc,
   7119                                           MII_CTRL_RESET, MII_CTRL_RESET));
   7120             }
   7121 
   7122             if (PHY_IS_BCM8484X_A0(pc)) {
   7123                 sal_usleep(300000);
   7124             }
   7125             soc_timeout_init(&TO(pc), 2000000, 0);
   7126             break;
   7127         default:
   7128             break;
   7129         }
   7130     }
   7131 
   7132     return SOC_E_NONE;
   7133 }
   7134 
   7135 STATIC int
   7136 _phy_84834_control_prbs_invert_data_set(int unit, soc_port_t port,
   7137                                         int tx, int invert)
   7138 {
   7139     uint16       data16;
   7140     phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
   7141 
   7142     data16 = (invert) ? PHY848XX_PRBS_INVERT_MASK : 0;
   7143     if ( PHY_IS_BCM8488X_A0(pc) ) {
   7144         /* Orca A0 workaround: must use 32-bit addressing mode for PRBS */
   7145         uint32  reg32 = (tx) ? PHY848XX_TX_PRBS_ADDR32_REGISTER
   7146                              : PHY848XX_RX_PRBS_ADDR32_REGISTER;
   7147         SOC_IF_ERROR_RETURN(
   7148             _phy848xx_addr32_reg_modify(unit, pc, reg32,
   7149                                     data16, PHY848XX_PRBS_INVERT_MASK) );
   7150     } else
   7151     if ( PHY_IS_BCM8485X_AND_UP(pc) ) {
   7152         uint32  reg   = (tx) ? PHY8485X_TX_PRBS_REGISTER
   7153                              : PHY8485X_RX_PRBS_REGISTER;
   7154         SOC_IF_ERROR_RETURN(
   7155             MODIFY_PHY8481_PMAD_REG(unit, pc, reg,
   7156                                     data16, PHY848XX_PRBS_INVERT_MASK) );
   7157     }
   7158     else {      /* 8483x / 8484x */
   7159         uint16  mask16;
   7160         if ( tx ) {
   7161             data16 = (invert) ? PHY84834_USER_PRBS_TX_INVERT : 0;
   7162             mask16 = PHY84834_USER_PRBS_TX_INVERT;
   7163         } else {
   7164             data16 = (invert) ? PHY84834_USER_PRBS_RX_INVERT : 0;
   7165             mask16 = PHY84834_USER_PRBS_RX_INVERT;
   7166         }
   7167         SOC_IF_ERROR_RETURN
   7168             (MODIFY_PHY8481_PHYXS_M_REG(unit, pc,
   7169                        PHY84834_USER_PRBS_CONTROL_0_REGISTER, data16, mask16) );
   7170     }
   7171     return SOC_E_NONE;
   7172 }
   7173 
   7174 STATIC int
   7175 _phy_84834_control_prbs_polynomial_set(int unit, soc_port_t port,
   7176                                        int poly_ctrl, int tx)   /* tx or rx */
   7177 {
   7178     phy_ctrl_t    *pc;       /* PHY software state */
   7179     uint16 data16;
   7180     uint16 mask16;
   7181 
   7182         /*
   7183          * poly_ctrl:
   7184          *  0x0 = prbs7
   7185          *  0x1 = prbs15
   7186          *  0x2 = prbs23
   7187          *  0x3 = prbs31
   7188          */
   7189     pc = EXT_PHY_SW_STATE(unit, port);
   7190 
   7191     /* 001 : prbs7 
   7192        010 : prbs9
   7193        011 : prbs11
   7194        100 : prbs15
   7195        101 : prbs23
   7196        110 : prbs31
   7197      */
   7198 
   7199     if ( PHY_IS_BCM8485X_AND_UP(pc) ) {
   7200         if ( PHY_IS_BCM8488X(pc) ) {
   7201             /* Turn on MDC clock for XFI */
   7202             SOC_IF_ERROR_RETURN(
   7203                 MODIFY_PHY8481_TOPLVL1_REG(unit, pc,
   7204                                 PHY8488X_MDIO_CLOCK_CONTROL_REGISTER,
   7205                                 PHY8488X_EN_CLK_MDC_XFI_MASK,
   7206                                 PHY8488X_EN_CLK_MDC_XFI_MASK) );
   7207         }
   7208 
   7209         /* Change XGP table to point to XFI */
   7210         SOC_IF_ERROR_RETURN
   7211             (WRITE_PHY8481_TOPLVL1_REG(unit, pc,
   7212                 PHY8485X_MDIO_CONTROL_REGISTER, 0x2004));
   7213 
   7214         if ( (poly_ctrl >= 0) && (poly_ctrl <= 6) ) {
   7215             data16 = poly_ctrl << 1;
   7216         } else {
   7217             return SOC_E_PARAM;     /* 8485x/6x/8x support polynominal 0-6 */
   7218         }
   7219 
   7220         if ( PHY_IS_BCM8488X_A0(pc) ) {
   7221             /* Orca A0 workaround: must use 32-bit addressing mode for PRBS */
   7222             uint32 reg32 = (tx) ? PHY848XX_TX_PRBS_ADDR32_REGISTER
   7223                                 : PHY848XX_RX_PRBS_ADDR32_REGISTER;
   7224             SOC_IF_ERROR_RETURN(
   7225                 _phy848xx_addr32_reg_write(unit, pc, reg32, data16) );
   7226         } else {
   7227             uint32  reg = (tx) ? PHY8485X_TX_PRBS_REGISTER
   7228                                : PHY8485X_RX_PRBS_REGISTER;
   7229             SOC_IF_ERROR_RETURN(
   7230                 WRITE_PHY8481_PMAD_REG(unit, pc, reg, data16) );
   7231         }
   7232     }
   7233     else {     /* 8483x / 8484x */
   7234         if (poly_ctrl == 0) {
   7235             data16 = 1;
   7236         } else if (poly_ctrl == 1) {
   7237             data16 = 4;
   7238         } else if (poly_ctrl == 2) {
   7239             data16 = 5;
   7240         } else if (poly_ctrl == 3) {
   7241             data16 = 6;
   7242         } else {
   7243             return SOC_E_PARAM;
   7244         } 
   7245         mask16 = PHY84834_USER_PRBS_TYPE_MASK;
   7246 
   7247         /* default is tx */
   7248         if (!tx) {  /* rx */
   7249             data16 = data16 << 12;
   7250             mask16 = mask16 << 12;
   7251         }
   7252 
   7253         /* both tx/rx types */
   7254         SOC_IF_ERROR_RETURN
   7255             (MODIFY_PHY8481_PHYXS_M_REG(unit, pc,
   7256                 PHY84834_USER_PRBS_CONTROL_0_REGISTER,
   7257                     data16, mask16));
   7258     }
   7259 
   7260     return SOC_E_NONE;
   7261 }
   7262 
   7263 STATIC int
   7264 _phy_84834_control_prbs_enable_set(int unit, soc_port_t port, int enable)
   7265 {
   7266     phy_ctrl_t    *pc;       /* PHY software state */
   7267 
   7268     pc = EXT_PHY_SW_STATE(unit, port);
   7269 
   7270     if ( PHY_IS_BCM8485X_AND_UP(pc) ) {
   7271         /* clear PRBS control if disabled */
   7272         if ( ! enable ) {       /* disable Tx/Rx PRBS */
   7273             if ( PHY_IS_BCM8488X_A0(pc) ) {
   7274                 /* Orca A0 workaround: must use 32-bit addressing mode for PRBS */
   7275                 SOC_IF_ERROR_RETURN(
   7276                     _phy848xx_addr32_reg_modify(unit, pc,
   7277                                 PHY848XX_TX_PRBS_ADDR32_REGISTER,
   7278                                 0,  PHY848XX_PRBS_ENABLE_MASK) );
   7279                 SOC_IF_ERROR_RETURN(
   7280                     _phy848xx_addr32_reg_modify(unit, pc,
   7281                                 PHY848XX_RX_PRBS_ADDR32_REGISTER,
   7282                                 0,  PHY848XX_PRBS_ENABLE_MASK) );
   7283             } else {
   7284                 SOC_IF_ERROR_RETURN
   7285                     (MODIFY_PHY8481_PMAD_REG(unit, pc,
   7286                         PHY8485X_TX_PRBS_REGISTER, 0, PHY8485X_USER_PRBS_TYPE_MASK));
   7287                 SOC_IF_ERROR_RETURN
   7288                     (MODIFY_PHY8481_PMAD_REG(unit, pc,
   7289                         PHY8485X_RX_PRBS_REGISTER, 0, PHY8485X_USER_PRBS_TYPE_MASK));
   7290             }
   7291             /* Restore XGP table to point to XFI */
   7292             SOC_IF_ERROR_RETURN
   7293                 (WRITE_PHY8481_TOPLVL1_REG(unit, pc,
   7294                     PHY8485X_MDIO_CONTROL_REGISTER, 0x3));
   7295             if ( PHY_IS_BCM8488X(pc) ) {
   7296             /* Turn off MDC clock for XFI */
   7297             SOC_IF_ERROR_RETURN(
   7298                 MODIFY_PHY8481_TOPLVL1_REG(unit, pc,
   7299                                 PHY8488X_MDIO_CLOCK_CONTROL_REGISTER,
   7300                                 0, PHY8488X_EN_CLK_MDC_XFI_MASK) );
   7301             }
   7302         } else {                /* enable PRBS generator/checker */
   7303             if ( PHY_IS_BCM8488X(pc) ) {
   7304             /* Turn on MDC clock for XFI */
   7305             SOC_IF_ERROR_RETURN(
   7306                 MODIFY_PHY8481_TOPLVL1_REG(unit, pc,
   7307                                 PHY8488X_MDIO_CLOCK_CONTROL_REGISTER,
   7308                                 PHY8488X_EN_CLK_MDC_XFI_MASK,
   7309                                 PHY8488X_EN_CLK_MDC_XFI_MASK) );
   7310             }
   7311             /* Change XGP table to point to XFI */
   7312             SOC_IF_ERROR_RETURN
   7313                 (WRITE_PHY8481_TOPLVL1_REG(unit, pc,
   7314                     PHY8485X_MDIO_CONTROL_REGISTER, 0x2004));
   7315 
   7316             if ( PHY_IS_BCM8488X_A0(pc) ) {
   7317                 /* Orca A0 workaround: must use 32-bit addressing mode for PRBS */
   7318                 SOC_IF_ERROR_RETURN(
   7319                     _phy848xx_addr32_reg_modify(unit, pc,
   7320                                 PHY848XX_TX_PRBS_ADDR32_REGISTER,
   7321                                 PHY848XX_PRBS_ENABLE_MASK,
   7322                                 PHY848XX_PRBS_ENABLE_MASK) );
   7323                 SOC_IF_ERROR_RETURN(
   7324                     _phy848xx_addr32_reg_modify(unit, pc,
   7325                                 PHY848XX_RX_PRBS_ADDR32_REGISTER,
   7326                                 PHY848XX_PRBS_ENABLE_MASK,
   7327                                 PHY848XX_PRBS_ENABLE_MASK) );
   7328             } else {
   7329                 SOC_IF_ERROR_RETURN
   7330                     (MODIFY_PHY8481_PMAD_REG(unit, pc,
   7331                         PHY8485X_TX_PRBS_REGISTER, 1, PHY8485X_USER_PRBS_TYPE_MASK));
   7332                 SOC_IF_ERROR_RETURN
   7333                     (MODIFY_PHY8481_PMAD_REG(unit, pc,
   7334                         PHY8485X_RX_PRBS_REGISTER, 1, PHY8485X_USER_PRBS_TYPE_MASK));
   7335             }
   7336         }
   7337     } else {
   7338         /* clear PRBS control if disabled */
   7339         if (!enable) {
   7340             SOC_IF_ERROR_RETURN
   7341                 (MODIFY_PHY8481_PHYXS_M_REG(unit, pc, 
   7342                     PHY84834_USER_PRBS_CONTROL_0_REGISTER, 0,
   7343                     PHY84834_USER_PRBS_TYPE_MASK |
   7344                     PHY84834_USER_PRBS_TYPE_MASK << 12)); /* rx type*/
   7345         } 
   7346 
   7347         /*  program the PRBS enable */
   7348         SOC_IF_ERROR_RETURN
   7349             (MODIFY_PHY8481_PHYXS_M_REG(unit, pc, 
   7350                 PHY84834_USER_PRBS_CONTROL_0_REGISTER, 
   7351                 enable? PHY84834_USER_PRBS_ENABLE: 0,PHY84834_USER_PRBS_ENABLE));
   7352     }
   7353 
   7354     return SOC_E_NONE;
   7355 }
   7356 
   7357 STATIC int
   7358 _phy_84834_control_prbs_enable_get(int unit, soc_port_t port, uint32 *value)
   7359 {
   7360     uint16 data16;
   7361     phy_ctrl_t    *pc;       /* PHY software state */
   7362 
   7363     pc = EXT_PHY_SW_STATE(unit, port);
   7364 
   7365     if (PHY_IS_BCM8485X_AND_UP(pc)) {
   7366         SOC_IF_ERROR_RETURN
   7367             (READ_PHY8481_PMAD_REG(unit, pc, 
   7368                 PHY8485X_TX_PRBS_REGISTER, &data16));
   7369         if (data16 & PHY8485X_USER_PRBS_TYPE_MASK) {
   7370             *value = TRUE;
   7371         } else {
   7372             *value = FALSE;
   7373         }
   7374     } else {
   7375         SOC_IF_ERROR_RETURN
   7376             (READ_PHY8481_PHYXS_M_REG(unit, pc, 
   7377                 PHY84834_USER_PRBS_CONTROL_0_REGISTER, &data16));
   7378         if (data16 & PHY84834_USER_PRBS_ENABLE) {
   7379             *value = TRUE;
   7380         } else {
   7381             *value = FALSE;
   7382         }
   7383     }
   7384 
   7385     return SOC_E_NONE;
   7386 }
   7387 
   7388 STATIC int
   7389 _phy_84834_control_prbs_polynomial_get(int unit, soc_port_t port, uint32 *value)
   7390 {
   7391     phy_ctrl_t    *pc;       /* PHY software state */
   7392     uint16 poly_ctrl;
   7393 
   7394     pc = EXT_PHY_SW_STATE(unit, port);
   7395 
   7396     if (PHY_IS_BCM8485X_AND_UP(pc)) {
   7397         SOC_IF_ERROR_RETURN
   7398             (READ_PHY8481_PMAD_REG(unit, pc,
   7399                 PHY8485X_TX_PRBS_REGISTER, &poly_ctrl));
   7400         *value = (poly_ctrl & 0xE) >> 1;
   7401     } else {
   7402         SOC_IF_ERROR_RETURN
   7403             (READ_PHY8481_PHYXS_M_REG(unit, pc, 
   7404                 PHY84834_USER_PRBS_CONTROL_0_REGISTER, &poly_ctrl));
   7405         poly_ctrl &= PHY84834_USER_PRBS_TYPE_MASK;
   7406 
   7407         if (poly_ctrl == 1) {
   7408             *value = 0;
   7409         } else if (poly_ctrl == 4) {
   7410             *value = 1;
   7411         } else if (poly_ctrl == 5) {
   7412             *value = 2;
   7413         } else if (poly_ctrl == 6) {
   7414             *value = 3;
   7415         } else {
   7416             *value = poly_ctrl;
   7417         }
   7418     }
   7419     return SOC_E_NONE;
   7420 }
   7421 
   7422 STATIC int
   7423 _phy_84834_control_prbs_tx_invert_data_get(int unit, soc_port_t port, uint32 *value)
   7424 {
   7425     phy_ctrl_t    *pc;       /* PHY software state */
   7426     uint16 data16;
   7427 
   7428     pc = EXT_PHY_SW_STATE(unit, port);
   7429 
   7430     if (PHY_IS_BCM8485X_AND_UP(pc)) {
   7431         *value = FALSE;
   7432         return SOC_E_UNAVAIL;
   7433     }
   7434 
   7435     SOC_IF_ERROR_RETURN
   7436         (READ_PHY8481_PHYXS_M_REG(unit, pc, 
   7437                   PHY84834_USER_PRBS_CONTROL_0_REGISTER, &data16));
   7438     if (data16 & PHY84834_USER_PRBS_TX_INVERT) {
   7439         *value = TRUE;
   7440     } else {
   7441         *value = FALSE;
   7442     }
   7443     return SOC_E_NONE;
   7444 }
   7445 
   7446 STATIC int
   7447 _phy_84834_control_prbs_rx_status_get(int unit, soc_port_t port, uint32 *value)
   7448 {
   7449     phy_ctrl_t    *pc;       /* PHY software state */
   7450     uint16        data16;
   7451     uint16        err_cnt_low, err_cnt_high;
   7452     uint32        err_cnt = 0;
   7453 
   7454     pc = EXT_PHY_SW_STATE(unit, port);
   7455 
   7456     if (PHY_IS_BCM8485X_AND_UP(pc)) {
   7457         /* Read register 0xD0D9 twice */
   7458         SOC_IF_ERROR_RETURN
   7459             (READ_PHY8481_PMAD_REG(unit, pc,
   7460                 PHY8485X_PRBS_STATUS_REGISTER, &data16));
   7461         SOC_IF_ERROR_RETURN
   7462             (READ_PHY8481_PMAD_REG(unit, pc,
   7463                 PHY8485X_PRBS_STATUS_REGISTER, &data16));
   7464 
   7465         /* Read error count register twice */
   7466         SOC_IF_ERROR_RETURN
   7467             (READ_PHY8481_PMAD_REG(unit, pc,
   7468                 PHY8485X_PRBS_ERR_COUNT_LSB_REGSTER, &err_cnt_low));
   7469         SOC_IF_ERROR_RETURN
   7470             (READ_PHY8481_PMAD_REG(unit, pc,
   7471                 PHY8485X_PRBS_ERR_COUNT_LSB_REGSTER, &err_cnt_low));
   7472         SOC_IF_ERROR_RETURN
   7473             (READ_PHY8481_PMAD_REG(unit, pc,
   7474                 PHY8485X_PRBS_ERR_COUNT_MSB_REGSTER, &err_cnt_high));
   7475         SOC_IF_ERROR_RETURN
   7476             (READ_PHY8481_PMAD_REG(unit, pc,
   7477                 PHY8485X_PRBS_ERR_COUNT_MSB_REGSTER, &err_cnt_high));
   7478 
   7479         err_cnt = (err_cnt_high << 16) |  err_cnt_low;
   7480 
   7481         if ((!err_cnt) && (data16 & 0x1)) {
   7482             *value = 0;
   7483         } else if (err_cnt) {
   7484             *value = err_cnt;
   7485         } else {
   7486             *value = -1;
   7487         }
   7488     } else {
   7489         *value = 0;
   7490         SOC_IF_ERROR_RETURN
   7491             (READ_PHY8481_PHYXS_M_REG(unit, pc, 
   7492                                       PHY84834_USER_PRBS_STATUS_0_REGISTER, &data16));
   7493         if (data16 == 0x8000) { /* PRBS lock and error free */
   7494             *value = 0;
   7495         } else if (!(data16 & 0x8000)) {
   7496             *value = -1;
   7497         } else {
   7498             *value = data16 & 0x7fff;
   7499         }
   7500     }
   7501 
   7502     return SOC_E_NONE;
   7503 }
   7504 
   7505 
   7506 STATIC int
   7507 _phy_84834_remote_loopback_set(int unit, soc_port_t port,int intf,uint32 enable)
   7508 {
   7509     phy_ctrl_t    *pc;       /* PHY software state */
   7510     
   7511     pc = EXT_PHY_SW_STATE(unit, port);
   7512 
   7513     if (intf == PHY_DIAG_INTF_SYS) {
   7514         SOC_IF_ERROR_RETURN
   7515                (MODIFY_PHY8481_PHYXS_M_REG(unit,pc, 0x0000,
   7516                enable ? (1<<14):0, (1<<14)));
   7517     }
   7518     return SOC_E_NONE;
   7519 }
   7520 
   7521 
   7522 /*
   7523  * Function:
   7524  *      phy_84834_control_set
   7525  * Purpose:
   7526  *      Configure PHY device specific control fucntion.
   7527  * Parameters:
   7528  *      unit  - StrataSwitch unit #.
   7529  *      port  - StrataSwitch port #.
   7530  *      type  - Control to update
   7531  *      value - New setting for the control
   7532  * Returns:
   7533  *      SOC_E_NONE
   7534  */
   7535 STATIC int
   7536 _phy_84834_control_set(int unit, soc_port_t port, int intf,int lane,
   7537                      soc_phy_control_t type, uint32 value)
   7538 {
   7539 #if 0
   7540     phy_ctrl_t    *pc;       /* PHY software state */
   7541 #endif
   7542     int rv;
   7543 
   7544 #if 0
   7545     pc = EXT_PHY_SW_STATE(unit, port);
   7546 #endif
   7547 
   7548     PHY_CONTROL_TYPE_CHECK(type);
   7549 
   7550     rv = SOC_E_UNAVAIL;
   7551 #if 0
   7552     if (intf == PHY_DIAG_INTF_SYS) {
   7553         /* if is targeted to the system side */
   7554         SOC_IF_ERROR_RETURN
   7555             (PHY84740_XFI(unit,pc));
   7556     }
   7557 #endif
   7558     switch(type) {
   7559     case SOC_PHY_CONTROL_PREEMPHASIS:
   7560         /* fall through */
   7561     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   7562         /* fall through */
   7563     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   7564         rv = _phy_8481_control_tx_driver_set(unit, port, type, value);
   7565         break;
   7566 #if 0
   7567     case SOC_PHY_CONTROL_EDC_MODE:
   7568         rv = _phy_84740_control_edc_mode_set(unit,port,value);
   7569         break;
   7570     case SOC_PHY_CONTROL_CLOCK_ENABLE:
   7571         rv = _phy_84740_control_recovery_clock_set(unit,port,value);
   7572         break;
   7573     case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
   7574         rv = _phy_84740_control_recovery_clock_freq_set(unit,port,value);
   7575         break;
   7576 #endif
   7577     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   7578         if (intf != PHY_DIAG_INTF_SYS) {
   7579             /* PRBS line side not supported */
   7580             rv = SOC_E_UNAVAIL;
   7581         }
   7582         else {
   7583             /* on line side, rx poly type is auto-detected. On system side,
   7584              * need to enable the rx type as well.
   7585              */
   7586             rv = _phy_84834_control_prbs_polynomial_set(unit, port, value, TRUE);
   7587             if (intf == PHY_DIAG_INTF_SYS) {
   7588                 rv = _phy_84834_control_prbs_polynomial_set(unit, port,value,FALSE);
   7589             }
   7590         }
   7591         break;
   7592     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   7593         /* on line side, rx invertion is auto-detected. On system side,
   7594          * need to enable the rx as well.
   7595          */
   7596         rv = _phy_84834_control_prbs_invert_data_set(unit, port, 2, value);
   7597         if (intf == PHY_DIAG_INTF_SYS) {
   7598             rv |= _phy_84834_control_prbs_invert_data_set(unit, port, 1, value);
   7599         }
   7600         break;
   7601     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   7602         /* fall through */
   7603     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   7604         /* tx/rx is enabled at the same time. no seperate control */
   7605         rv = _phy_84834_control_prbs_enable_set(unit, port, value);
   7606         break;
   7607     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   7608         rv = _phy_84834_remote_loopback_set(unit, port,PHY_DIAG_INTF_SYS,value);
   7609         break;
   7610     default:
   7611         rv = SOC_E_UNAVAIL;
   7612         break;
   7613     }
   7614 #if 0
   7615     if (intf == PHY_DIAG_INTF_SYS) {
   7616         /* if it is targeted to the system side, switch back */
   7617         SOC_IF_ERROR_RETURN
   7618             (PHY84740_MMF(unit,pc));
   7619     }
   7620 #endif
   7621     return rv;
   7622 }
   7623 
   7624 /*
   7625  * Function:
   7626  *      phy_84834_control_get
   7627  * Purpose:
   7628  *      Get current control settign of the PHY.
   7629  * Parameters:
   7630  *      unit  - StrataSwitch unit #.
   7631  *      port  - StrataSwitch port #.
   7632  *      type  - Control to update
   7633  *      value - (OUT)Current setting for the control
   7634  * Returns:
   7635  *      SOC_E_NONE
   7636  */
   7637 STATIC int
   7638 _phy_84834_control_get(int unit, soc_port_t port, int intf,int lane,
   7639                      soc_phy_control_t type, uint32 *value)
   7640 {
   7641 #if 0
   7642     phy_ctrl_t    *pc;       /* PHY software state */
   7643 #endif
   7644     int rv;
   7645 /*    uint16 data16; */
   7646 
   7647 #if 0
   7648     pc = EXT_PHY_SW_STATE(unit, port);
   7649 #endif
   7650 
   7651     PHY_CONTROL_TYPE_CHECK(type);
   7652 
   7653 #if 0
   7654     if (intf == PHY_DIAG_INTF_SYS) {
   7655         /* targeted to the system side */
   7656         SOC_IF_ERROR_RETURN
   7657             (PHY84740_XFI(unit,pc));
   7658     }
   7659 #endif
   7660     rv = SOC_E_UNAVAIL;
   7661     switch(type) {
   7662     case SOC_PHY_CONTROL_PREEMPHASIS:
   7663         /* fall through */
   7664     case SOC_PHY_CONTROL_DRIVER_CURRENT:
   7665         /* fall through */
   7666     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
   7667         rv = _phy_8481_control_tx_driver_get(unit, port, type, value);
   7668         break;
   7669 #if 0
   7670     case SOC_PHY_CONTROL_EDC_MODE:
   7671         rv = _phy_84740_control_edc_mode_get(unit,port,value);
   7672         break;
   7673     case SOC_PHY_CONTROL_CLOCK_ENABLE:
   7674         SOC_IF_ERROR_RETURN
   7675            (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_REG, 
   7676                                           &data16));
   7677         *value = (data16 & PHY84740_RECOVERY_CLK_ENABLE_MASK)? TRUE: FALSE; 
   7678         rv = SOC_E_NONE;
   7679         break;
   7680 #endif
   7681     case SOC_PHY_CONTROL_PRBS_POLYNOMIAL:
   7682         if (intf == PHY_DIAG_INTF_SYS) {
   7683             rv = _phy_84834_control_prbs_polynomial_get(unit, port, value);
   7684         }
   7685         else { /* PRBS line side not supported */
   7686             rv = SOC_E_UNAVAIL;
   7687         }
   7688         break;
   7689     case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA:
   7690         rv = _phy_84834_control_prbs_tx_invert_data_get(unit, port, value);
   7691         break;
   7692     case SOC_PHY_CONTROL_PRBS_TX_ENABLE:
   7693         /* fall through */
   7694     case SOC_PHY_CONTROL_PRBS_RX_ENABLE:
   7695         rv = _phy_84834_control_prbs_enable_get(unit, port, value);
   7696         break;
   7697     case SOC_PHY_CONTROL_PRBS_RX_STATUS:
   7698         rv = _phy_84834_control_prbs_rx_status_get(unit, port, value);
   7699         break;
   7700 #if 0
   7701     case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
   7702         SOC_IF_ERROR_RETURN
   7703             (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, 
   7704                    &data16));
   7705         switch ((data16 >> PHY84740_RECOVERY_CLK_FREQ_SHIFT) & 0x3) {
   7706             case 0x1:
   7707                 *value = 125000;
   7708                 break;
   7709             case 0x2:
   7710                 *value = 195312;
   7711                 break;
   7712             case 0x3:
   7713                 *value = 156250;
   7714                 break;
   7715             default:
   7716                 *value = 0x0;
   7717                 break;
   7718         }
   7719         rv = SOC_E_NONE;
   7720         break;
   7721 #endif
   7722 
   7723     default:
   7724         rv = SOC_E_UNAVAIL;
   7725         break;
   7726     }
   7727 
   7728 #if 0
   7729     if (intf == PHY_DIAG_INTF_SYS) {
   7730         /* if it is targeted to the system side, switch back */
   7731         SOC_IF_ERROR_RETURN
   7732             (PHY84740_MMF(unit,pc));
   7733     }
   7734 #endif
   7735     return rv;
   7736 }
   7737 
   7738 
   7739 #ifdef BCM848XX_STATE_MFG_DIAG_SUPPORT
   7740 
   7741 STATIC int
   7742 _phy_8481_mfg_test_fw_ready(int unit, phy_ctrl_t *pc, uint16 val, uint16 mask)
   7743 {
   7744     int     rv;
   7745     uint16  status;
   7746 
   7747     soc_timeout_init(&TO(pc), 25000000, 0);
   7748     do {
   7749         sal_usleep(50000);
   7750         rv = READ_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, &status);
   7751         if ( SOC_FAILURE(rv) ) {
   7752             break;    /* failed to read register */
   7753         }
   7754 
   7755         if ( (status & mask) == val ) {
   7756             return SOC_E_NONE;      /* status check OK */
   7757         }
   7758     } while ( ! soc_timeout_check(&TO(pc)) );
   7759 
   7760     /* register read or status check failed */
   7761     LOG_WARN(BSL_LS_SOC_PHY,
   7762              (BSL_META_U(unit,
   7763                          "PHY848X manufacturing diagnostics failed: unit=%d port=%d\n"),
   7764               unit, pc->port));
   7765     return SOC_E_FAIL;
   7766 }
   7767 
   7768 STATIC int
   7769 _phy_8481_mfg_test_set(int unit, soc_port_t port, int op_cmd, int arg)
   7770 {
   7771     phy_ctrl_t    *pc;
   7772 
   7773     pc = EXT_PHY_SW_STATE(unit, port);
   7774     if ( ! (FLAGS(pc) & PHY8483X_MFG_TEST_SUPPORT) ) {
   7775         return SOC_E_UNAVAIL;
   7776     }
   7777 
   7778     switch ( op_cmd ) {
   7779     case PHY_DIAG_CTRL_MFG_HYB_CANC:
   7780     case PHY_DIAG_CTRL_MFG_DENC:
   7781         SOC_IF_ERROR_RETURN            /* MFG Test init */
   7782             (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, 0xf003));
   7783         break;
   7784 
   7785     case PHY_DIAG_CTRL_MFG_TX_ON:
   7786         SOC_IF_ERROR_RETURN
   7787             (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, (((arg & 0xf) << 12) | 0x3)));
   7788         break;
   7789 
   7790     case PHY_DIAG_CTRL_MFG_EXIT:
   7791         SOC_IF_ERROR_RETURN
   7792             (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, 0x7));
   7793         return SOC_E_NONE;
   7794 
   7795     default:
   7796         return SOC_E_UNAVAIL;
   7797     }
   7798     
   7799     if(!(PHY_IS_BCM8485X_AND_UP(pc))) {
   7800         SOC_IF_ERROR_RETURN
   7801             (MODIFY_PHY8481_PMD_IEEE_TST_MODE_10G_REG(unit, pc, (0x5 << 13), (0x7 << 13)));
   7802     } else {
   7803         SOC_IF_ERROR_RETURN
   7804             (MODIFY_PHY8481_PMD_IEEE_TST_MODE_10G_REG(unit, pc, (0x1 << 13), (0x7 << 13)));
   7805     }
   7806     /* MFG Test init done. PHYC_CTL_SPARE_GRP5_REG should be reset to 0xF000 */
   7807     SOC_IF_ERROR_RETURN
   7808         (_phy_8481_mfg_test_fw_ready(unit, pc, 0xf000, 0xffff));
   7809 
   7810     LOG_WARN(BSL_LS_SOC_PHY,
   7811              (BSL_META_U(unit,
   7812                          "PHY848X manufacturing diagnostics init: unit=%d port=%d\n"), unit, port));
   7813 
   7814     return SOC_E_NONE;
   7815 }
   7816 #endif  /* BCM848XX_STATE_MFG_DIAG_SUPPORT */
   7817 
   7818 #ifdef PHY8185X_DEBUG_CMD_HANDLER
   7819 STATIC int
   7820 _phy_8585x_generic_command_handler_test_get(int unit, phy_ctrl_t *pc)
   7821 {
   7822     uint16 status;
   7823 
   7824     _phy8485x_emi_mode_enable_get(unit, pc, &status);
   7825     _phy8485x_sub_lf_rf_status_get(unit, pc, &status);
   7826     _phy8485x_snr_get(unit, pc);
   7827     _phy8485x_current_temp_get(unit, pc);
   7828     return SOC_E_NONE;
   7829 }
   7830 
   7831 STATIC int
   7832 _phy_8585x_generic_command_handler_test_set(int unit, phy_ctrl_t *pc)
   7833 {
   7834     uint16 status = 1;
   7835 
   7836     _phy8485x_emi_mode_enable_set(unit, pc, status);
   7837 
   7838     return SOC_E_NONE;
   7839 }
   7840 #endif
   7841 
   7842 #ifdef BCM848XX_STATE_MFG_DIAG_SUPPORT
   7843 STATIC int
   7844 _phy_8481_mfg_test_get(int unit, soc_port_t port, int op_cmd, uint32 arg[])
   7845 {
   7846     phy_ctrl_t *pc;
   7847     uint16 status;
   7848     int requested_cmd, data_len;
   7849 
   7850     pc = EXT_PHY_SW_STATE(unit, port);
   7851     if ( ! (FLAGS(pc) & PHY8483X_MFG_TEST_SUPPORT) ) {
   7852         return SOC_E_UNAVAIL;
   7853     }
   7854 
   7855     switch ( op_cmd ) {
   7856     case PHY_DIAG_CTRL_MFG_HYB_CANC:
   7857        SOC_IF_ERROR_RETURN
   7858             (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, 0x1));
   7859         break;
   7860     case PHY_DIAG_CTRL_MFG_DENC:
   7861         SOC_IF_ERROR_RETURN
   7862             (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, 0x2));
   7863         break;
   7864 
   7865     case PHY_DIAG_CTRL_MFG_TX_ON:
   7866         break;
   7867     case PHY_DIAG_CTRL_MFG_EXIT:
   7868         return SOC_E_NONE;
   7869     default:
   7870         return SOC_E_UNAVAIL;
   7871     }
   7872 
   7873     /* MFG Test done. PHYC_CTL_SPARE_GRP5_REG[2:0] should be reset to 000 */
   7874     SOC_IF_ERROR_RETURN
   7875         (_phy_8481_mfg_test_fw_ready(unit, pc, 0x0, 0x0007));
   7876 
   7877     switch (op_cmd) {
   7878     case PHY_DIAG_CTRL_MFG_HYB_CANC:
   7879         requested_cmd = 0x1;
   7880         data_len = 770*4;
   7881         break;
   7882     case PHY_DIAG_CTRL_MFG_DENC:
   7883         requested_cmd = 0x2;
   7884         data_len = 44*4;
   7885         break;
   7886     case PHY_DIAG_CTRL_MFG_TX_ON:
   7887         requested_cmd = 0x3;
   7888         data_len = 0;
   7889         break;
   7890     /*
   7891      * COVERITY
   7892      *
   7893      * This default is unreachable. It is kept intentionally as a defensive default for future development.
   7894      */
   7895     /* coverity[dead_error_begin]  */
   7896     default:
   7897         return SOC_E_UNAVAIL;
   7898     }
   7899 
   7900     /* ACK from FW, should be identical to MFG_CMD in PHYC_CTL_SPARE_GRP5[2:0] */
   7901     SOC_IF_ERROR_RETURN
   7902         (READ_PHY8481_PHYC_CTL_SPARE_GRP6_REG(unit, pc, &status));
   7903     if ( (status & 0x7) != requested_cmd ) {
   7904         LOG_WARN(BSL_LS_SOC_PHY,
   7905                  (BSL_META_U(unit,
   7906                              "PHY848X manufacturing diagnostics command mismatch: u=%d p=%d\n"), unit, port));
   7907         return SOC_E_FAIL;
   7908     }
   7909 
   7910     if ( data_len ) {
   7911         uint32 addr;
   7912         SOC_IF_ERROR_RETURN
   7913             (_phy_8481_mdio2arm_read(unit, port, 0xc300003c, &addr, 1));
   7914         SOC_IF_ERROR_RETURN
   7915             (_phy_8481_read_from_arm(unit, pc, soc_ntohl_load(&addr), (uint8*)arg, data_len));
   7916     }
   7917 
   7918     /* Turn off the transmission */
   7919     SOC_IF_ERROR_RETURN
   7920         (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, 0xf003));
   7921     SOC_IF_ERROR_RETURN    /*  and wait for the operation done */
   7922         (_phy_8481_mfg_test_fw_ready(unit, pc, 0xf000, 0xffff));
   7923 
   7924     LOG_WARN(BSL_LS_SOC_PHY,
   7925              (BSL_META_U(unit,
   7926                          "PHY848X manufacturing diagnostics OK: unit=%d port=%d\n"), unit, port));
   7927 
   7928     return SOC_E_NONE;
   7929 }
   7930 
   7931 STATIC int
   7932 _phy_8481_diag_dsc_get(phy_ctrl_t *pc)
   7933 {
   7934 #ifdef BCM848XX_DIAG_DSC_SUPPORT
   7935     if ( PHY_IS_BCM8488X(pc) ) {
   7936         set_intpc(pc);
   7937         get_dsc_param_orca();
   7938     } else {
   7939         set_pc(pc);
   7940         get_dsc_param_koi();
   7941     }
   7942 #else
   7943     LOG_CLI((BSL_META_U(pc->unit, "*** Diag DSC not supported: "
   7944                                   "unit=%d port=%d\n"), pc->unit, pc->port));
   7945 #endif
   7946 
   7947     return SOC_E_NONE;
   7948 }
   7949 
   7950 STATIC int
   7951 _phy_8481_state_test_set(int unit, soc_port_t port, int op_cmd, int arg)
   7952 {
   7953     phy_ctrl_t    *pc;
   7954     uint16 status;
   7955     int rv;
   7956 
   7957     pc = EXT_PHY_SW_STATE(unit, port);
   7958 
   7959     if (!(FLAGS(pc) & PHY8483X_STATE_TEST_SUPPORT)) {
   7960         return SOC_E_UNAVAIL;
   7961     }
   7962     switch (op_cmd) {
   7963     case PHY_DIAG_CTRL_STATE_TRACE1:
   7964         break;
   7965     case PHY_DIAG_CTRL_STATE_TRACE2:
   7966         break;
   7967     case PHY_DIAG_CTRL_STATE_WHEREAMI:
   7968     case PHY_DIAG_CTRL_STATE_TEMP:
   7969         soc_timeout_init(&TO(pc), 7000000, 0);
   7970         do {
   7971             rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status);
   7972             if (PHY8481_IS_READY_FOR_CMD(pc, status) || SOC_FAILURE(rv)) {
   7973                 break;
   7974             }
   7975         } while (!soc_timeout_check(&TO(pc)));
   7976 
   7977         if (!PHY8481_IS_OPEN_FOR_CMD(pc, status)) {
   7978             LOG_CLI((BSL_META_U(unit,
   7979                                 "_phy_8481_state_test_set not ready u=%d "
   7980                                 "p=%d status=%04x\n"),
   7981                      unit, pc->port, status));
   7982             return SOC_E_FAIL;
   7983         }
   7984         SOC_IF_ERROR_RETURN
   7985             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, (op_cmd ==  PHY_DIAG_CTRL_STATE_WHEREAMI) ?
   7986              PHY84834_DIAG_CMD_GET_SNR_V2 : PHY84834_DIAG_CMD_GET_CURRENT_TEMP_V2));
   7987 
   7988         soc_timeout_init(&TO(pc), 1000000, 0);
   7989         break;
   7990     case PHY_DIAG_CTRL_STATE_GENERIC:
   7991 #ifdef PHY8185X_DEBUG_CMD_HANDLER
   7992         if (PHY_IS_BCM8485X_AND_UP(pc)) {
   7993             _phy_8585x_generic_command_handler_test_set(unit, pc);
   7994         } else {
   7995             return SOC_E_NONE;
   7996         }
   7997 #endif
   7998         break;
   7999     default:
   8000         return SOC_E_UNAVAIL;
   8001     }
   8002 
   8003     return SOC_E_NONE;
   8004 }
   8005 
   8006 STATIC int
   8007 _phy_8481_state_test_get(int unit, soc_port_t port, int op_cmd, uint32 arg[])
   8008 {
   8009     phy_ctrl_t *pc;
   8010     uint32 addr = 0;
   8011     int len = 0, rv;
   8012     XGPHY_DIAG_DATA_t *data = (XGPHY_DIAG_DATA_t *) arg; 
   8013     uint16 temp0, temp1, status;
   8014 
   8015     pc = EXT_PHY_SW_STATE(unit, port);
   8016 
   8017     if (!(FLAGS(pc) & PHY8483X_STATE_TEST_SUPPORT)) {
   8018         return SOC_E_UNAVAIL;
   8019     }
   8020 
   8021     switch (op_cmd) {
   8022     case PHY_DIAG_CTRL_STATE_TRACE1:
   8023         addr = 0x50800;
   8024         len = 2048*4;
   8025         break;
   8026     case PHY_DIAG_CTRL_STATE_TRACE2:
   8027         addr = 0x53000;
   8028         len = 1024*4;
   8029         break;
   8030     case PHY_DIAG_CTRL_STATE_WHEREAMI:
   8031     case PHY_DIAG_CTRL_STATE_TEMP:
   8032         do {
   8033             rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status);
   8034             if (PHY8481_IS_CMD_COMPLETE(pc, status) || SOC_FAILURE(rv)) {
   8035                 break;
   8036             }
   8037         } while (!soc_timeout_check(&TO(pc)));
   8038         if (PHY_IS_BCM8483X(pc) || PHY_IS_BCM8484X(pc)) {
   8039         SOC_IF_ERROR_RETURN
   8040             (WRITE_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE));
   8041         }
   8042         if ((status & PHY84834_CMD_COMPLETE_PASS) == 0) {
   8043             LOG_CLI((BSL_META_U(unit,
   8044                                 "_phy_8481_state_test_get failed: u=%d p=%d "
   8045                                 "status=%04x\n"), unit, pc->port, status));
   8046             return SOC_E_FAIL;
   8047         }
   8048         break;
   8049     case PHY_DIAG_CTRL_STATE_GENERIC:
   8050 #ifdef PHY8185X_DEBUG_CMD_HANDLER 
   8051         if (PHY_IS_BCM8485X_AND_UP(pc)) {
   8052             _phy_8585x_generic_command_handler_test_get(unit, pc);
   8053         } else {
   8054         return SOC_E_NONE;
   8055         }
   8056 #endif
   8057         break;
   8058     default:
   8059         return SOC_E_UNAVAIL;
   8060     }
   8061 
   8062     if (op_cmd == PHY_DIAG_CTRL_STATE_WHEREAMI) {
   8063         if (PHY_IS_BCM8485X_AND_UP(pc)) { 
   8064             sal_memset(data->snr_block, 0, sizeof(data->snr_block));
   8065 
   8066             SOC_IF_ERROR_RETURN
   8067                 (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &temp1)); /* DATA2 */
   8068             soc_htolel_store(&data->snr_block[16], temp1);
   8069             soc_htolel_store(&data->snr_block[0], temp1);    /* SNR OK */
   8070 
   8071             SOC_IF_ERROR_RETURN
   8072                 (READ_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, &temp1)); /* DATA3 */
   8073             soc_htolel_store(&data->snr_block[20], temp1);
   8074             soc_htolel_store(&data->snr_block[4], temp1);    /* SNR OK */
   8075 
   8076             SOC_IF_ERROR_RETURN
   8077                 (READ_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, &temp1)); /* DATA4 */
   8078             soc_htolel_store(&data->snr_block[24], temp1);
   8079             soc_htolel_store(&data->snr_block[8], temp1);    /* SNR OK */
   8080 
   8081             SOC_IF_ERROR_RETURN
   8082                 (READ_PHY84834_TOP_CONFIG_SCRATCH_31r(unit, pc, &temp1)); /* DATA5 */
   8083             soc_htolel_store(&data->snr_block[28], temp1);
   8084             soc_htolel_store(&data->snr_block[12], temp1);    /* SNR OK */
   8085 
   8086             data->serr = data->cerr = data->block_lock = data->block_point_id = 0;
   8087             data->flags = FLAGS(pc) & PHY8483X_FULL_SNR_SUPPORT ? PHY_DIAG_FULL_SNR_SUPPORT : 0;
   8088         } else {
   8089             /*
   8090             SOC_IF_ERROR_RETURN
   8091                 (READ_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, &dr1));
   8092              */
   8093             SOC_IF_ERROR_RETURN
   8094                 (READ_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, &temp1)); /* DATA3 */
   8095             SOC_IF_ERROR_RETURN
   8096                 (READ_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, &temp0)); /* DATA4 */
   8097 
   8098             SOC_IF_ERROR_RETURN
   8099                 (_phy_8481_read_from_arm(unit, pc, ((uint32)temp1) << 16 | temp0,
   8100                data->snr_block, (FLAGS(pc) & PHY8483X_FULL_SNR_SUPPORT) ? sizeof(data->snr_block) : 16));
   8101 
   8102             temp1 = soc_letohl_load(&data->snr_block[16]) - 32768;
   8103             soc_htolel_store(&data->snr_block[16], temp1);
   8104             temp1 = soc_letohl_load(&data->snr_block[20]) - 32768;
   8105             soc_htolel_store(&data->snr_block[20], temp1);
   8106             temp1 = soc_letohl_load(&data->snr_block[24]) - 32768;
   8107             soc_htolel_store(&data->snr_block[24], temp1);
   8108             temp1 = soc_letohl_load(&data->snr_block[28]) - 32768;
   8109             soc_htolel_store(&data->snr_block[28], temp1);
   8110 
   8111             SOC_IF_ERROR_RETURN
   8112                 (READ_PHY8481_PMAD_REG(unit, pc, 0xb089,&temp0));
   8113             SOC_IF_ERROR_RETURN
   8114                 (READ_PHY8481_PMAD_REG(unit, pc, 0xb08a,&temp1));
   8115             data->serr = ((uint32)temp1) << 16 | temp0;
   8116 
   8117             SOC_IF_ERROR_RETURN
   8118                 (READ_PHY8481_PMAD_REG(unit, pc, 0xb08b,&temp0));
   8119             SOC_IF_ERROR_RETURN
   8120                 (READ_PHY8481_PMAD_REG(unit, pc, 0xb08c,&temp1));
   8121             data->cerr = ((uint32)temp1) << 16 | temp0;
   8122 
   8123             SOC_IF_ERROR_RETURN
   8124                 (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x405c,&temp0));
   8125             SOC_IF_ERROR_RETURN
   8126                 (READ_PHY8481_PCS_REG(unit, pc, 0x21, &temp1));
   8127             SOC_IF_ERROR_RETURN
   8128                 (READ_PHY8481_PCS_REG(unit, pc, 0x21, &temp1)); /* read twice to clear latch */
   8129             data->block_point_id = temp0;
   8130             data->block_lock = (temp1 >> 15) & 0x1;
   8131 
   8132             data->flags = FLAGS(pc) & PHY8483X_FULL_SNR_SUPPORT ? PHY_DIAG_FULL_SNR_SUPPORT : 0; 
   8133         }
   8134 
   8135     } else if (op_cmd == PHY_DIAG_CTRL_STATE_TEMP) {
   8136         SOC_IF_ERROR_RETURN
   8137             (READ_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, &data->digital_temp)); /* DATA1 */
   8138         SOC_IF_ERROR_RETURN
   8139             (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &data->analog_temp)); /* DATA2 */
   8140     } else {
   8141        SOC_IF_ERROR_RETURN
   8142             (_phy_8481_read_from_arm(unit, pc, addr, (uint8 *)arg, len));
   8143     }
   8144 
   8145     return SOC_E_NONE;
   8146 }
   8147 #endif  /* BCM848XX_STATE_MFG_DIAG_SUPPORT */
   8148 
   8149 STATIC int
   8150 phy_8481_diag_ctrl(
   8151    int unit, /* unit */
   8152    soc_port_t port, /* port */
   8153    uint32 inst, /* the specific device block the control action directs to */
   8154    int op_type,  /* operation types: read,write or command sequence */
   8155    int op_cmd,   /* command code */
   8156    void *arg)     /* command argument  */
   8157 {
   8158 #ifdef BCM848XX_STATE_MFG_DIAG_SUPPORT
   8159     int lane;
   8160     int intf;
   8161     phy_ctrl_t    *pc;
   8162 
   8163     pc = EXT_PHY_SW_STATE(unit, port);
   8164 
   8165     LOG_INFO(BSL_LS_SOC_PHY,
   8166              (BSL_META_U(unit,
   8167                          "phy_8481_diag_ctrl: u=%d p=%d ctrl=0x%x\n"),
   8168                          unit, port,op_cmd));
   8169 
   8170     lane = PHY_DIAG_INST_LN(inst);
   8171     intf = PHY_DIAG_INST_INTF(inst);
   8172     if (intf == PHY_DIAG_INTF_DFLT) {
   8173         intf = PHY_DIAG_INTF_LINE;
   8174     }
   8175 
   8176     if (op_type == PHY_DIAG_CTRL_GET) {
   8177         switch (op_cmd) {
   8178         case PHY_DIAG_CTRL_MFG_HYB_CANC:
   8179         case PHY_DIAG_CTRL_MFG_DENC:
   8180         case PHY_DIAG_CTRL_MFG_TX_ON:
   8181         case PHY_DIAG_CTRL_MFG_EXIT:
   8182         SOC_IF_ERROR_RETURN
   8183             (_phy_8481_mfg_test_get(unit, port,
   8184                   op_cmd,(uint32 *)arg));
   8185             break;
   8186         case PHY_DIAG_CTRL_STATE_TRACE1:
   8187         case PHY_DIAG_CTRL_STATE_TRACE2:
   8188         case PHY_DIAG_CTRL_STATE_WHEREAMI:
   8189         case PHY_DIAG_CTRL_STATE_TEMP:
   8190         case PHY_DIAG_CTRL_STATE_GENERIC:
   8191         SOC_IF_ERROR_RETURN
   8192             (_phy_8481_state_test_get(unit, port,
   8193                   op_cmd,(uint32 *)arg));
   8194             break;
   8195         default:
   8196         SOC_IF_ERROR_RETURN
   8197             (_phy_84834_control_get(unit, port, intf, lane,
   8198                   op_cmd,(uint32 *)arg));
   8199             break;
   8200         }
   8201     } else if (op_type == PHY_DIAG_CTRL_SET) {
   8202         switch (op_cmd) {
   8203         case PHY_DIAG_CTRL_MFG_HYB_CANC:
   8204         case PHY_DIAG_CTRL_MFG_DENC:
   8205         case PHY_DIAG_CTRL_MFG_TX_ON:
   8206         case PHY_DIAG_CTRL_MFG_EXIT:
   8207         SOC_IF_ERROR_RETURN
   8208             (_phy_8481_mfg_test_set(unit, port,
   8209                   op_cmd, PTR_TO_INT(arg)));
   8210             break;
   8211         case PHY_DIAG_CTRL_STATE_TRACE1:
   8212         case PHY_DIAG_CTRL_STATE_TRACE2:
   8213         case PHY_DIAG_CTRL_STATE_WHEREAMI:
   8214         case PHY_DIAG_CTRL_STATE_TEMP:
   8215         case PHY_DIAG_CTRL_STATE_GENERIC:
   8216         SOC_IF_ERROR_RETURN
   8217             (_phy_8481_state_test_set(unit, port,
   8218                   op_cmd, PTR_TO_INT(arg)));
   8219             break;
   8220         default:
   8221         SOC_IF_ERROR_RETURN
   8222             (_phy_84834_control_set(unit, port, intf, lane,
   8223                   op_cmd, PTR_TO_INT(arg)));
   8224             break;
   8225         }
   8226     } else if (op_type == PHY_DIAG_CTRL_CMD) {
   8227         switch (op_cmd) {
   8228         case PHY_DIAG_CTRL_DSC:
   8229             /* Diag DSC supported on system side of BCM8485X  */
   8230             if (PHY_IS_BCM8485X_AND_UP(pc) && intf == PHY_DIAG_INTF_SYS) {
   8231                 SOC_IF_ERROR_RETURN
   8232                      (_phy_8481_diag_dsc_get(pc));
   8233             }
   8234             else {
   8235                 return SOC_E_UNAVAIL;
   8236             }
   8237             break;
   8238         }
   8239     }
   8240 #endif  /* BCM848XX_STATE_MFG_DIAG_SUPPORT */
   8241     return SOC_E_NONE;
   8242 }
   8243 
   8244 STATIC int
   8245 _phy848xx_short_reach_enable_set(int unit,phy_ctrl_t *pc, uint16 enable )
   8246 {
   8247     uint16 args[5];
   8248     args[0] = enable;
   8249 
   8250     if (PHY_IS_BCM8488X(pc) && enable) {
   8251         args[1] = enable;
   8252     }
   8253     SOC_IF_ERROR_RETURN
   8254         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_SHORT_REACH_ENABLE_GENERIC, args, (PHY_IS_BCM8488X(pc) && enable) ? 2 : 1));
   8255     
   8256     return (SOC_E_NONE);
   8257 }
   8258 
   8259 STATIC int
   8260 _phy848xx_short_reach_enable_get(int unit, phy_ctrl_t *pc, uint16 *enable, uint16 *fenable)
   8261 {
   8262     uint16 args[5];
   8263     *fenable = 0;
   8264 
   8265     if ( !PHY_IS_BCM8488X(pc) ) {
   8266         SOC_IF_ERROR_RETURN
   8267             (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_SHORT_REACH_ENABLE_GENERIC, args, 1));
   8268 
   8269         if (enable) {
   8270             *enable = args[0];
   8271         }
   8272     }
   8273     else { /* Orca  */
   8274         SOC_IF_ERROR_RETURN
   8275             (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_SHORT_REACH_ENABLE_GENERIC, args, 2));
   8276 
   8277         if (enable) {
   8278             *enable = args[0];
   8279         }
   8280 
   8281         if (args[0]) {
   8282             *fenable = args[1];
   8283         }
   8284     }
   8285     return (SOC_E_NONE);
   8286 }
   8287 
   8288 STATIC int
   8289 _phy_84834_power_mode_set (int unit, soc_port_t port, uint32 mode)
   8290 {
   8291     phy_ctrl_t    *pc;
   8292 
   8293     pc       = EXT_PHY_SW_STATE(unit, port);
   8294 
   8295     if (pc->power_mode == mode) {
   8296         return SOC_E_NONE;
   8297     }
   8298     if (mode == SOC_PHY_CONTROL_POWER_LOW) {
   8299         SOC_IF_ERROR_RETURN
   8300             (_phy848xx_short_reach_enable_set(unit, pc,  1));
   8301     } else if (mode == SOC_PHY_CONTROL_POWER_FULL) {
   8302         SOC_IF_ERROR_RETURN
   8303             (_phy848xx_short_reach_enable_set(unit, pc,  0));
   8304     } else {
   8305         return SOC_E_UNAVAIL;
   8306     }
   8307  
   8308     pc->power_mode = mode;
   8309 
   8310     return SOC_E_NONE;
   8311 }
   8312 
   8313 STATIC int
   8314 _phy_84834_power_mode_get (int unit, soc_port_t port, uint32 *mode)
   8315 {
   8316     phy_ctrl_t    *pc;
   8317     uint16       temp1=0, temp2=0;
   8318 
   8319     pc       = EXT_PHY_SW_STATE(unit, port);
   8320 
   8321     SOC_IF_ERROR_RETURN
   8322         (_phy848xx_short_reach_enable_get(unit, pc, &temp1, &temp2));
   8323     if (temp1) {
   8324         if (PHY_IS_BCM8488X(pc)) {
   8325             if (temp2) {
   8326                 *mode = SOC_PHY_CONTROL_POWER_LOW;
   8327             } else {
   8328                 *mode = SOC_PHY_CONTROL_POWER_FULL;
   8329             }
   8330         } else { 
   8331             *mode = SOC_PHY_CONTROL_POWER_LOW;
   8332         }
   8333     } else {
   8334         *mode = SOC_PHY_CONTROL_POWER_FULL;
   8335     }
   8336     pc->power_mode = *mode;
   8337 
   8338     return SOC_E_NONE;
   8339 }
   8340 
   8341 STATIC int
   8342 phy_8481_cable_diag(int unit, soc_port_t port,
   8343                     soc_port_cable_diag_t *status)
   8344 {
   8345     phy_ctrl_t    *pc;
   8346     soc_timeout_t  to;
   8347     int            i, rv, enable = 0, an = 0, an_done = 0, speed = 0;
   8348     uint16         ctrl_status, result, length;
   8349 
   8350 
   8351     pc = EXT_PHY_SW_STATE(unit, port);
   8352     
   8353     /* ECD not supported on disabled port for KOI and later PHYs  */
   8354     if (PHY_IS_BCM8485X_AND_UP(pc)) {
   8355         SOC_IF_ERROR_RETURN
   8356             (phy_8481_enable_get(unit, port, &enable));
   8357         if (!enable) {
   8358            return SOC_E_UNAVAIL; 
   8359         }
   8360 
   8361         SOC_IF_ERROR_RETURN
   8362             (phy_8481_an_get(unit, port, &an, &an_done));
   8363         SOC_IF_ERROR_RETURN
   8364             (phy_8481_speed_get(unit, port, &speed));
   8365         
   8366         /* KOI does not support ECD for forced 100M  */
   8367         if ( (speed == 100) && !(an) ) {
   8368             return SOC_E_UNAVAIL;
   8369         }
   8370     }
   8371 
   8372     status->fuzz_len = 10;
   8373     status->npairs = 4;
   8374     status->state = SOC_PORT_CABLE_STATE_OK;
   8375 
   8376     /* run now, not at AN, enanle inter pair short check, don't break link, length in meters */
   8377     SOC_IF_ERROR_RETURN
   8378         (MODIFY_PHY8481_TOP_CONFIG_CABLE_DIAG_CTRL_STAT_REG(unit, pc, (1U<<15)|(1U<<10), 
   8379             (1U<<15)|(1U<<14)|(1U<<13)|(1U<<12)|(1U<<10)));
   8380 
   8381     sal_usleep(100);
   8382     soc_timeout_init(&to, 50000000, 0);
   8383     
   8384     do {
   8385         rv = READ_PHY8481_TOP_CONFIG_CABLE_DIAG_CTRL_STAT_REG(unit, pc, &ctrl_status);
   8386         if (((ctrl_status & (1U<<11)) == 0) ||
   8387             SOC_FAILURE(rv)) {
   8388             break;
   8389         }
   8390     } while (!soc_timeout_check(&to));
   8391 
   8392     if ((ctrl_status & (1U<<11)) != 0) {
   8393         LOG_WARN(BSL_LS_SOC_PHY,
   8394                  (BSL_META_U(unit,
   8395                              "PHY848X Cable Diagnostics failed: u=%d p=%d\n"), unit, port ));
   8396         return (SOC_E_FAIL);
   8397     }
   8398 
   8399     SOC_IF_ERROR_RETURN
   8400         (READ_PHY8481_PHYC_CTL_CABLE_DIAG_RESULT_REG(unit, pc, &result));
   8401 
   8402     for( i=3; i>=0; i--) {
   8403 
   8404         switch (result & 0xf) {
   8405         case 0x1:
   8406             status->pair_state[i] = SOC_PORT_CABLE_STATE_OK;
   8407             break;
   8408         case 0x2:
   8409             status->pair_state[i] = SOC_PORT_CABLE_STATE_OPEN;
   8410             break;
   8411         case 0x3:
   8412             status->pair_state[i] = SOC_PORT_CABLE_STATE_SHORT;
   8413             break;
   8414         case 0x4:
   8415             status->pair_state[i] = SOC_PORT_CABLE_STATE_CROSSTALK;
   8416             break;
   8417         default:
   8418             status->pair_state[i] = SOC_PORT_CABLE_STATE_UNKNOWN;
   8419             break;
   8420         }
   8421 
   8422         if (status->pair_state[i] > status->state) {
   8423             status->state = status->pair_state[i];
   8424         }
   8425 
   8426         switch (i) {
   8427         case 3:
   8428             SOC_IF_ERROR_RETURN
   8429                 (READ_PHY8481_PHYC_CTL_CABLE_DIAG_PAIR78_LEN_REG(unit, pc, &length));
   8430             break;
   8431         case 2:
   8432             SOC_IF_ERROR_RETURN
   8433                 (READ_PHY8481_PHYC_CTL_CABLE_DIAG_PAIR56_LEN_REG(unit, pc, &length));
   8434             break;
   8435         case 1:
   8436             SOC_IF_ERROR_RETURN
   8437                 (READ_PHY8481_PHYC_CTL_CABLE_DIAG_PAIR34_LEN_REG(unit, pc, &length));
   8438             break;
   8439         case 0:
   8440             SOC_IF_ERROR_RETURN
   8441                 (READ_PHY8481_PHYC_CTL_CABLE_DIAG_PAIR12_LEN_REG(unit, pc, &length));
   8442             break;
   8443         }
   8444         status->pair_len[i] = length;
   8445         result >>= 4;
   8446     }
   8447 
   8448     return SOC_E_NONE;
   8449 }
   8450 
   8451 STATIC int
   8452 _phy84834_timesync_enable_set(int unit,phy_ctrl_t *pc, uint16 enable )
   8453 {
   8454     uint16 args[5];
   8455     args[0] = enable;
   8456 
   8457     if ( enable ) {
   8458         if ( ! (FLAGS(pc) & PHY8483X_TIMESYNC_ENABLED) ) {
   8459             SOC_IF_ERROR_RETURN
   8460                 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc,
   8461                         (uint16) PHY84834_DIAG_CMD_SET_1588_ENABLE_GENERIC,
   8462                         args, 1));
   8463             FLAGS(pc) |= PHY8483X_TIMESYNC_ENABLED;
   8464             /* PTP_PARSER_EG_CNTR_[ALL/PTP]_PKT_[EN/CLR] registers *\
   8465             \* 1.0xda20,0xda30,0xda21,0xda31 ,  bit[0]             */
   8466             SOC_IF_ERROR_RETURN
   8467                 (MODIFY_PHY8481_PMAD_REG(unit, pc,
   8468                         PHY84834_PTP_PARSER_EG_CNTR_ALL_PKT_EN , 0x1, 0x1));
   8469             SOC_IF_ERROR_RETURN
   8470                 (MODIFY_PHY8481_PMAD_REG(unit, pc,
   8471                         PHY84834_PTP_PARSER_EG_CNTR_PTP_PKT_EN , 0x1, 0x1));
   8472             SOC_IF_ERROR_RETURN
   8473                 (MODIFY_PHY8481_PMAD_REG(unit, pc,
   8474                         PHY84834_PTP_PARSER_EG_CNTR_ALL_PKT_CLR, 0x1, 0x1));
   8475             SOC_IF_ERROR_RETURN
   8476                 (MODIFY_PHY8481_PMAD_REG(unit, pc,
   8477                         PHY84834_PTP_PARSER_EG_CNTR_PTP_PKT_CLR, 0x1, 0x1));
   8478             /* PTP_PARSER_IG_CNTR_[ALL/PTP]_PKT_[EN/CLR] registers *\
   8479             \* 1.0xdaa0,0xdab0,0xdaa1,0xdab1 ,  bit[0]             */
   8480             SOC_IF_ERROR_RETURN
   8481                 (MODIFY_PHY8481_PMAD_REG(unit, pc,
   8482                         PHY84834_PTP_PARSER_IG_CNTR_ALL_PKT_EN , 0x1, 0x1));
   8483             SOC_IF_ERROR_RETURN
   8484                 (MODIFY_PHY8481_PMAD_REG(unit, pc,
   8485                         PHY84834_PTP_PARSER_IG_CNTR_PTP_PKT_EN , 0x1, 0x1));
   8486             SOC_IF_ERROR_RETURN
   8487                 (MODIFY_PHY8481_PMAD_REG(unit, pc,
   8488                         PHY84834_PTP_PARSER_IG_CNTR_ALL_PKT_CLR, 0x1, 0x1));
   8489             SOC_IF_ERROR_RETURN
   8490                 (MODIFY_PHY8481_PMAD_REG(unit, pc,
   8491                         PHY84834_PTP_PARSER_IG_CNTR_PTP_PKT_CLR, 0x1, 0x1));
   8492         }
   8493 
   8494     } else {      /* disable */
   8495         if ((FLAGS(pc) & PHY8483X_TIMESYNC_ENABLED)) {
   8496             SOC_IF_ERROR_RETURN
   8497                 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc,
   8498                         (uint16)PHY84834_DIAG_CMD_SET_1588_ENABLE_GENERIC,
   8499                         args, 1));
   8500             FLAGS(pc) &= ~PHY8483X_TIMESYNC_ENABLED;
   8501             SOC_IF_ERROR_RETURN
   8502                 (MODIFY_PHY8481_PMAD_REG(unit, pc,
   8503                         PHY84834_PTP_PARSER_EG_CNTR_ALL_PKT_EN, 0x0, 0x1));
   8504             SOC_IF_ERROR_RETURN
   8505                 (MODIFY_PHY8481_PMAD_REG(unit, pc,
   8506                         PHY84834_PTP_PARSER_IG_CNTR_ALL_PKT_EN, 0x0, 0x1));
   8507         }
   8508     }
   8509     SOC_IF_ERROR_RETURN
   8510         (phy_8481_an_set(unit, pc->port, 1));
   8511 
   8512     return (SOC_E_NONE);
   8513 }
   8514 
   8515 STATIC int
   8516 _phy84834_timesync_enable_get(int unit,phy_ctrl_t *pc, uint16 *enable )
   8517 {
   8518     uint16 args[5];
   8519 
   8520     SOC_IF_ERROR_RETURN
   8521         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_1588_ENABLE_GENERIC, args, 1));
   8522 
   8523     if (enable) {
   8524         *enable = args[0];
   8525     }
   8526 
   8527     return (SOC_E_NONE);
   8528 }
   8529 
   8530 void _phy84834_encode_egress_message_mode(soc_port_phy_timesync_event_message_egress_mode_t mode,
   8531                                             int offset, uint16 *value)
   8532 {
   8533     switch (mode) {
   8534     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE:
   8535         *value |= (0x0 << offset);
   8536         break;
   8537     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD:
   8538         *value |= (0x1 << offset);
   8539         break;
   8540     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN:
   8541         *value |= (0x2 << offset);
   8542         break;
   8543     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP:
   8544         *value |= (0x3 << offset);
   8545         break;
   8546     default:
   8547         break;
   8548     }
   8549 }
   8550 
   8551 void _phy84834_encode_ingress_message_mode(soc_port_phy_timesync_event_message_ingress_mode_t mode,
   8552                                             int offset, uint16 *value)
   8553 {
   8554     switch (mode) {
   8555     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE:
   8556         *value |= (0x0 << offset);
   8557         break;
   8558     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD:
   8559         *value |= (0x1 << offset);
   8560         break;
   8561     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP:
   8562         *value |= (0x2 << offset);
   8563         break;
   8564     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME:
   8565         *value |= (0x3 << offset);
   8566         break;
   8567     default:
   8568         break;
   8569     }
   8570 }
   8571 
   8572 void _phy84834_decode_egress_message_mode(uint16 value, int offset,
   8573                                             soc_port_phy_timesync_event_message_egress_mode_t *mode)
   8574 {
   8575     switch ((value >> offset) & 0x7) {
   8576     case 0x0:
   8577         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE;
   8578         break;
   8579     case 0x1:
   8580         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD;
   8581         break;
   8582     case 0x2:
   8583         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN;
   8584         break;
   8585     case 0x3:
   8586         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP;
   8587         break;
   8588     default:
   8589         break;
   8590     }
   8591 }
   8592 
   8593 void _phy84834_decode_ingress_message_mode(uint16 value, int offset,
   8594                                             soc_port_phy_timesync_event_message_ingress_mode_t *mode)
   8595 {
   8596     switch ((value >> offset) & 0x7) {
   8597     case 0x0:
   8598         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE;
   8599         break;
   8600     case 0x1:
   8601         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD;
   8602         break;
   8603     case 0x2:
   8604         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP;
   8605         break;
   8606     case 0x3:
   8607         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME;
   8608         break;
   8609     default:
   8610         break;
   8611     }
   8612 }
   8613 
   8614 void _phy84834_encode_gmode(soc_port_phy_timesync_global_mode_t mode,
   8615                                             uint16 *value)
   8616 {
   8617     switch (mode) {
   8618     case SOC_PORT_PHY_TIMESYNC_MODE_FREE:
   8619         *value = 0x1;
   8620         break;
   8621     case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN:
   8622         *value = 0x2;
   8623         break;
   8624     case SOC_PORT_PHY_TIMESYNC_MODE_CPU:
   8625         *value = 0x3;
   8626         break;
   8627     default:
   8628         break;
   8629     }
   8630 }
   8631 
   8632 void _phy84834_decode_gmode(uint16 value, soc_port_phy_timesync_global_mode_t *mode)
   8633 {
   8634     switch (value & 0x3) {
   8635     case 0x1:
   8636         *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   8637         break;
   8638     case 0x2:
   8639         *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN;
   8640         break;
   8641     case 0x3:
   8642         *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU;
   8643         break;
   8644     default:
   8645         break;
   8646     }
   8647 }
   8648 
   8649 
   8650 void _phy84834_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode,
   8651                                             uint16 *value)
   8652 {
   8653     switch (mode) {
   8654     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0:
   8655         *value = 1;
   8656         break;
   8657     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1:
   8658         *value = 2;
   8659         break;
   8660     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT:
   8661         *value = 3;
   8662         break;
   8663     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU:
   8664         *value = 4;
   8665         break;
   8666     default:
   8667         break;
   8668     }
   8669 }
   8670 
   8671 void _phy84834_decode_framesync_mode(uint16 value, soc_port_phy_timesync_framesync_mode_t *mode)
   8672 {
   8673     switch (value & 0xf) {
   8674     case 1:
   8675         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0;
   8676         break;
   8677     case 2:
   8678         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1;
   8679         break;
   8680     case 3:
   8681         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT;
   8682         break;
   8683     case 4:
   8684         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU;
   8685         break;
   8686     default:
   8687         break;
   8688     }
   8689 }
   8690 
   8691 void _phy84834_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t mode,
   8692                                             uint16 *value)
   8693 {
   8694     switch (mode) {
   8695     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE:
   8696         *value = 0x0;
   8697         break;
   8698     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME:
   8699         *value = 0x1;
   8700         break;
   8701     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN:
   8702         *value = 0x2;
   8703         break;
   8704     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC:
   8705         *value = 0x3;
   8706         break;
   8707     default:
   8708         break;
   8709     }
   8710 }
   8711 
   8712 #ifdef PHY8185X_DEBUG_CMD_HANDLER
   8713 STATIC int
   8714 _phy8485x_emi_mode_enable_get(int unit, phy_ctrl_t *pc, uint16 *status)
   8715 {
   8716     uint16 args[2];
   8717 
   8718    SOC_IF_ERROR_RETURN
   8719         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_EMI_MODE_ENABLE_V2, args, 1));
   8720 
   8721     *status = args[0];
   8722 
   8723     return (SOC_E_NONE);
   8724 }
   8725 
   8726 STATIC int
   8727 _phy8485x_emi_mode_enable_set(int unit, phy_ctrl_t *pc, uint16 status)
   8728 {
   8729     uint16 args[2];
   8730 
   8731     args[0] = status;
   8732     SOC_IF_ERROR_RETURN
   8733         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_EMI_MODE_ENABLE_V2, args, 1));
   8734 
   8735     return (SOC_E_NONE);
   8736 }
   8737 
   8738 STATIC int
   8739 _phy8485x_sub_lf_rf_status_get(int unit, phy_ctrl_t *pc, uint16 *status)
   8740 {
   8741     uint16 args[2];
   8742 
   8743     SOC_IF_ERROR_RETURN
   8744        (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_SUB_LF_RF_V2, args, 1));
   8745 
   8746     *status = args[0];
   8747 
   8748     return (SOC_E_NONE);
   8749 }
   8750 
   8751 STATIC int
   8752 _phy8485x_sub_lf_rf_set(int unit, phy_ctrl_t *pc)
   8753 {
   8754     uint16 args[2];
   8755     args[0]=1;
   8756 
   8757     SOC_IF_ERROR_RETURN
   8758        (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_SUB_LF_RF_GENERIC, args, 1));
   8759 
   8760     return (SOC_E_NONE);
   8761 }
   8762 
   8763 STATIC int
   8764 _phy8485x_sub_lf_rf_clear(int unit, phy_ctrl_t *pc)
   8765 {
   8766    uint16 args[2];
   8767    args[0]=1;
   8768 
   8769    SOC_IF_ERROR_RETURN
   8770         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_CLEAR_SUB_LF_RF_GENERIC, args, 1));
   8771 
   8772     return (SOC_E_NONE);
   8773 }
   8774 
   8775 STATIC int
   8776 _phy8485x_snr_get(int unit, phy_ctrl_t *pc)
   8777 {
   8778     uint16 args[5];
   8779     args[0]=0;
   8780 
   8781     SOC_IF_ERROR_RETURN
   8782     (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_SNR_GENERIC,  args, 5));
   8783     
   8784     return (SOC_E_NONE);
   8785 }
   8786 
   8787 STATIC int
   8788 _phy8485x_current_temp_get(int unit, phy_ctrl_t *pc)
   8789 {
   8790     uint16 args[2];
   8791     args[0]=0;
   8792 
   8793     SOC_IF_ERROR_RETURN
   8794         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_CURRENT_TEMP_GENERIC,  args, 1));
   8795 
   8796     return (SOC_E_NONE);
   8797 }
   8798 
   8799 STATIC int
   8800 _phy8485x_upper_temp_warn_level_get(int unit, phy_ctrl_t *pc, uint16 *temp)
   8801 {
   8802     uint16 args[2];
   8803     args[0]=0;
   8804 
   8805     SOC_IF_ERROR_RETURN
   8806         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_UPPER_TEMP_WARNING_LEVEL_V2,  args, 1));
   8807 
   8808     *temp = args[0];
   8809 
   8810     return (SOC_E_NONE);
   8811 }
   8812 
   8813 STATIC int
   8814 _phy8485x_upper_temp_warn_level_set(int unit, phy_ctrl_t *pc, uint16 temp)
   8815 {
   8816     uint16 args[2];
   8817     args[0]=temp;
   8818 
   8819     SOC_IF_ERROR_RETURN
   8820         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_UPPER_TEMP_WARNING_LEVEL_V2,  args, 1));
   8821 
   8822     return (SOC_E_NONE);
   8823 }
   8824 
   8825 STATIC int
   8826 _phy8485x_lower_temp_warn_level_get(int unit, phy_ctrl_t *pc, uint16 *temp)
   8827 {
   8828     uint16 args[2];
   8829     args[0]=0;
   8830 
   8831     SOC_IF_ERROR_RETURN
   8832         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_LOWER_TEMP_WARNING_LEVEL_V2,  args, 1));
   8833 
   8834     *temp = args[0];
   8835 
   8836     return (SOC_E_NONE);
   8837 }
   8838 
   8839 STATIC int
   8840 _phy8485x_lower_temp_warn_level_set(int unit, phy_ctrl_t *pc, uint16 temp)
   8841 {
   8842     uint16 args[2];
   8843     args[0]=temp;
   8844 
   8845     SOC_IF_ERROR_RETURN
   8846         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_LOWER_TEMP_WARNING_LEVEL_V2,  args, 1));
   8847 
   8848     return (SOC_E_NONE);
   8849 }
   8850 
   8851 STATIC int
   8852 _phy8486x_xfi_2p5g_mode_get(int unit, phy_ctrl_t *pc, uint16 *mode_2p5g)
   8853 {
   8854     uint16  args[2] = { 0, 0 };
   8855 
   8856     SOC_IF_ERROR_RETURN
   8857         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc,
   8858                     (uint16) PHY84834_DIAG_CMD_GET_XFI_2P5G_MODE_V2, args, 1) );
   8859     *mode_2p5g = args[0];
   8860 
   8861     return (SOC_E_NONE);
   8862 }
   8863 
   8864 STATIC int
   8865 _phy848xx_xfi_2p5g_5g_mode_get(int unit, phy_ctrl_t *pc, uint16 *mode_2p5g, uint16 *mode_5g)
   8866 {
   8867     uint16  args[2] = { 0, 0 };
   8868 
   8869     SOC_IF_ERROR_RETURN
   8870         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc,
   8871                     (uint16) PHY84834_DIAG_CMD_GET_XFI_2P5G_MODE_V2, args, (PHY_IS_BCM8488X(pc) ? 2 : 1)) );
   8872     *mode_2p5g = args[0];
   8873     if (PHY_IS_BCM8488X(pc)) {
   8874         *mode_5g = args[1];
   8875     }
   8876     return (SOC_E_NONE);
   8877 }
   8878 
   8879 STATIC int
   8880 _phy_848xx_led_type_get (int unit, soc_port_t port, uint32 *led_type, uint32 *led_mode)
   8881 {
   8882     uint16 args[5];
   8883     phy_ctrl_t    *pc;
   8884 
   8885     pc = EXT_PHY_SW_STATE(unit, port);
   8886 
   8887     SOC_IF_ERROR_RETURN
   8888         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84888_DIAG_CMD_GET_LED_TYPE, args, 2));
   8889 
   8890     if (led_type) {
   8891         *led_type = args[0];
   8892     }
   8893     if ( PHY_IS_BCM8488X(pc) && (args[0] == 2) ) {
   8894         *led_mode = args[1];
   8895     }
   8896 
   8897     return (SOC_E_NONE);
   8898 }
   8899 
   8900 STATIC int
   8901 _phy_848xx_led_type_set (int unit, soc_port_t port, uint32 led_type, uint32 led_mode)
   8902 {
   8903     uint16 args[5];
   8904     phy_ctrl_t    *pc;
   8905 
   8906     pc = EXT_PHY_SW_STATE(unit, port);
   8907     args[0] = led_type;
   8908 
   8909     if (led_type == 2) {
   8910         args[1] = led_mode;
   8911     }
   8912 
   8913     SOC_IF_ERROR_RETURN
   8914         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84888_DIAG_CMD_SET_LED_TYPE, args, 2));
   8915 
   8916     return (SOC_E_NONE);
   8917 }
   8918 
   8919 STATIC int
   8920 _phy_848xx_pause_frame_mode_get (int unit, soc_port_t port, uint32 *enable)
   8921 {
   8922     uint16 args[2];
   8923     phy_ctrl_t    *pc;
   8924 
   8925     pc = EXT_PHY_SW_STATE(unit, port);
   8926 
   8927     SOC_IF_ERROR_RETURN
   8928         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84888_DIAG_CMD_GET_PAUSE_FRAME_MODE, args, 1));
   8929     *enable = args[0];
   8930 
   8931     return (SOC_E_NONE);
   8932 }
   8933 
   8934 STATIC int
   8935 _phy_848xx_pause_frame_mode_set (int unit, soc_port_t port, uint32 enable)
   8936 {
   8937     uint16 args[2];
   8938     phy_ctrl_t    *pc;
   8939 
   8940     pc = EXT_PHY_SW_STATE(unit, port);
   8941     args[0] = enable;
   8942 
   8943     SOC_IF_ERROR_RETURN
   8944         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84888_DIAG_CMD_SET_PAUSE_FRAME_MODE, args, 1));
   8945 
   8946     return (SOC_E_NONE);
   8947 }
   8948 #endif /* PHY8185X_DEBUG_CMD_HANDLER */
   8949 
   8950 STATIC int
   8951 _phy_848xx_mgbase_802_3bz_type_get (int unit, phy_ctrl_t *pc, uint16 *frame_type, uint16 *frame_mode)
   8952 {
   8953     uint16        args[5];
   8954 
   8955     SOC_IF_ERROR_RETURN
   8956         (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84888_DIAG_CMD_GET_MGBASET_802_3BZ_TYPE, args, 2));
   8957 
   8958     *frame_type = args[0];
   8959     *frame_mode = args[1];
   8960 
   8961     return (SOC_E_NONE);
   8962 }
   8963 
   8964 STATIC int
   8965 _phy_848xx_mgbase_802_3bz_type_set (int unit, phy_ctrl_t *pc, uint16 frame_type, uint16 frame_mode)
   8966 {
   8967     uint16        args[5];
   8968 
   8969     args[0] = frame_type;
   8970     args[1] = frame_mode;
   8971 
   8972     SOC_IF_ERROR_RETURN
   8973         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84888_DIAG_CMD_SET_MGBASET_802_3BZ_TYPE, args, 2));
   8974 
   8975     return (SOC_E_NONE);
   8976 }
   8977 
   8978 STATIC int
   8979 _phy848xx_xfi_2p5g_5g_mode_set(int unit, phy_ctrl_t *pc, uint16 mode_2p5g)
   8980 {
   8981     uint16 args[2];
   8982 
   8983     args[0] = mode_2p5g;
   8984     if ( PHY_IS_BCM8488X(pc) ) {
   8985         args[1] = mode_2p5g;
   8986     }
   8987     SOC_IF_ERROR_RETURN
   8988         (PHY84834_TOP_LEVEL_CMD_SET(unit, pc,
   8989                     (uint16)PHY84834_DIAG_CMD_SET_XFI_2P5G_MODE_V2, args, (PHY_IS_BCM8488X(pc) ? 2 : 1)) );
   8990     return (SOC_E_NONE);
   8991 }
   8992 
   8993 void _phy84834_decode_syncout_mode(uint16 value,
   8994                                             soc_port_phy_timesync_syncout_mode_t *mode)
   8995 {
   8996     switch (value & 0x3) {
   8997     case 0x0:
   8998         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   8999         break;
   9000     case 0x1:
   9001         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME;
   9002         break;
   9003     case 0x2:
   9004         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN;
   9005         break;
   9006     case 0x3:
   9007         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC;
   9008         break;
   9009     }
   9010 }
   9011 
   9012 
   9013 /*
   9014  * Function:
   9015  *    phy84834_timesync_config_set
   9016  * Purpose:
   9017  *
   9018  * Parameters:
   9019  *
   9020  * Returns:
   9021  */
   9022 int
   9023 phy84834_timesync_config_set(int unit, soc_port_t port,
   9024                              soc_port_phy_timesync_config_t *conf)
   9025 {
   9026     uint16 eg_config= 0, ig_config = 0,
   9027            nse_sc_cfg = 0, value = 0, nse_nco_cfg = 0, temp16 = 0,temp1 = 0,temp2 = 0,
   9028            gmode = 0, syncout_mode = 0, framesync_mode = 0;
   9029     phy_ctrl_t *pc;
   9030 
   9031     pc = EXT_PHY_SW_STATE(unit, port);
   9032 
   9033     if(NULL == conf) {
   9034         return SOC_E_PARAM;
   9035     }
   9036     if ( PHY_IS_BCM8488X(pc) || (! PHY_IS_BCM8483X_AND_UP(pc)) ) {
   9037         return SOC_E_UNAVAIL;
   9038     }
   9039     
   9040     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   9041         SOC_IF_ERROR_RETURN
   9042             (_phy84834_timesync_enable_set(unit, pc,
   9043                         (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) ? 1 : 0 ));
   9044 
   9045         /* Capture PKT INFO  - Rx & Tx*/
   9046         temp1 = temp2 = 0;  
   9047         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) {
   9048             temp1 |= PHY84834_PTP_EG_PTP_PKT_CFG_CAPT_PTP_ALL;
   9049             temp2 |= PHY84834_PTP_IG_PTP_PKT_CFG_CAPT_PTP_ALL; 
   9050         }
   9051         /* Egress  Parser PTP Config Reg. 1.DA08[15,11,7,3] */
   9052         SOC_IF_ERROR_RETURN
   9053             (MODIFY_PHY8481_PMAD_REG(unit, pc,
   9054                              PHY84834_PTP_EG_PTP_PKT_CFG_REG,
   9055                              temp1, PHY84834_PTP_EG_PTP_PKT_CFG_CAPT_PTP_ALL));
   9056         /* Ingress Parser PTP Config Reg. 1.DA88[15,11,7,3] */
   9057         SOC_IF_ERROR_RETURN
   9058             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9059                              PHY84834_PTP_IG_PTP_PKT_CFG_REG,
   9060                              temp2, PHY84834_PTP_IG_PTP_PKT_CFG_CAPT_PTP_ALL));
   9061 
   9062         /* Timestamp/Source_port capturing configuration */
   9063         /* Capture full 80-bit src_port or 16-bit src port + 64-bit IP/MAC */
   9064         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_FULL_SOURCE_PORT) {
   9065             temp16 |= PHY8486X_PTP_PIC_CONFIG_FULL_SRC_PORT;
   9066         }
   9067         /* Capture packet's 48-bit countstamp or 64 LSB of 80-bit timestamp */
   9068         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_LONG_TIMESTAMP) {
   9069             temp16 |= PHY8486X_PTP_PIC_CONFIG_LONG_TIMESTAMP;
   9070         }
   9071         /* PIC Configuration Reg. 1.DB01[1:0] */
   9072         SOC_IF_ERROR_RETURN
   9073             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9074                                      PHY8486X_PTP_PIC_CONFIG_REG,
   9075                                      temp16, PHY8486X_PTP_PIC_CONFIG_MASK) );
   9076 
   9077         /* Enable timestamp capture on the next frame sync event */
   9078         nse_sc_cfg |= PHY84834_PTP_NSE_SC_CFG_FSYNC_EN;
   9079         if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) {
   9080             nse_sc_cfg |= PHY84834_PTP_NSE_SC_CFG_FSYNC_TS_EN;
   9081         }
   9082         SOC_IF_ERROR_RETURN
   9083             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9084                                      PHY84834_PTP_NSE_SC_CFG_REG,
   9085                                      nse_sc_cfg, 
   9086                                      PHY84834_PTP_NSE_SC_CFG_FSYNC_EN |
   9087                                      PHY84834_PTP_NSE_SC_CFG_FSYNC_TS_EN) );
   9088        
   9089         /* Enable the FCS/CRC check in PTP detection receiving side */
   9090         temp16 = 0;
   9091         if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) {
   9092             temp16 |= PHY84834_PTP_IG_CFG_FCS_CHECK_EN;       
   9093         }
   9094         SOC_IF_ERROR_RETURN
   9095             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9096                                      PHY84834_PTP_IG_CFG_REG,
   9097                                      temp16, 
   9098                                      PHY84834_PTP_IG_CFG_FCS_CHECK_EN));
   9099 
   9100         /* Enable different packet detections & checks in Rx & Tx direction */
   9101         if ( (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) ||
   9102              (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) ) {
   9103             ig_config |= PHY84834_PTP_IG_CFG_L2_802AS_EN;
   9104             eg_config |= PHY84834_PTP_EG_CFG_L2_802AS_EN;
   9105         }
   9106         if ( conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE ) {
   9107             ig_config |= PHY84834_PTP_IG_CFG_L4_IP4_UDP_EN;
   9108             eg_config |= PHY84834_PTP_EG_CFG_L4_IP4_UDP_EN;
   9109         }
   9110         if ( conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE ) {
   9111             ig_config |= PHY84834_PTP_IG_CFG_L4_IP6_UDP_EN;
   9112             eg_config |= PHY84834_PTP_EG_CFG_L4_IP6_UDP_EN;
   9113         }
   9114 #if 0
   9115         if (conf->flags & SOC_PORT_PHY_TIMESYNC_L4_IPV6_ADDR_ENABLE) {
   9116             ig_config |= PHY84834_PTP_IG_CFG_L4_IP6_UDP_ACH_EN;
   9117             eg_config |= PHY84834_PTP_EG_CFG_L4_IP6_UDP_ACH_EN;
   9118         }
   9119         if (conf->flags & SOC_PORT_PHY_TIMESYNC_L4_IP_ADDR_ENABLE) {
   9120             ig_config |= PHY84834_PTP_IG_CFG_L4_IP4_UDP_ACH_EN;
   9121             eg_config |= PHY84834_PTP_EG_CFG_L4_IP4_UDP_ACH_EN;
   9122         }
   9123         if ((conf->flags & SOC_PORT_PHY_TIMESYNC_L2_DS_ENABLE) 
   9124            || (conf->flags & SOC_PORT_PHY_TIMESYNC_AS_DS_ENABLE)) { 
   9125             ig_config |= PHY84834_PTP_IG_CFG_L2_802AS_ACH_EN;
   9126             eg_config |= PHY84834_PTP_EG_CFG_L2_802AS_ACH_EN;
   9127         } 
   9128 #endif
   9129         /* IG Config */
   9130         SOC_IF_ERROR_RETURN
   9131             (WRITE_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_IG_CFG_REG, ig_config));
   9132         /* EG Config */
   9133         SOC_IF_ERROR_RETURN
   9134             (WRITE_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_EG_CFG_REG, eg_config));
   9135                                           
   9136 
   9137         /* Set input for NCO adder */
   9138         if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) {
   9139             nse_nco_cfg |= (uint16)  PHY84834_PTP_NSE_NCO_CFG_FCW_SEL;
   9140         } else {
   9141             nse_nco_cfg &= (uint16) ~PHY84834_PTP_NSE_NCO_CFG_FCW_SEL;
   9142         }
   9143 
   9144         /* NSE NCO CFG register */
   9145         SOC_IF_ERROR_RETURN
   9146             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9147                                                PHY84834_PTP_NSE_NCO_CFG_REG, 
   9148                                                nse_nco_cfg, 
   9149                                                PHY84834_PTP_NSE_NCO_CFG_FCW_SEL));
   9150     }
   9151 
   9152     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) {
   9153         SOC_IF_ERROR_RETURN
   9154             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9155                                               PHY84834_PTP_VLAN_1TAG_TPID_REG, conf->itpid));
   9156     }
   9157     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) {
   9158         SOC_IF_ERROR_RETURN
   9159             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9160                                               PHY84834_PTP_VLAN_2TAG_OTPID_REG, conf->otpid));
   9161     }
   9162     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) {
   9163         SOC_IF_ERROR_RETURN
   9164             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9165                                               PHY84834_PTP_VLAN_2TAG_OTPID_1_REG, conf->otpid2));
   9166     }
   9167     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) {
   9168         SOC_IF_ERROR_RETURN
   9169             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9170                                               PHY84834_PTP_NSE_SHDW_DPLL_SYNC_DIV_REG, 
   9171                                               conf->ts_divider & 0x0fff));
   9172         /* Enable loading shadow reg value to active copy on next framesync */
   9173         SOC_IF_ERROR_RETURN
   9174             (MODIFY_PHY8481_PMAD_REG(unit, pc,
   9175                                                PHY84834_PTP_NSE_SHDW_CTL_REG,
   9176                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNC_DIV,
   9177                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNC_DIV));
   9178     }
   9179     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) {
   9180         /* Do nothing
   9181          *
   9182          * In some chips there are two registers Rx timestamp offset & 
   9183          * Rx link delay. These two registers do similar funtion. 
   9184          * The offset was added to the internal timestamp, the 
   9185          * link delay was subtracted from it. Rx link delay control not required 
   9186          * in this chip. Tx/RX timestamp offset does the job. The signed value will
   9187          * be added to the timestamp.
   9188          */
   9189     }
   9190 
   9191     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) {
   9192         SOC_IF_ERROR_RETURN
   9193             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9194                      PHY84834_PTP_NSE_SHDW_ORG_TS_0_REG, 
   9195                      (uint16)(conf->original_timecode.nanoseconds & 0xffff)));
   9196         SOC_IF_ERROR_RETURN
   9197             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9198                      PHY84834_PTP_NSE_SHDW_ORG_TS_1_REG, 
   9199                      (uint16)((conf->original_timecode.nanoseconds >> 16) & 0xffff)));
   9200         SOC_IF_ERROR_RETURN
   9201             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9202                      PHY84834_PTP_NSE_SHDW_ORG_TS_2_REG, 
   9203                      (uint16)(COMPILER_64_LO(conf->original_timecode.seconds) & 0xffff)));
   9204         SOC_IF_ERROR_RETURN
   9205             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9206                      PHY84834_PTP_NSE_SHDW_ORG_TS_3_REG, 
   9207                      (uint16)((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) 
   9208                         & 0xffff)));
   9209         SOC_IF_ERROR_RETURN
   9210             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9211                      PHY84834_PTP_NSE_SHDW_ORG_TS_4_REG, 
   9212                      (uint16)(COMPILER_64_HI(conf->original_timecode.seconds) & 0xffff)));
   9213         /* Enable loading shadow reg value to active copy on next framesync */
   9214         SOC_IF_ERROR_RETURN
   9215             (MODIFY_PHY8481_PMAD_REG(unit, pc,
   9216                                                PHY84834_PTP_NSE_SHDW_CTL_REG,
   9217                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_ORIG_TS,
   9218                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_ORIG_TS));
   9219     }
   9220 
   9221     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) {
   9222         _phy84834_encode_gmode(conf->gmode,&gmode);
   9223     }
   9224     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) {
   9225         _phy84834_encode_framesync_mode(conf->framesync.mode, &framesync_mode);
   9226         SOC_IF_ERROR_RETURN
   9227             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9228                                         PHY84834_NSE_SYNCIN_FSYNC_LEN_0_REG, 
   9229                                         conf->framesync.length_threshold & 0xffff));/*[15:0]*/
   9230         SOC_IF_ERROR_RETURN
   9231             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9232                                         PHY84834_NSE_SYNCIN_FSYNC_LEN_1_REG, 
   9233                                         (conf->framesync.length_threshold >> 16) & 0x7,
   9234                                         0x7));/*[18:16]*/
   9235         SOC_IF_ERROR_RETURN
   9236             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9237                                         PHY84834_NSE_SYNCIN_FSYNC_DLY_0_REG, 
   9238                                         conf->framesync.event_offset & 0xffff));/*[15:0]*/
   9239         SOC_IF_ERROR_RETURN
   9240             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9241                                         PHY84834_NSE_SYNCIN_FSYNC_DLY_1_REG, 
   9242                                         (conf->framesync.event_offset >> 16) & 0x7,
   9243                                         0x7));/*[18:16]*/
   9244     }
   9245 
   9246     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) {
   9247         _phy84834_encode_syncout_mode(conf->syncout.mode, &syncout_mode);
   9248 
   9249         /* Interval & pulse width of syncout pulse */
   9250         SOC_IF_ERROR_RETURN
   9251             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9252                                               PHY84834_PTP_NSE_SHDW_SOUT_INTERVAL_0_REG, 
   9253                                               conf->syncout.interval & 0xffff));
   9254         SOC_IF_ERROR_RETURN
   9255             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9256                                               PHY84834_PTP_NSE_SHDW_SOUT_INTERVAL_1_REG,
   9257                                               ((conf->syncout.interval >> 16) & 0xffff)));
   9258         SOC_IF_ERROR_RETURN
   9259             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9260                                               PHY84834_PTP_NSE_SHDW_SOUT_PULSE1_LEN_REG, 
   9261                                               conf->syncout.pulse_1_length & 0x0fff));
   9262         SOC_IF_ERROR_RETURN
   9263             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9264                                               PHY84834_PTP_NSE_SHDW_SOUT_PULSE2_LEN_REG, 
   9265                                               conf->syncout.pulse_2_length & 0x0fff));
   9266         /* Local timer for SYNC_OUT */
   9267         SOC_IF_ERROR_RETURN
   9268             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9269                         PHY84834_PTP_NSE_SOUT_TS_CMP_0_REG,
   9270                         (uint16)(COMPILER_64_LO(conf->syncout.syncout_ts) & 0xffff)));
   9271         SOC_IF_ERROR_RETURN
   9272             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9273                         PHY84834_PTP_NSE_SOUT_TS_CMP_1_REG,
   9274                         (uint16)((COMPILER_64_LO(conf->syncout.syncout_ts) >> 16) & 0xffff)));
   9275         SOC_IF_ERROR_RETURN
   9276             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9277                         PHY84834_PTP_NSE_SOUT_TS_CMP_2_REG,
   9278                         (uint16)(COMPILER_64_HI(conf->syncout.syncout_ts) & 0xffff)));
   9279 
   9280         /* Enable loading shadow reg value to active copy on next framesync */
   9281         SOC_IF_ERROR_RETURN
   9282             (MODIFY_PHY8481_PMAD_REG(unit, pc,
   9283                                                PHY84834_PTP_NSE_SHDW_CTL_REG,
   9284                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNCOUT,
   9285                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNCOUT));
   9286     }
   9287  
   9288     /* GMODE */ 
   9289     SOC_IF_ERROR_RETURN
   9290         (MODIFY_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_NSE_SC_CFG_REG, 
   9291                    (gmode << 0) | (framesync_mode << 4) | (syncout_mode << 8), 
   9292                    ( PHY84834_PTP_NSE_SC_CFG_GS_MODE |
   9293                      PHY84834_PTP_NSE_SC_CFG_SI_MODE |
   9294                      PHY84834_PTP_NSE_SC_CFG_SO_MODE)) );
   9295     /* TX TS OFFSET register */
   9296     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) {
   9297         SOC_IF_ERROR_RETURN
   9298             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9299                                               PHY84834_PTP_TS_EG_SOP_OFFSET_0_REG, 
   9300                                               (uint16)(conf->tx_timestamp_offset & 0xffff)));
   9301         SOC_IF_ERROR_RETURN
   9302             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9303                                               PHY84834_PTP_TS_EG_SOP_OFFSET_1_REG, 
   9304                                               (uint16)((conf->tx_timestamp_offset >> 16) & 0xf ),
   9305                                               0xf));
   9306 
   9307     }
   9308 
   9309      /* RX TS OFFSET register */
   9310     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) {
   9311         SOC_IF_ERROR_RETURN
   9312             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9313                                               PHY84834_PTP_TS_IG_SOP_OFFSET_0_REG, 
   9314                                               (uint16)(conf->rx_timestamp_offset & 0xffff)));
   9315         SOC_IF_ERROR_RETURN
   9316             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9317                                               PHY84834_PTP_TS_IG_SOP_OFFSET_1_REG, 
   9318                                               (uint16)((conf->rx_timestamp_offset >> 16) & 0xf ),
   9319                                               0xf));
   9320     }
   9321 
   9322     /* PTP TX action */
   9323     value = 0;
   9324     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) {
   9325         _phy84834_encode_egress_message_mode(conf->tx_sync_mode, 0, &value);
   9326     }
   9327     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) {
   9328         _phy84834_encode_egress_message_mode(conf->tx_delay_request_mode, 4, &value);
   9329     }
   9330     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) {
   9331         _phy84834_encode_egress_message_mode(conf->tx_pdelay_request_mode, 8, &value);
   9332     }
   9333     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) {
   9334         _phy84834_encode_egress_message_mode(conf->tx_pdelay_response_mode, 12, &value);
   9335     }
   9336     SOC_IF_ERROR_RETURN
   9337         (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9338                            PHY84834_PTP_EG_PTP_PKT_CFG_REG, 
   9339                            value, 
   9340                            ( PHY84834_PTP_EG_PTP_PKT_CFG_ACTION_PTP_SYNC
   9341                            | PHY84834_PTP_EG_PTP_PKT_CFG_ACTION_PTP_DREQ
   9342                            | PHY84834_PTP_EG_PTP_PKT_CFG_ACTION_PTP_PDREQ
   9343                            | PHY84834_PTP_EG_PTP_PKT_CFG_ACTION_PTP_PDRESP)) ); 
   9344     /* PTP RX action */
   9345     value = 0;
   9346     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) {
   9347         _phy84834_encode_ingress_message_mode(conf->rx_sync_mode, 0, &value);
   9348     }
   9349     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) {
   9350         _phy84834_encode_ingress_message_mode(conf->rx_delay_request_mode, 4, &value);
   9351     }
   9352     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) {
   9353         _phy84834_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 8, &value);
   9354     }
   9355     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) {
   9356         _phy84834_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 12, &value);
   9357     }
   9358     SOC_IF_ERROR_RETURN
   9359         (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9360                            PHY84834_PTP_IG_PTP_PKT_CFG_REG, 
   9361                            value, 
   9362                            ( PHY84834_PTP_IG_PTP_PKT_CFG_ACTION_PTP_SYNC
   9363                            | PHY84834_PTP_IG_PTP_PKT_CFG_ACTION_PTP_DREQ
   9364                            | PHY84834_PTP_IG_PTP_PKT_CFG_ACTION_PTP_PDREQ
   9365                            | PHY84834_PTP_IG_PTP_PKT_CFG_ACTION_PTP_PDRESP)) );                                    
   9366 
   9367     /* DPLL initial reference phase */
   9368     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   9369         /* [15:0] */
   9370         SOC_IF_ERROR_RETURN
   9371             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9372                         PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_0_REG, 
   9373                         (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 0xffff)));
   9374         /* [31:16]  */
   9375         SOC_IF_ERROR_RETURN
   9376             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9377                         PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_1_REG, 
   9378                         (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 0xffff)));
   9379         /* [47:32] */
   9380         SOC_IF_ERROR_RETURN
   9381             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9382                         PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_2_REG, 
   9383                         (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 0xffff)));
   9384         /* Enable loading shadow reg value to active copy on next framesync */
   9385         SOC_IF_ERROR_RETURN
   9386             (MODIFY_PHY8481_PMAD_REG(unit, pc,
   9387                                                PHY84834_PTP_NSE_SHDW_CTL_REG,
   9388                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PHASE,
   9389                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PHASE));
   9390     }
   9391 
   9392     /* DPLL REF PHASE */
   9393     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   9394         SOC_IF_ERROR_RETURN
   9395             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9396                                               PHY84834_PTP_NSE_DPLL_SHDW_REF_PERIOD_0_REG, 
   9397                                               conf->phy_1588_dpll_ref_phase_delta & 0xffff));
   9398         SOC_IF_ERROR_RETURN
   9399             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9400                                               PHY84834_PTP_NSE_DPLL_SHDW_REF_PERIOD_1_REG, 
   9401                                               (conf->phy_1588_dpll_ref_phase_delta >> 16) & 0xffff));
   9402          /* Enable loading shadow reg value to active copy on next framesync */
   9403         SOC_IF_ERROR_RETURN
   9404             (MODIFY_PHY8481_PMAD_REG(unit, pc,
   9405                                                PHY84834_PTP_NSE_SHDW_CTL_REG,
   9406                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PERIOD,
   9407                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PERIOD));
   9408     }
   9409 
   9410     /* DPLL K1 */
   9411     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   9412         SOC_IF_ERROR_RETURN
   9413             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9414                                               PHY84834_PTP_NSE_DPLL_SHDW_GAIN_1_REG, 
   9415                                               conf->phy_1588_dpll_k1 & 0x3f));
   9416        /* Enable loading shadow reg value to active copy on next framesync */
   9417         SOC_IF_ERROR_RETURN
   9418             (MODIFY_PHY8481_PMAD_REG(unit, pc,
   9419                                                PHY84834_PTP_NSE_SHDW_CTL_REG,
   9420                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN1,
   9421                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN1));
   9422     }
   9423 
   9424     /* DPLL K2 */
   9425     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   9426         SOC_IF_ERROR_RETURN
   9427             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9428                                               PHY84834_PTP_NSE_DPLL_SHDW_GAIN_2_REG, 
   9429                                               conf->phy_1588_dpll_k2 & 0x3f));
   9430        /* Enable loading shadow reg value to active copy on next framesync */
   9431         SOC_IF_ERROR_RETURN
   9432             (MODIFY_PHY8481_PMAD_REG(unit, pc,
   9433                                                PHY84834_PTP_NSE_SHDW_CTL_REG,
   9434                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN2,
   9435                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN2));
   9436     }
   9437 
   9438     /* DPLL K3 */
   9439     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   9440         SOC_IF_ERROR_RETURN
   9441             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9442                                               PHY84834_PTP_NSE_DPLL_SHDW_GAIN_3_REG, 
   9443                                               conf->phy_1588_dpll_k3 & 0x3f));
   9444        /* Enable loading shadow reg value to active copy on next framesync */
   9445         SOC_IF_ERROR_RETURN
   9446             (MODIFY_PHY8481_PMAD_REG(unit, pc,
   9447                                                PHY84834_PTP_NSE_SHDW_CTL_REG,
   9448                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN3,
   9449                                                PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN3));
   9450     }
   9451 
   9452     /* IEEE-1588 Gen-2 Inband operation */
   9453     if ( conf->validity_mask &
   9454                SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL ) {
   9455         /*
   9456          *  Inband control parameters setting
   9457          */
   9458         temp16 = (conf->inband_control.resv0_id
   9459                       << PHY848XX_PTP_INBAND_CNTL_RESV0_ID_SHIFT)
   9460                        & PHY848XX_PTP_INBAND_CNTL_RESV0_ID;
   9461         if ( conf->inband_control.flags &
   9462                         SOC_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE ) {
   9463             temp16 |= PHY848XX_PTP_INBAND_CNTL_SYNC_EN;
   9464         }
   9465         if ( conf->inband_control.flags &
   9466                         SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE ) {
   9467             temp16 |= PHY848XX_PTP_INBAND_CNTL_DREQ_EN;
   9468         }
   9469         if ( conf->inband_control.flags &
   9470                         SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE ) {
   9471             temp16 |= PHY848XX_PTP_INBAND_CNTL_PREQ_EN;
   9472         }
   9473         if ( conf->inband_control.flags &
   9474                         SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE ) {
   9475             temp16 |= PHY848XX_PTP_INBAND_CNTL_PRSP_EN;
   9476         }
   9477 
   9478         if ( conf->inband_control.flags &
   9479                         SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK ) {
   9480             temp16 |= PHY848XX_PTP_INBAND_CNTL_RESV0_ID_CHECK;
   9481         }
   9482         if ( conf->inband_control.flags &
   9483                         SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE ) {
   9484             temp16 |= PHY848XX_PTP_INBAND_CNTL_RESV0_ID_UPDATE;
   9485         }
   9486         if ( (conf->flags & SOC_PORT_PHY_TIMESYNC_FOLLOW_UP_ASSIST_ENABLE) ||
   9487              (conf->inband_control.flags &
   9488                         SOC_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST) ) {
   9489             temp16 |= PHY848XX_PTP_INBAND_CNTL_TS_UPD_FOLLOW_UP |
   9490                       PHY848XX_PTP_INBAND_CNTL_TS_CAP_MODE;
   9491         }
   9492         if ( (conf->flags & SOC_PORT_PHY_TIMESYNC_DELAY_RESP_ASSIST_ENABLE) ||
   9493              (conf->inband_control.flags &
   9494                         SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST) ) {
   9495             temp16 |= PHY848XX_PTP_INBAND_CNTL_TS_UPD_DELAY_RSP |
   9496                       PHY848XX_PTP_INBAND_CNTL_TS_CAP_MODE;
   9497         }
   9498         if ( conf->inband_control.flags &
   9499                         SOC_PORT_PHY_TIMESYNC_INBAND_TIMER_MODE_SELECT ) {
   9500             temp16 |= PHY848XX_PTP_INBAND_CNTL_TS_SEL;
   9501         }
   9502         if ( conf->inband_control.timer_mode &
   9503                         SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT ) {
   9504             temp16 |= PHY848XX_PTP_INBAND_CNTL_TS_SEL;
   9505 }
   9506         /* PTP Inband Control Register, 01.0xDC00  */
   9507         SOC_IF_ERROR_RETURN
   9508             (WRITE_PHY8481_PMAD_REG(unit, pc, 
   9509                                     PHY848XX_PTP_INBAND_CNTL_REG, temp16) );
   9510 
   9511         /* config the comparison of IP, VLAN & Source_Port in SOP memory */
   9512         temp16 = 0;
   9513         if ( conf->inband_control.flags &
   9514                         SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID) {
   9515             temp16 |= PHY848XX_PTP_INBAND_CTL2_CMP_VLAN_ID;
   9516         }
   9517         if ( conf->inband_control.flags &
   9518                         SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM) {
   9519             temp16 |= PHY848XX_PTP_INBAND_CTL2_CMP_SRC_PORT;
   9520         } 
   9521         if ( conf->inband_control.flags &
   9522                         SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR ) {
   9523             temp16 |= PHY848XX_PTP_INBAND_CTL2_CMP_IP_ADDR; 
   9524         }
   9525         /* PTP Inband Control 2 Register, 01.0xDC01  */
   9526         SOC_IF_ERROR_RETURN
   9527             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
   9528                                      PHY848XX_PTP_INBAND_CTL2_REG, temp16,
   9529                                      PHY848XX_PTP_INBAND_CTL2_CMP_MASK) );
   9530     } /* TIMESYNC_VALID_PHY_1588_INBAND_CONTROL */
   9531 
   9532     return SOC_E_NONE;
   9533 }
   9534 
   9535 /*
   9536  * Function:
   9537  *    phy84834_timesync_config_get
   9538  * Purpose:
   9539  *
   9540  * Parameters:
   9541  *
   9542  * Returns:
   9543  */
   9544 
   9545 int
   9546 phy84834_timesync_config_get(int unit, soc_port_t port,
   9547                              soc_port_phy_timesync_config_t *conf)
   9548 {
   9549     uint16  eg_config = 0, value = 0,
   9550             nse_sc_cfg = 0, nse_nco_cfg = 0, temp1, temp2, temp3, temp16 = 0 ;
   9551     soc_port_phy_timesync_global_mode_t gmode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   9552     soc_port_phy_timesync_framesync_mode_t framesync_mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE;
   9553     soc_port_phy_timesync_syncout_mode_t syncout_mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   9554     phy_ctrl_t *pc;
   9555 
   9556     pc = EXT_PHY_SW_STATE(unit, port);
   9557 
   9558     if ( PHY_IS_BCM8488X(pc) || (! PHY_IS_BCM8483X_AND_UP(pc)) ) {
   9559         return SOC_E_UNAVAIL;
   9560     }
   9561     conf->flags = 0;
   9562 
   9563     /* NSE SC CFG register */
   9564     SOC_IF_ERROR_RETURN
   9565         (READ_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_NSE_SC_CFG_REG, &nse_sc_cfg));
   9566 
   9567     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   9568         SOC_IF_ERROR_RETURN
   9569             (_phy84834_timesync_enable_get(unit, pc, &value ));
   9570 
   9571         if (value) {
   9572             conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE;
   9573         }
   9574 
   9575         /* Capture pkt info enabled 
   9576          * Note: Both tx and rx pkt capture need to be enabled 
   9577          * to consider this flag to be set
   9578          */
   9579         temp1 = temp2 = 0;
   9580         SOC_IF_ERROR_RETURN
   9581         (READ_PHY8481_PMAD_REG(unit, pc,
   9582                                PHY84834_PTP_EG_PTP_PKT_CFG_REG, &temp1));
   9583         SOC_IF_ERROR_RETURN
   9584         (READ_PHY8481_PMAD_REG(unit, pc,
   9585                                PHY84834_PTP_IG_PTP_PKT_CFG_REG, &temp2));
   9586 
   9587         if ( (temp1 & PHY84834_PTP_EG_PTP_PKT_CFG_CAPT_PTP_SYNC) &&
   9588              (temp2 & PHY84834_PTP_IG_PTP_PKT_CFG_CAPT_PTP_SYNC)) {
   9589             conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE; 
   9590         }
   9591 
   9592         /* The Heartbeat registers ensure that ToD is synchronized  *\
   9593         \* across the whole system.                                 */
   9594         if (nse_sc_cfg & PHY84834_PTP_NSE_SC_CFG_FSYNC_TS_EN) {
   9595             conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE;
   9596         }
   9597 
   9598         /* RX CRC -- Igress Parser Configuration Register, Reg. 1.DA81[0]  */
   9599         SOC_IF_ERROR_RETURN
   9600             (READ_PHY8481_PMAD_REG(unit, pc,
   9601                                    PHY84834_PTP_IG_CFG_REG, &temp16));
   9602         if ( temp16 & PHY84834_PTP_IG_CFG_FCS_CHECK_EN) {
   9603             conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE;
   9604         }
   9605 
   9606         /* EG Config: addr check enable & packet detection  *\
   9607         \* Egress Parser Configuration Register  1.DA01     */
   9608         SOC_IF_ERROR_RETURN
   9609             (READ_PHY8481_PMAD_REG(unit, pc,
   9610                                    PHY84834_PTP_EG_CFG_REG, &eg_config));
   9611         if ( eg_config & PHY84834_PTP_IG_CFG_L2_802AS_EN ) {
   9612             conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE |
   9613                            SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE;
   9614         }
   9615         if ( eg_config & PHY84834_PTP_IG_CFG_L4_IP4_UDP_EN ) {
   9616             conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE;
   9617         }
   9618         if ( eg_config & PHY84834_PTP_IG_CFG_L4_IP6_UDP_EN ) {
   9619             conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE;
   9620         }
   9621 #if 0
   9622         if (eg_config & PHY84834_PTP_EG_CFG_L4_IP6_UDP_ACH_EN) {
   9623             eg_config |= SOC_PORT_PHY_TIMESYNC_L4_IPV6_ADDR_ENABLE;
   9624         }
   9625         if (eg_config & PHY84834_PTP_EG_CFG_L4_IP4_UDP_ACH_EN) {
   9626             eg_config |= SOC_PORT_PHY_TIMESYNC_L4_IP_ADDR_ENABLE;
   9627         }
   9628         if (eg_config & PHY84834_PTP_IG_CFG_L2_802AS_ACH_EN) { 
   9629             eg_config |= SOC_PORT_PHY_TIMESYNC_L2_DS_ENABLE 
   9630                          | SOC_PORT_PHY_TIMESYNC_AS_DS_ENABLE;
   9631         } 
   9632 #endif
   9633         /* CLK src for NCO */
   9634         SOC_IF_ERROR_RETURN
   9635             (READ_PHY8481_PMAD_REG(unit, pc, 
   9636                                    PHY84834_PTP_NSE_NCO_CFG_REG, &nse_nco_cfg));
   9637 
   9638         if ( nse_nco_cfg & PHY84834_PTP_NSE_NCO_CFG_FCW_SEL ) {
   9639             conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT;
   9640         }
   9641     }
   9642 
   9643 
   9644     /* Gmode */
   9645     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) {
   9646         _phy84834_decode_gmode(nse_sc_cfg ,&gmode);
   9647         conf->gmode = gmode;
   9648     }
   9649 
   9650     /* Framesync */
   9651     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) {
   9652         _phy84834_decode_framesync_mode((nse_sc_cfg >> 4), &framesync_mode);
   9653         conf->framesync.mode = framesync_mode;
   9654         /* Length threshold */
   9655         SOC_IF_ERROR_RETURN
   9656             (READ_PHY8481_PMAD_REG(unit, pc,
   9657                                         PHY84834_NSE_SYNCIN_FSYNC_LEN_1_REG,
   9658                                         &temp16)); /*[18:16]*/
   9659         conf->framesync.length_threshold = (temp16 & 0x7); 
   9660         conf->framesync.length_threshold <<= 16;
   9661  
   9662         SOC_IF_ERROR_RETURN
   9663             (READ_PHY8481_PMAD_REG(unit, pc, 
   9664                                         PHY84834_NSE_SYNCIN_FSYNC_LEN_0_REG, 
   9665                                         &temp16));/*[15:0]*/
   9666         conf->framesync.length_threshold |= temp16;
   9667 
   9668         /* Event offset */
   9669         SOC_IF_ERROR_RETURN
   9670             (READ_PHY8481_PMAD_REG(unit, pc,
   9671                                         PHY84834_NSE_SYNCIN_FSYNC_DLY_1_REG,
   9672                                         &temp16)); /*[18:16]*/
   9673         conf->framesync.event_offset = (temp16 & 0x7);
   9674         conf->framesync.event_offset <<= 16;
   9675 
   9676         SOC_IF_ERROR_RETURN
   9677             (READ_PHY8481_PMAD_REG(unit, pc, 
   9678                                         PHY84834_NSE_SYNCIN_FSYNC_DLY_0_REG, 
   9679                                         &temp16));/*[15:0]*/
   9680         conf->framesync.event_offset |= temp16;
   9681 
   9682     }
   9683 
   9684     /* SYNC OUT */
   9685     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) {
   9686         _phy84834_decode_syncout_mode((nse_sc_cfg >> 8), &syncout_mode);
   9687         conf->syncout.mode = syncout_mode;
   9688         
   9689         /* Syncout interval */   
   9690         SOC_IF_ERROR_RETURN
   9691             (READ_PHY8481_PMAD_REG(unit, pc,
   9692                                               PHY84834_PTP_NSE_SHDW_SOUT_INTERVAL_1_REG,
   9693                                               &temp16));
   9694         conf->syncout.interval = temp16;
   9695         conf->syncout.interval <<= 16;
   9696  
   9697         SOC_IF_ERROR_RETURN
   9698             (READ_PHY8481_PMAD_REG(unit, pc, 
   9699                                               PHY84834_PTP_NSE_SHDW_SOUT_INTERVAL_0_REG, 
   9700                                               &temp16));
   9701         conf->syncout.interval |= temp16;
   9702         
   9703         /* Syncout pulse 1 */
   9704         temp16 = 0;
   9705         SOC_IF_ERROR_RETURN
   9706             (READ_PHY8481_PMAD_REG(unit, pc, 
   9707                                               PHY84834_PTP_NSE_SHDW_SOUT_PULSE1_LEN_REG, 
   9708                                               &temp16));
   9709         conf->syncout.pulse_1_length =  temp16 & 0x0fff;
   9710         
   9711         /* Syncout pulse 2 */
   9712         temp16 = 0;
   9713         SOC_IF_ERROR_RETURN
   9714             (READ_PHY8481_PMAD_REG(unit, pc, 
   9715                                               PHY84834_PTP_NSE_SHDW_SOUT_PULSE2_LEN_REG, 
   9716                                               &temp16));
   9717         conf->syncout.pulse_2_length =  temp16 & 0x0fff;
   9718 
   9719         /* Syncout timestamp match value */
   9720         SOC_IF_ERROR_RETURN
   9721             (READ_PHY8481_PMAD_REG(unit, pc, 
   9722                                               PHY84834_PTP_NSE_SOUT_TS_CMP_0_REG, 
   9723                                               &temp1));
   9724         SOC_IF_ERROR_RETURN
   9725             (READ_PHY8481_PMAD_REG(unit, pc, 
   9726                                               PHY84834_PTP_NSE_SOUT_TS_CMP_1_REG, 
   9727                                               &temp2));
   9728         SOC_IF_ERROR_RETURN
   9729             (READ_PHY8481_PMAD_REG(unit, pc, 
   9730                                               PHY84834_PTP_NSE_SOUT_TS_CMP_2_REG, 
   9731                                               &temp3));
   9732         COMPILER_64_SET(conf->syncout.syncout_ts, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1)));
   9733     }
   9734 
   9735     /* VLAN TAG register */
   9736     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) {
   9737         SOC_IF_ERROR_RETURN
   9738             (READ_PHY8481_PMAD_REG(unit, pc, 
   9739                                               PHY84834_PTP_VLAN_1TAG_TPID_REG,
   9740                                               &conf->itpid));
   9741     }
   9742 
   9743     /* OUTER VLAN TAG register */
   9744     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) {
   9745         SOC_IF_ERROR_RETURN
   9746             (READ_PHY8481_PMAD_REG(unit, pc, 
   9747                                               PHY84834_PTP_VLAN_2TAG_OTPID_REG, 
   9748                                               &conf->otpid));
   9749     }
   9750 
   9751     /* INNER VLAN TAG register */
   9752     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) {
   9753         SOC_IF_ERROR_RETURN
   9754             (READ_PHY8481_PMAD_REG(unit, pc, 
   9755                                               PHY84834_PTP_VLAN_2TAG_OTPID_1_REG,
   9756                                               &conf->otpid2));
   9757     }
   9758 
   9759     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) {
   9760         SOC_IF_ERROR_RETURN
   9761             (READ_PHY8481_PMAD_REG(unit, pc, 
   9762                                               PHY84834_PTP_NSE_SHDW_DPLL_SYNC_DIV_REG, 
   9763                                               &conf->ts_divider));
   9764         conf->ts_divider &= 0xfff;
   9765     }
   9766 
   9767     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) {
   9768          /* Do nothing
   9769          *
   9770          * In some chips there are two registers Rx timestamp offset & 
   9771          * Rx link delay. These two registers do similar funtion. 
   9772          * The offset is added to the internal timestamp, the 
   9773          * link delay is subtracted from it. Rx link delay control not required 
   9774          * in this chip. Tx/RX timestamp offset does the job. The signed value will
   9775          * be added to the timestamp.
   9776          */
   9777     }
   9778 
   9779     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) {
   9780         /* TIME CODE 0 register */
   9781         SOC_IF_ERROR_RETURN
   9782             (READ_PHY8481_PMAD_REG(unit, pc, 
   9783                                               PHY84834_PTP_NSE_SHDW_ORG_TS_0_REG, 
   9784                                               &temp1));
   9785 
   9786         /* TIME CODE 1 register */
   9787         SOC_IF_ERROR_RETURN
   9788             (READ_PHY8481_PMAD_REG(unit, pc, 
   9789                                               PHY84834_PTP_NSE_SHDW_ORG_TS_1_REG, 
   9790                                               &temp2));
   9791 
   9792         conf->original_timecode.nanoseconds = ((uint32)temp2 << 16) | temp1; 
   9793 
   9794         /* TIME CODE 2 register */
   9795         SOC_IF_ERROR_RETURN
   9796             (READ_PHY8481_PMAD_REG(unit, pc, 
   9797                                               PHY84834_PTP_NSE_SHDW_ORG_TS_2_REG, 
   9798                                               &temp1));
   9799         /* TIME CODE 3 register */
   9800         SOC_IF_ERROR_RETURN
   9801             (READ_PHY8481_PMAD_REG(unit, pc, 
   9802                                               PHY84834_PTP_NSE_SHDW_ORG_TS_3_REG, 
   9803                                               &temp2));
   9804         /* TIME CODE 4 register */
   9805         SOC_IF_ERROR_RETURN
   9806             (READ_PHY8481_PMAD_REG(unit, pc, 
   9807                                               PHY84834_PTP_NSE_SHDW_ORG_TS_4_REG, 
   9808                                               &temp3));
   9809         COMPILER_64_SET(conf->original_timecode.seconds, ((uint32)temp3),  (((uint32)temp2<<16)|((uint32)temp1)));
   9810     }
   9811 
   9812     /* TX TS OFFSET register */
   9813     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) {
   9814 
   9815         SOC_IF_ERROR_RETURN
   9816             (READ_PHY8481_PMAD_REG(unit, pc, 
   9817                                               PHY84834_PTP_TS_EG_SOP_OFFSET_0_REG, 
   9818                                               &temp1));
   9819         SOC_IF_ERROR_RETURN
   9820             (READ_PHY8481_PMAD_REG(unit, pc, 
   9821                                               PHY84834_PTP_TS_EG_SOP_OFFSET_1_REG, 
   9822                                               &temp2));
   9823         conf->tx_timestamp_offset = ((uint32)temp2 & 0xf) << 16 | temp1;
   9824     }
   9825     
   9826     /* RX TS OFFSET register */
   9827     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) {
   9828         SOC_IF_ERROR_RETURN
   9829             (READ_PHY8481_PMAD_REG(unit, pc, 
   9830                                               PHY84834_PTP_TS_IG_SOP_OFFSET_0_REG, 
   9831                                               (uint16 *)&temp1));
   9832         SOC_IF_ERROR_RETURN
   9833             (READ_PHY8481_PMAD_REG(unit, pc, 
   9834                                               PHY84834_PTP_TS_IG_SOP_OFFSET_1_REG, 
   9835                                               &temp2));
   9836         conf->rx_timestamp_offset = ((uint32)temp2 & 0xf) << 16 | temp1;
   9837     }
   9838 
   9839     /* PTP TX action */
   9840     SOC_IF_ERROR_RETURN
   9841         (READ_PHY8481_PMAD_REG(unit, pc, 
   9842                                PHY84834_PTP_EG_PTP_PKT_CFG_REG, &value)); 
   9843 
   9844     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) {
   9845         _phy84834_decode_egress_message_mode(value, 0, &conf->tx_sync_mode);
   9846     }
   9847 
   9848     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) {
   9849         _phy84834_decode_egress_message_mode(value, 4, &conf->tx_delay_request_mode);
   9850     }
   9851 
   9852     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) {
   9853         _phy84834_decode_egress_message_mode(value, 8, &conf->tx_pdelay_request_mode);
   9854     }
   9855 
   9856     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) {
   9857         _phy84834_decode_egress_message_mode(value, 12, &conf->tx_pdelay_response_mode);
   9858     }
   9859                                             
   9860     /* PTP RX action */
   9861     SOC_IF_ERROR_RETURN
   9862         (READ_PHY8481_PMAD_REG(unit, pc, 
   9863                                PHY84834_PTP_IG_PTP_PKT_CFG_REG, &value)); 
   9864 
   9865     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) {
   9866         _phy84834_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode);
   9867     }
   9868 
   9869     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) {
   9870         _phy84834_decode_ingress_message_mode(value, 4, &conf->rx_delay_request_mode);
   9871     }
   9872 
   9873     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) {
   9874         _phy84834_decode_ingress_message_mode(value, 8, &conf->rx_pdelay_request_mode);
   9875     }
   9876 
   9877     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) {
   9878         _phy84834_decode_ingress_message_mode(value, 12, &conf->rx_pdelay_response_mode);
   9879     }
   9880 
   9881     /* DPLL initial reference phase */                                       
   9882     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   9883         /* [15:0] */
   9884         SOC_IF_ERROR_RETURN
   9885             (READ_PHY8481_PMAD_REG(unit, pc, 
   9886                                               PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_0_REG, 
   9887                                               &temp1));
   9888 
   9889         /* [31:16] */
   9890         SOC_IF_ERROR_RETURN
   9891             (READ_PHY8481_PMAD_REG(unit, pc, 
   9892                                               PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_1_REG, 
   9893                                               &temp2));
   9894 
   9895         /* [47:32] */
   9896         SOC_IF_ERROR_RETURN
   9897             (READ_PHY8481_PMAD_REG(unit, pc, 
   9898                                               PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_2_REG, 
   9899                                               &temp3));
   9900 
   9901         COMPILER_64_SET(conf->phy_1588_dpll_ref_phase, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1)));
   9902     }
   9903 
   9904     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   9905         SOC_IF_ERROR_RETURN
   9906             (READ_PHY8481_PMAD_REG(unit, pc, 
   9907                                               PHY84834_PTP_NSE_DPLL_SHDW_REF_PERIOD_0_REG, 
   9908                                               &temp1));
   9909         SOC_IF_ERROR_RETURN
   9910             (READ_PHY8481_PMAD_REG(unit, pc, 
   9911                                               PHY84834_PTP_NSE_DPLL_SHDW_REF_PERIOD_1_REG, 
   9912                                               &temp2));
   9913 
   9914         conf->phy_1588_dpll_ref_phase_delta = ((uint32)temp2 << 16) | temp1; 
   9915     }
   9916 
   9917     /* DPLL K1 */
   9918     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   9919         SOC_IF_ERROR_RETURN
   9920             (READ_PHY8481_PMAD_REG(unit, pc, 
   9921                                               PHY84834_PTP_NSE_DPLL_SHDW_GAIN_1_REG, 
   9922                                               &conf->phy_1588_dpll_k1)); 
   9923         conf->phy_1588_dpll_k1 &= 0x3f;
   9924     }
   9925 
   9926     /* DPLL K2 */
   9927     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   9928         SOC_IF_ERROR_RETURN
   9929             (READ_PHY8481_PMAD_REG(unit, pc, 
   9930                                               PHY84834_PTP_NSE_DPLL_SHDW_GAIN_2_REG, 
   9931                                               &conf->phy_1588_dpll_k2)); 
   9932         conf->phy_1588_dpll_k2 &= 0x3f;
   9933     }
   9934 
   9935     /* DPLL K3 */
   9936     if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   9937         SOC_IF_ERROR_RETURN
   9938             (READ_PHY8481_PMAD_REG(unit, pc, 
   9939                                               PHY84834_PTP_NSE_DPLL_SHDW_GAIN_3_REG, 
   9940                                               &conf->phy_1588_dpll_k3)); 
   9941         conf->phy_1588_dpll_k3 &= 0x3f;
   9942     }
   9943 
   9944     /* IEEE-1588 Gen-2 Inband operations */
   9945     if ( (conf->validity_mask &
   9946                 SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL) ) {
   9947         /* PTP Inband Control Register, 1.0xDC00  */
   9948         SOC_IF_ERROR_RETURN
   9949             (READ_PHY8481_PMAD_REG(unit, pc, 
   9950                                    PHY848XX_PTP_INBAND_CNTL_REG, &temp16) );
   9951         conf->inband_control.resv0_id =         /* Rev0_ID[7:4] */
   9952                 (temp16 & PHY848XX_PTP_INBAND_CNTL_RESV0_ID)
   9953                  >> PHY848XX_PTP_INBAND_CNTL_RESV0_ID_SHIFT;
   9954 
   9955         if ( temp16 & PHY848XX_PTP_INBAND_CNTL_SYNC_EN ) {
   9956             conf->inband_control.flags |=
   9957                 SOC_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE;
   9958         }
   9959         if ( temp16 & PHY848XX_PTP_INBAND_CNTL_DREQ_EN ) {
   9960             conf->inband_control.flags |=
   9961                 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE;
   9962         }
   9963         if ( temp16 & PHY848XX_PTP_INBAND_CNTL_PREQ_EN ) {
   9964             conf->inband_control.flags |=
   9965                 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE;
   9966         }
   9967         if ( temp16 & PHY848XX_PTP_INBAND_CNTL_PRSP_EN ) {
   9968             conf->inband_control.flags |=
   9969                 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE;
   9970         }
   9971 
   9972         if ( temp16 & PHY848XX_PTP_INBAND_CNTL_RESV0_ID_CHECK ) {
   9973             conf->inband_control.flags |=
   9974                 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK;
   9975         }
   9976         if ( temp16 & PHY848XX_PTP_INBAND_CNTL_RESV0_ID_UPDATE ) {
   9977             conf->inband_control.flags |=
   9978                 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE;
   9979         }
   9980         if ( temp16 & PHY848XX_PTP_INBAND_CNTL_TS_UPD_FOLLOW_UP ) {
   9981             conf->inband_control.flags |=
   9982                 SOC_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST;
   9983             conf->flags |=
   9984                 SOC_PORT_PHY_TIMESYNC_FOLLOW_UP_ASSIST_ENABLE;
   9985         }
   9986         if ( temp16 & PHY848XX_PTP_INBAND_CNTL_TS_UPD_DELAY_RSP ) {
   9987             conf->inband_control.flags |=
   9988                 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST;
   9989             conf->flags |=
   9990                 SOC_PORT_PHY_TIMESYNC_DELAY_RESP_ASSIST_ENABLE;
   9991         }
   9992         if ( temp16 & PHY848XX_PTP_INBAND_CNTL_TS_SEL ) {
   9993             conf->inband_control.timer_mode |=
   9994                       SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT;
   9995         } else {
   9996             conf->inband_control.timer_mode |=
   9997                       SOC_PORT_PHY_TIMESYNC_TIMER_MODE_48BIT;
   9998         }
   9999         if ( temp16 & PHY848XX_PTP_INBAND_CNTL_IP_ADDR_EN ) {
  10000             if ( temp16 & PHY848XX_PTP_INBAND_CNTL_IP_MAC_SEL ) {
  10001                 conf->inband_control.flags |=
  10002                       SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR;
  10003             } else {
  10004                 conf->inband_control.flags |=
  10005                       SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR;
  10006             }
  10007         }
  10008 
  10009         /* PTP Inband Control 2 Register, 01.0xDC01  */
  10010         SOC_IF_ERROR_RETURN
  10011             (READ_PHY8481_PMAD_REG(unit, pc, 
  10012                                    PHY848XX_PTP_INBAND_CTL2_REG, &temp16) );
  10013         /* comparison of IP, VLAN & Source_Port in SOP memory */
  10014         if ( temp16 & PHY848XX_PTP_INBAND_CTL2_CMP_VLAN_ID ) {
  10015             conf->inband_control.flags |=
  10016                       SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID;
  10017         }
  10018         if ( temp16 & PHY848XX_PTP_INBAND_CTL2_CMP_SRC_PORT ) {
  10019             conf->inband_control.flags |=
  10020                       SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM;
  10021         }
  10022         if ( temp16 & PHY848XX_PTP_INBAND_CTL2_CMP_IP_ADDR ) {
  10023             conf->inband_control.flags |=
  10024                       SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR;
  10025         }
  10026     } /* SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL */
  10027 
  10028     return SOC_E_NONE;
  10029 }
  10030 
  10031 
  10032 /*
  10033  * Function:
  10034  *    phy84834_timesync_control_set
  10035  * Purpose:
  10036  *
  10037  * Parameters:
  10038  *
  10039  * Returns:
  10040  */
  10041 int
  10042 phy84834_timesync_control_set(int unit, soc_port_t port,
  10043                               soc_port_control_phy_timesync_t type,
  10044                               uint64 value)
  10045 {
  10046     uint16 temp1, temp2; 
  10047     uint32 value0;
  10048     phy_ctrl_t *pc;
  10049 
  10050     pc = EXT_PHY_SW_STATE(unit, port);
  10051 
  10052     if ( PHY_IS_BCM8488X(pc) || (! PHY_IS_BCM8483X_AND_UP(pc)) ) {
  10053         return SOC_E_UNAVAIL;
  10054     }
  10055 
  10056     switch (type) {
  10057 
  10058     case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
  10059     case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
  10060         return SOC_E_UNAVAIL;
  10061 
  10062 
  10063     case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
  10064         SOC_IF_ERROR_RETURN
  10065             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
  10066                           PHY84834_PTP_NSE_NCO_CFG_REG, 
  10067                           NCO_SHADOW_REG_STATIC_FCW,
  10068                           PHY84834_PTP_NSE_NCO_CFG_FCW_SEL));
  10069         SOC_IF_ERROR_RETURN
  10070             (WRITE_PHY8481_PMAD_REG(unit, pc, 
  10071                           PHY84834_NSE_NCO_SHADOW_FCW_0_REG, 
  10072                           (uint16)(COMPILER_64_LO(value) & 0xffff)));
  10073         SOC_IF_ERROR_RETURN
  10074             (WRITE_PHY8481_PMAD_REG(unit, pc, 
  10075                           PHY84834_NSE_NCO_SHADOW_FCW_1_REG, 
  10076                           (uint16)((COMPILER_64_LO(value) >> 16) & 0xffff)));
  10077         /* Enable loading of shadow reg on next framesync */
  10078         SOC_IF_ERROR_RETURN
  10079             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
  10080                           PHY84834_PTP_NSE_SHDW_CTL_REG, 
  10081                           PHY84834_PTP_NSE_SHDW_CTL_LOAD_NCO_FCW,
  10082                           PHY84834_PTP_NSE_SHDW_CTL_LOAD_NCO_FCW));
  10083         break;
  10084 
  10085     case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC:
  10086         SOC_IF_ERROR_RETURN
  10087             (MODIFY_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_NSE_SC_CFG_REG,
  10088                           (uint16) ((COMPILER_64_LO(value) & 0x07) << 4),
  10089                           PHY84834_PTP_NSE_SC_CFG_SI_MODE));
  10090         break;
  10091 
  10092     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
  10093         SOC_IF_ERROR_RETURN
  10094             (WRITE_PHY8481_PMAD_REG(unit, pc, 
  10095                                               PHY84834_NSE_NCO_SHADOW_TIME_HIGH_0_REG, 
  10096                                               (uint16)(COMPILER_64_LO(value) & 0xffff)));
  10097         SOC_IF_ERROR_RETURN
  10098             (WRITE_PHY8481_PMAD_REG(unit, pc, 
  10099                                               PHY84834_NSE_NCO_SHADOW_TIME_HIGH_1_REG, 
  10100                                               (uint16)((COMPILER_64_LO(value) >> 16) & 0xffff)));
  10101         SOC_IF_ERROR_RETURN
  10102             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
  10103                                                PHY84834_NSE_NCO_SHADOW_TIME_HIGH_2_REG, 
  10104                                                (uint16)COMPILER_64_HI(value), 0x0fff));
  10105         /* Enable loading of shadow reg on next framesync */
  10106         SOC_IF_ERROR_RETURN
  10107             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
  10108                                               PHY84834_PTP_NSE_SHDW_CTL_REG, 
  10109                                               PHY84834_PTP_NSW_SHDW_CTL_LOAD_COUNT_HIGH,
  10110                                               PHY84834_PTP_NSW_SHDW_CTL_LOAD_COUNT_HIGH));
  10111         break;
  10112 
  10113     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
  10114         temp1 = temp2 = 0;
  10115         value0 = COMPILER_64_LO(value);
  10116 
  10117         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) {
  10118             temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_ORIG_TS;
  10119         }
  10120         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) {
  10121             temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_ORIG_TS;
  10122         }
  10123         if (value0 &  SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) {
  10124             temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNCOUT;
  10125         }
  10126         if (value0 &  SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) {
  10127             temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_SYNCOUT;
  10128         }
  10129         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) {
  10130             temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNC_DIV;
  10131         }
  10132         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) {
  10133             temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_SYNC_DIV;
  10134         }
  10135         if (value0 &  SOC_PORT_PHY_TIMESYNC_TN_LOAD) {
  10136             temp1 |= PHY84834_PTP_NSW_SHDW_CTL_LOAD_NTP_TIME;
  10137         }
  10138         if (value0 &  SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) {
  10139             temp2 |= PHY84834_PTP_NSW_SHDW_CLR_LOAD_NTP_TIME;
  10140         }
  10141         if (value0 &  SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) {
  10142             temp1 |= PHY84834_PTP_NSW_SHDW_CTL_LOAD_TIME_COUNT;
  10143         }
  10144         if (value0 &  SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) {
  10145             temp2 |= PHY84834_PTP_NSW_SHDW_CLR_LOAD_TIME_COUNT;
  10146         }
  10147         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) {
  10148             temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_NCO_FCW;
  10149         }
  10150         if (value0 &  SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) {
  10151             temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_NCO_FCW;
  10152         }
  10153         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) {
  10154             temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_FCW;
  10155         }
  10156         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) {
  10157             temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_FCW;
  10158         }
  10159         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) {
  10160             temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PHASE;
  10161         }
  10162         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) {
  10163             temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_REF_PHASE;
  10164         }
  10165         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) {
  10166             temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PERIOD;
  10167         }
  10168         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) {
  10169             temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_REF_PERIOD;
  10170         }
  10171         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) {
  10172             temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN3;
  10173         }
  10174         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) {
  10175             temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN3;
  10176         }
  10177         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) {
  10178             temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN2;
  10179         }
  10180         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) {
  10181             temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN2;
  10182         }
  10183         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) {
  10184             temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN1;
  10185         }
  10186         if (value0 &  SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) {
  10187             temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN1;
  10188         }
  10189         SOC_IF_ERROR_RETURN
  10190             (WRITE_PHY8481_PMAD_REG(unit, pc, 
  10191                                     PHY84834_PTP_NSE_SHDW_CTL_REG, temp1));
  10192         SOC_IF_ERROR_RETURN
  10193             (WRITE_PHY8481_PMAD_REG(unit, pc, 
  10194                                     PHY84834_PTP_NSE_SHDW_CLR_REG, temp2));
  10195         break;
  10196 
  10197     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
  10198         temp1 = 0;
  10199         value0 = COMPILER_64_LO(value);
  10200 
  10201         if (value0 &  SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT) {
  10202             temp1 |= PHY84834_PTP_INT_PIC_EN;
  10203         }
  10204         if (value0 &  SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT) {
  10205             temp1 |= PHY84834_PTP_INT_FSYNC_EN;
  10206         }
  10207         SOC_IF_ERROR_RETURN
  10208             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
  10209                                               PHY84834_PTP_INT_EN_REG, 
  10210                                               temp1,
  10211                                               (PHY84834_PTP_INT_PIC_EN |
  10212                                                PHY84834_PTP_INT_FSYNC_EN)));
  10213         break;
  10214 
  10215     case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
  10216         value0 = COMPILER_64_LO(value);
  10217         SOC_IF_ERROR_RETURN
  10218             (WRITE_PHY8481_PMAD_REG(unit, pc, 
  10219                                                PHY84834_PTP_TS_EG_SOP_OFFSET_0_REG, 
  10220                                                (uint16)(value0 & 0xffff))); 
  10221         SOC_IF_ERROR_RETURN
  10222             (WRITE_PHY8481_PMAD_REG(unit, pc, 
  10223                                                PHY84834_PTP_TS_EG_SOP_OFFSET_1_REG, 
  10224                                                (uint16)((value0 >> 16) & 0xf))); 
  10225         break;
  10226 
  10227     case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
  10228         value0 = COMPILER_64_LO(value);
  10229         SOC_IF_ERROR_RETURN
  10230             (WRITE_PHY8481_PMAD_REG(unit, pc, 
  10231                                                PHY84834_PTP_TS_IG_SOP_OFFSET_0_REG, 
  10232                                                (uint16)(value0 & 0xffff))); 
  10233         SOC_IF_ERROR_RETURN
  10234             (WRITE_PHY8481_PMAD_REG(unit, pc, 
  10235                                                PHY84834_PTP_TS_IG_SOP_OFFSET_1_REG, 
  10236                                                (uint16)((value0 >> 16) & 0xf)));
  10237         break;
  10238 
  10239     default:
  10240         return SOC_E_UNAVAIL;
  10241         break;
  10242     }
  10243 
  10244     return SOC_E_NONE;
  10245 }
  10246 
  10247 /*
  10248  * Function:
  10249  *    phy84834_timesync_control_get
  10250  * Purpose:
  10251  *
  10252  * Parameters:
  10253  *
  10254  * Returns:
  10255  */
  10256 int
  10257 phy84834_timesync_control_get(int unit, soc_port_t port,
  10258                               soc_port_control_phy_timesync_t type,
  10259                               uint64 *value)
  10260 {
  10261     uint16 value0 = 0;
  10262     uint16 value1 = 0;
  10263     uint16 value2 = 0;
  10264     uint16 value3 = 0;
  10265     uint32 value32;
  10266     phy_ctrl_t *pc;
  10267 
  10268     pc = EXT_PHY_SW_STATE(unit, port);
  10269 
  10270     if ( PHY_IS_BCM8488X(pc) || (! PHY_IS_BCM8483X_AND_UP(pc)) ) {
  10271         return SOC_E_UNAVAIL;
  10272     }
  10273 
  10274     switch (type) {
  10275     case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
  10276 
  10277         SOC_IF_ERROR_RETURN
  10278             (READ_PHY8481_PMAD_REG(unit, pc,
  10279                           PHY84834_PTP_NSE_SC_COUNTSTAMP_FSYNC_0_REG,
  10280                           &value0));
  10281         SOC_IF_ERROR_RETURN
  10282             (READ_PHY8481_PMAD_REG(unit, pc,
  10283                           PHY84834_PTP_NSE_SC_COUNTSTAMP_FSYNC_1_REG,
  10284                           &value1));
  10285         SOC_IF_ERROR_RETURN
  10286             (READ_PHY8481_PMAD_REG(unit, pc,
  10287                           PHY84834_PTP_NSE_SC_COUNTSTAMP_FSYNC_2_REG,
  10288                           &value2));
  10289         COMPILER_64_SET((*value), (((uint32)value3<<16)|((uint32)value2)),
  10290                                   (((uint32)value1<<16)|((uint32)value0)));
  10291         break;
  10292 
  10293     case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
  10294 
  10295         SOC_IF_ERROR_RETURN
  10296             (READ_PHY8481_PMAD_REG(unit, pc,
  10297                           PHY84834_PTP_PIC_FIFO_RD_PKT_TS_0_REG,
  10298                           &value0));
  10299         SOC_IF_ERROR_RETURN
  10300             (READ_PHY8481_PMAD_REG(unit, pc,
  10301                           PHY84834_PTP_PIC_FIFO_RD_PKT_TS_1_REG,
  10302                           &value1));
  10303         SOC_IF_ERROR_RETURN
  10304             (READ_PHY8481_PMAD_REG(unit, pc,
  10305                           PHY84834_PTP_PIC_FIFO_RD_PKT_TS_2_REG,
  10306                           &value2));
  10307         SOC_IF_ERROR_RETURN
  10308             (MODIFY_PHY8481_PMAD_REG(unit, pc,
  10309                           PHY84834_PTP_PIC_FIFO_CTL_REG, 0x0001, 0x0001)); 
  10310 
  10311         COMPILER_64_SET((*value), (((uint32)value3<<16)|((uint32)value2)),
  10312                                   (((uint32)value1<<16)|((uint32)value0)));
  10313         break;
  10314 
  10315     case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
  10316         SOC_IF_ERROR_RETURN
  10317             (READ_PHY8481_PMAD_REG(unit, pc, 
  10318                           PHY84834_NSE_NCO_SHADOW_FCW_0_REG, 
  10319                           &value0));
  10320         SOC_IF_ERROR_RETURN
  10321             (READ_PHY8481_PMAD_REG(unit, pc, 
  10322                           PHY84834_NSE_NCO_SHADOW_FCW_1_REG, 
  10323                           &value1));
  10324         COMPILER_64_SET((*value), (((uint32)value3<<16)|((uint32)value2)),
  10325                                   (((uint32)value1<<16)|((uint32)value0)));
  10326         break;
  10327 
  10328     case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC:
  10329         SOC_IF_ERROR_RETURN
  10330             (READ_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_NSE_SC_CFG_REG,
  10331                                              &value0));
  10332         COMPILER_64_SET((*value),  0,
  10333                         (value0 & (PHY84834_PTP_NSE_SC_CFG_SI_MODE)) >> 4);
  10334         LOG_WARN(BSL_LS_SOC_PHY, (BSL_META_U(unit, "u=%d p=%d v0=0x%x v=0x%x\n"), unit,pc->port,value0,(COMPILER_64_LO(*value))));
  10335         break;
  10336 
  10337     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
  10338         SOC_IF_ERROR_RETURN
  10339             (READ_PHY8481_PMAD_REG(unit, pc, 
  10340                           PHY84834_NSE_NCO_SHADOW_TIME_HIGH_0_REG, 
  10341                           &value0)); 
  10342         SOC_IF_ERROR_RETURN
  10343             (READ_PHY8481_PMAD_REG(unit, pc, 
  10344                           PHY84834_NSE_NCO_SHADOW_TIME_HIGH_1_REG, 
  10345                           &value1)); 
  10346         SOC_IF_ERROR_RETURN
  10347             (READ_PHY8481_PMAD_REG(unit, pc, 
  10348                           PHY84834_NSE_NCO_SHADOW_TIME_HIGH_2_REG, 
  10349                           &value2)); 
  10350 
  10351         COMPILER_64_SET((*value), ((uint32)(value2 & 0x0fff)),
  10352                                   (((uint32)value1<<16)|((uint32)value0)));
  10353         break;
  10354 
  10355     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
  10356         value32 = 0;
  10357         SOC_IF_ERROR_RETURN
  10358             (READ_PHY8481_PMAD_REG(unit, pc, 
  10359                                    PHY84834_PTP_NSE_SHDW_CTL_REG, &value1));
  10360         SOC_IF_ERROR_RETURN
  10361             (READ_PHY8481_PMAD_REG(unit, pc, 
  10362                                    PHY84834_PTP_NSE_SHDW_CLR_REG, &value2));
  10363         if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_ORIG_TS) {
  10364             value32 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD;
  10365         }
  10366         if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_ORIG_TS) {
  10367             value32 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD;
  10368         }
  10369         if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNCOUT) {
  10370             value32 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD;
  10371         }
  10372         if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_SYNCOUT) {
  10373             value32 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD;
  10374         }
  10375         if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNC_DIV) {
  10376             value32 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD;
  10377         }
  10378         if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_SYNC_DIV) {
  10379             value32 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD;
  10380         }
  10381         if (value1 & PHY84834_PTP_NSW_SHDW_CTL_LOAD_NTP_TIME) {
  10382             value32 |= SOC_PORT_PHY_TIMESYNC_TN_LOAD;
  10383         }
  10384         if (value2 & PHY84834_PTP_NSW_SHDW_CLR_LOAD_NTP_TIME) {
  10385             value32 |= SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD;
  10386         }
  10387         if (value1 & PHY84834_PTP_NSW_SHDW_CTL_LOAD_TIME_COUNT) {
  10388             value32 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD;
  10389         }
  10390         if (value2 & PHY84834_PTP_NSW_SHDW_CLR_LOAD_TIME_COUNT) {
  10391             value32 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD;
  10392         }
  10393         if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_NCO_FCW) {
  10394             value32 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD;
  10395         }
  10396         if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_NCO_FCW) {
  10397             value32 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD;
  10398         }
  10399         if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_FCW ) {
  10400             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD;
  10401         }
  10402         if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_FCW ) {
  10403             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD;
  10404         }
  10405         if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PHASE) {
  10406             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD;
  10407         }
  10408         if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_REF_PHASE) {
  10409             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD;
  10410         }
  10411         if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PERIOD) {
  10412             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD;
  10413         }
  10414         if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_REF_PERIOD) {
  10415             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD;
  10416         }
  10417         if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN3) {
  10418             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD;
  10419         }
  10420         if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN3) {
  10421             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD;
  10422         }
  10423         if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN2) {
  10424             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD;
  10425         }
  10426         if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN2) {
  10427             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD;
  10428         }
  10429         if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN1) {
  10430             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD;
  10431         }
  10432         if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN1) {
  10433             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD;
  10434         }
  10435         COMPILER_64_SET((*value), 0, (uint32)value32);
  10436         break;
  10437 
  10438     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT:
  10439         SOC_IF_ERROR_RETURN
  10440             (READ_PHY8481_PMAD_REG(unit, pc, 
  10441                                               PHY84834_PTP_INT_STATUS_REG, 
  10442                                               &value1));
  10443         value32 = 0;
  10444         if (value1 & PHY84834_PTP_INT_STATUS_PIC) {
  10445             /* Clear the interrupt status. Not self clearing! */
  10446             SOC_IF_ERROR_RETURN
  10447             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
  10448                                               PHY84834_PTP_INT_CLEAR_REG, 
  10449                                               PHY84834_PTP_INT_CLEAR_PIC,
  10450                                               PHY84834_PTP_INT_CLEAR_PIC));
  10451             value32 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT;
  10452         }
  10453         if (value1 & PHY84834_PTP_INT_CLEAR_FSYNC) {
  10454             /* Clear the interrupt status. Not self clearing! */
  10455             SOC_IF_ERROR_RETURN
  10456             (MODIFY_PHY8481_PMAD_REG(unit, pc, 
  10457                                               PHY84834_PTP_INT_CLEAR_REG, 
  10458                                               PHY84834_PTP_INT_CLEAR_FSYNC,
  10459                                               PHY84834_PTP_INT_CLEAR_FSYNC));
  10460             value32 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT;
  10461         }
  10462         COMPILER_64_SET((*value), 0, (uint32)value32);
  10463         break;
  10464 
  10465     case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
  10466         SOC_IF_ERROR_RETURN
  10467             (READ_PHY8481_PMAD_REG(unit, pc, 
  10468                                                PHY84834_PTP_TS_EG_SOP_OFFSET_0_REG, 
  10469                                                &value0)); 
  10470         SOC_IF_ERROR_RETURN
  10471             (READ_PHY8481_PMAD_REG(unit, pc, 
  10472                                                PHY84834_PTP_TS_EG_SOP_OFFSET_1_REG, 
  10473                                                &value1)); 
  10474         COMPILER_64_SET((*value), 0, ((uint32)(value1 & 0xf) << 16) | (uint32)(value0 & 0x0fff));
  10475         break;
  10476 
  10477     case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
  10478         SOC_IF_ERROR_RETURN
  10479             (READ_PHY8481_PMAD_REG(unit, pc, 
  10480                                                PHY84834_PTP_TS_IG_SOP_OFFSET_0_REG, 
  10481                                                &value0)); 
  10482         SOC_IF_ERROR_RETURN
  10483             (READ_PHY8481_PMAD_REG(unit, pc, 
  10484                                                PHY84834_PTP_TS_IG_SOP_OFFSET_1_REG, 
  10485                                                &value1)); 
  10486         COMPILER_64_SET((*value), 0, ((uint32)(value1 & 0xf) << 16) | (uint32)(value0 & 0x0fff));
  10487         break;
  10488 
  10489     default:
  10490         return SOC_E_UNAVAIL;
  10491     }
  10492 
  10493     return SOC_E_NONE;
  10494 }
  10495 
  10496 /*
  10497  * Function:
  10498  *      phy_8481_reg_read
  10499  * Purpose:
  10500  *      Routine to read PHY register
  10501  * Parameters:
  10502  *      uint         - BCM unit number
  10503  *      port         - port number
  10504  *      flags        - Flags which specify the register type
  10505  *      phy_reg_addr - Encoded register address
  10506  *      phy_data     - (OUT) Value read from PHY register
  10507  */
  10508 STATIC int
  10509 phy_8481_reg_read(int unit, soc_port_t port, uint32 flags,
  10510                   uint32 phy_reg_addr, uint32 *phy_data)
  10511 {
  10512     phy_ctrl_t    *pc;
  10513     uint32         reg_flags;
  10514     uint16         reg_bank;
  10515     uint8          reg_addr;
  10516     uint16         data16;
  10517 
  10518     pc = EXT_PHY_SW_STATE(unit, port);
  10519 
  10520     if (PHY_COPPER_MODE(unit, port)) {
  10521         if ((SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr) == 0x7) && 
  10522            (SOC_PHY_CLAUSE45_REGAD(phy_reg_addr) >= 0xffe0)) {
  10523             reg_flags = SOC_PHY_REG_FLAGS(phy_reg_addr);
  10524             reg_bank  = SOC_PHY_REG_BANK(phy_reg_addr);
  10525             reg_addr  = SOC_PHY_REG_ADDR(phy_reg_addr);
  10526             /* handle gphy registers */ 
  10527             SOC_IF_ERROR_RETURN
  10528                 (phy_8481_reg_xge_read(unit, pc, reg_flags, reg_bank, PHY8481_C45_DEV_AN, reg_addr, &data16));
  10529         } else {
  10530            SOC_IF_ERROR_RETURN
  10531                (READ_PHY_REG(unit, pc, phy_reg_addr, &data16));
  10532        }
  10533        *phy_data = (uint32)data16;
  10534     } else {
  10535         if (NXT_PC(pc)) {
  10536             PHYDRV_CALL_ARG3(pc,PHY_REG_READ,flags,phy_reg_addr,phy_data);
  10537         }
  10538     }
  10539     return SOC_E_NONE;
  10540 }
  10541 
  10542 /*
  10543  * Function:
  10544  *      phy_8481_reg_write
  10545  * Purpose:
  10546  *      Routine to write PHY register
  10547  * Parameters:
  10548  *      uint         - BCM unit number
  10549  *      port         - port number
  10550  *      flags        - Flags which specify the register type
  10551  *      phy_reg_addr - Encoded register address
  10552  *      phy_data     - (IN) Value written to PHY register
  10553  */
  10554 STATIC int
  10555 phy_8481_reg_write(int unit, soc_port_t port, uint32 flags,
  10556                   uint32 phy_reg_addr, uint32 phy_data)
  10557 {
  10558     phy_ctrl_t    *pc;       /* PHY software state */
  10559     uint32         reg_flags;
  10560     uint16         reg_bank;
  10561     uint8          reg_addr;
  10562     uint16         data16;
  10563 
  10564     pc = EXT_PHY_SW_STATE(unit, port);
  10565 
  10566     if (PHY_COPPER_MODE(unit, port)) {
  10567         data16 = (uint16)(phy_data & 0xffff);
  10568 
  10569         if ((SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr) == 0x7) && 
  10570            (SOC_PHY_CLAUSE45_REGAD(phy_reg_addr) >= 0xffe0)) {
  10571             reg_flags = SOC_PHY_REG_FLAGS(phy_reg_addr);
  10572             reg_bank  = SOC_PHY_REG_BANK(phy_reg_addr);
  10573             reg_addr  = SOC_PHY_REG_ADDR(phy_reg_addr);
  10574             /* handle gphy registers */ 
  10575             SOC_IF_ERROR_RETURN
  10576                 (phy_8481_reg_xge_write(unit, pc, reg_flags, reg_bank, PHY8481_C45_DEV_AN, reg_addr, data16));
  10577         } else {
  10578            SOC_IF_ERROR_RETURN
  10579                (WRITE_PHY_REG(unit, pc, phy_reg_addr, data16));
  10580        }
  10581     } else {
  10582         if (NXT_PC(pc)) {
  10583             PHYDRV_CALL_ARG3(pc, PHY_REG_WRITE, flags, phy_reg_addr, phy_data);
  10584         }
  10585     }
  10586     return SOC_E_NONE;
  10587 }
  10588 
  10589 /*
  10590  * Function:
  10591  *      phy_8481_reg_modify
  10592  * Purpose:
  10593  *      Routine to read PHY register
  10594  * Parameters:
  10595  *      uint         - BCM unit number
  10596  *      port         - port number
  10597  *      flags        - Flags which specify the register type
  10598  *      phy_reg_addr - Encoded register address
  10599  *      phy_data     - (IN) Value written to PHY register
  10600  *      phy_data_mask    - (IN) Mask used for writing
  10601  */
  10602 STATIC int
  10603 phy_8481_reg_modify(int unit, soc_port_t port, uint32 flags,
  10604                   uint32 phy_reg_addr, uint32 phy_data, uint32 phy_data_mask)
  10605 {
  10606     phy_ctrl_t    *pc;       /* PHY software state */
  10607     uint32         reg_flags;
  10608     uint16         reg_bank;
  10609     uint8          reg_addr;
  10610     uint16         data16;
  10611     uint16         mask16;
  10612 
  10613     pc = EXT_PHY_SW_STATE(unit, port);
  10614 
  10615     if (PHY_COPPER_MODE(unit, port)) {
  10616         data16 = (uint16)(phy_data & 0xffff);
  10617         mask16 = (uint16)(phy_data_mask & 0xffff);
  10618 
  10619         if ((SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr) == 0x7) && 
  10620            (SOC_PHY_CLAUSE45_REGAD(phy_reg_addr) >= 0xffe0)) {
  10621             reg_flags = SOC_PHY_REG_FLAGS(phy_reg_addr);
  10622             reg_bank  = SOC_PHY_REG_BANK(phy_reg_addr);
  10623             reg_addr  = SOC_PHY_REG_ADDR(phy_reg_addr);
  10624             /* handle gphy registers */ 
  10625             SOC_IF_ERROR_RETURN
  10626                 (phy_8481_reg_xge_modify(unit, pc, reg_flags, reg_bank, PHY8481_C45_DEV_AN, reg_addr, data16, mask16));
  10627         } else {
  10628            SOC_IF_ERROR_RETURN
  10629                (MODIFY_PHY_REG(unit, pc, phy_reg_addr, data16, mask16));
  10630        }
  10631     } else {
  10632         if (NXT_PC(pc)) {
  10633             PHYDRV_CALL_ARG4(pc, PHY_REG_MODIFY, flags, phy_reg_addr, phy_data, phy_data_mask);
  10634         }
  10635     }
  10636     return SOC_E_NONE;
  10637 }
  10638 
  10639 int
  10640 phy_8481_reg_xge_read(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank,
  10641                       uint8 dev_addr, uint16 reg_addr, uint16 *data)
  10642 {
  10643     uint32  value;
  10644     uint16  tmp, tmp2 = 0;
  10645     uint16  reg_group, bit_shift;
  10646     int     rv = SOC_E_NONE;
  10647  
  10648     /* Atomic read/write way - new FW */ 
  10649     if ( FLAGS(pc) & PHY8483X_ATOMIC_ACCESS_SHD ) {
  10650         switch(reg_addr) {
  10651         /* Map shadow registers */
  10652         case 0xfff5:
  10653             reg_group = REG_GROUP_SHADOW_MISC_REG;
  10654             bit_shift = 0x0;
  10655             break;
  10656         case 0xfff8:
  10657             reg_group = REG_GROUP_SHADOW18;
  10658             bit_shift = 0x0;
  10659             break;
  10660         case 0xfffc:
  10661             reg_group = REG_GROUP_SHADOW1c;
  10662             bit_shift = 0x0;
  10663             break;
  10664         case 0xfffd:
  10665             reg_group = REG_GROUP_SHADOW_EXP_REG;
  10666             bit_shift = 0x0;
  10667             break;
  10668         default:
  10669             if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) {
  10670                 /* Must not read from reserved registers */
  10671                 if (reg_addr > 0xfffe) {
  10672                    rv = SOC_E_PARAM;
  10673                 }
  10674             }
  10675             reg_group = REG_GROUP_SHADOW_EXP_REG;
  10676             bit_shift = 0x0;
  10677             if (SOC_SUCCESS(rv)) {
  10678                 rv = READ_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data);
  10679                 return rv;
  10680             }
  10681             break;
  10682         }
  10683         if (SOC_SUCCESS(rv)) {
  10684             if(!(flags & SOC_PHY_REG_DUMMY_ACCESS)) {
  10685                 rv =  _phy8485x_shadow_reg_read(unit, pc, reg_group, reg_bank, 0xffff , bit_shift, data);
  10686             } else {
  10687 
  10688                 reg_group = REG_GROUP_SHADOW_EXP_REG;
  10689                 bit_shift = 0x0;
  10690 
  10691                 do {
  10692                     rv =  _phy8485x_shadow_reg_read(unit, pc, reg_group, reg_bank & 0xff , 0xffff , bit_shift, &tmp);
  10693                     if (SOC_FAILURE(rv)) {
  10694                         break;
  10695                     }
  10696                     rv =  _phy8485x_shadow_reg_read(unit, pc, reg_group, reg_bank & 0xff , 0xffff , bit_shift, &tmp);
  10697                     if (SOC_FAILURE(rv)) {
  10698                         break;
  10699                     }
  10700                     rv =  _phy8485x_shadow_reg_read(unit, pc, reg_group, reg_bank & 0xff , 0xffff , bit_shift, &tmp);
  10701                     if (SOC_FAILURE(rv)) {
  10702                         break;
  10703                     }
  10704                     rv =  _phy8485x_shadow_reg_read(unit, pc, reg_group, reg_bank & 0xff , 0xffff , bit_shift, &tmp2);
  10705                 } while(0);
  10706 
  10707                 value = tmp2;
  10708                 value <<= 16; /*upper count*/
  10709                 value |= tmp;
  10710                 * ((uint32 *) data) = value;
  10711             }
  10712         }
  10713     }
  10714     else {  /* (! PHY8483X_ATOMIC_ACCESS_SHD), old way if FW is old */
  10715         rv = READ_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data);
  10716     }
  10717 
  10718     if ( SOC_FAILURE(rv) ) {
  10719         LOG_INFO(BSL_LS_SOC_PHY,
  10720                  (BSL_META_U(unit,
  10721                     "phy_8481_reg_xge_read failed:"
  10722                     " u=%d phy_id=0x%2x dev_addr=0x%02x reg_bank=0x%04x reg_addr=0x%02x" 
  10723                     " rv=%d\n"), unit, pc->phy_id, dev_addr, reg_bank, reg_addr, rv));
  10724     }
  10725     return rv;
  10726 }
  10727 
  10728 int
  10729 phy_8481_reg_xge_write(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank,
  10730                        uint8 dev_addr, uint16 reg_addr, uint16 data)
  10731 {
  10732     uint16  reg_group, bit_shift;
  10733     int     rv = SOC_E_NONE;
  10734 
  10735     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
  10736         return rv;
  10737     }
  10738 
  10739     /* Atomic read/write way - new FW */
  10740     if ( FLAGS(pc) & PHY8483X_ATOMIC_ACCESS_SHD ) {
  10741         /* Map shadow registers */
  10742         switch(reg_addr) {
  10743         case 0xfff5:
  10744             reg_group = REG_GROUP_SHADOW_MISC_REG;
  10745             bit_shift = 0x0;
  10746             break;
  10747         case 0xfff8:
  10748             reg_group = REG_GROUP_SHADOW18;
  10749             bit_shift = 0x0;
  10750             break;
  10751         case 0xfffc:
  10752             reg_group = REG_GROUP_SHADOW1c;
  10753             bit_shift = 0x0;
  10754             break;
  10755         case 0xfffd:
  10756             reg_group = REG_GROUP_SHADOW_EXP_REG;
  10757             bit_shift = 0x0;
  10758             break;
  10759         default:
  10760             if ( ! (flags & SOC_PHY_REG_RESERVE_ACCESS) ) {
  10761                 /* Must not write to reserved registers */
  10762                 if (reg_addr > 0xfffe) {
  10763                     rv = SOC_E_PARAM;
  10764                 }
  10765             }
  10766             reg_group = REG_GROUP_SHADOW_EXP_REG;
  10767             bit_shift = 0x0;
  10768             if ( SOC_SUCCESS(rv) ) {
  10769                 rv = WRITE_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data);
  10770                 return rv;
  10771             }
  10772             break;
  10773         }
  10774         if (SOC_SUCCESS(rv)) {
  10775             rv = _phy8485x_shadow_reg_write(unit, pc, reg_group, reg_bank, 0xffff , bit_shift, data);
  10776         }
  10777     }
  10778     else {  /* (! PHY8483X_ATOMIC_ACCESS_SHD), old way if FW is old */
  10779         rv = WRITE_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data);
  10780     }
  10781 
  10782     if (SOC_FAILURE(rv)) {
  10783         if ( SOC_FAILURE(rv) ) {
  10784         LOG_INFO(BSL_LS_SOC_PHY,
  10785                  (BSL_META_U(unit,
  10786                     "phy_8481_reg_xge_write failed:"
  10787                     " u=%d phy_id=0x%2x dev_addr=0x%02x reg_bank=0x%04x reg_addr=0x%02x"                        
  10788                     " rv=%d\n"), unit, pc->phy_id, dev_addr, reg_bank, reg_addr, rv));
  10789         }
  10790     }
  10791 
  10792     PHY8481_D7_FFXX_REG_VERIFY(unit, pc, flags,  reg_bank, reg_addr);
  10793     return rv;
  10794 }
  10795 
  10796 int
  10797 phy_8481_reg_xge_modify(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank,
  10798                 uint8 dev_addr, uint16 reg_addr, uint16 data, uint16 mask)
  10799 {
  10800     int     rv;
  10801     uint16 reg_group, bit_shift;
  10802 
  10803     rv       = SOC_E_NONE;
  10804 
  10805     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)) {
  10806         return rv;
  10807     }
  10808 
  10809     /* Atomic read/write way - new FW */
  10810     if (FLAGS(pc) & PHY8483X_ATOMIC_ACCESS_SHD) {
  10811         switch(reg_addr) {
  10812         /* Map shadow registers */
  10813         case 0xfff5:
  10814             reg_group = REG_GROUP_SHADOW_MISC_REG;
  10815             bit_shift = 0x0;
  10816             break;
  10817         case 0xfff8:
  10818             reg_group = REG_GROUP_SHADOW18;
  10819             bit_shift = 0x0;
  10820             if (reg_bank == 0x0007) {
  10821                 data |= 0x8000;
  10822                 mask |= 0x8000;
  10823             }
  10824             break;
  10825         case 0xfffc:
  10826             reg_group = REG_GROUP_SHADOW1c;
  10827             bit_shift = 0x0;
  10828             break;
  10829         case 0xfffd:
  10830             reg_group = REG_GROUP_SHADOW_EXP_REG;
  10831             bit_shift = 0x0;
  10832             break;
  10833         default:
  10834             if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) {
  10835                 /* Must not write to reserved registers */
  10836                 if (reg_addr > 0xfffe) {
  10837                     rv = SOC_E_PARAM;
  10838                 }
  10839             }
  10840             reg_group = REG_GROUP_SHADOW_EXP_REG;
  10841             bit_shift = 0x0;
  10842             if (SOC_SUCCESS(rv)) {
  10843                 rv = MODIFY_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data, mask);
  10844                 return rv;
  10845             }
  10846             break;
  10847         }
  10848         if (SOC_SUCCESS(rv)) {
  10849             rv = _phy8485x_shadow_reg_write(unit, pc, reg_group, reg_bank, mask , bit_shift, data);
  10850         }
  10851     }
  10852     else {  /* (! PHY8483X_ATOMIC_ACCESS_SHD), old way if FW is old */
  10853         rv = MODIFY_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data, mask);
  10854     }
  10855 
  10856     if (SOC_FAILURE(rv)) {
  10857         LOG_INFO(BSL_LS_SOC_PHY,
  10858                  (BSL_META_U(unit,
  10859                     "phy_8481_reg_xge_modify failed:"
  10860                     " u=%d phy_id=0x%2x dev_addr=0x%02x reg_bank=0x%04x reg_addr=0x%02x"
  10861                     " rv=%d\n"), unit, pc->phy_id, dev_addr, reg_bank, reg_addr, rv)); 
  10862     }
  10863 
  10864     PHY8481_D7_FFXX_REG_VERIFY( unit, pc, flags,  reg_bank, reg_addr);
  10865     return rv;
  10866 }
  10867 
  10868 
  10869 #ifdef PHY8481_FW_DEBUG
  10870 int
  10871 phy_8481_fw_reg_dump(int unit, soc_port_t port)
  10872 {
  10873     phy_ctrl_t *pc;
  10874     uint16      config, status;
  10875     char *mac_mode, *line_mode, *cu_speed, *fiber_speed, *line_device, *mac_device, *crc_status; 
  10876 
  10877     pc       = EXT_PHY_SW_STATE(unit, port);
  10878 
  10879     SOC_IF_ERROR_RETURN
  10880         (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &config));
  10881 
  10882     SOC_IF_ERROR_RETURN
  10883         (READ_PHY8481_TOP_CONFIG_LINK_STATUS_REG(unit, pc, &status));
  10884 
  10885     LOG_CLI((BSL_META_U(unit,
  10886                         "TOP_CONFIG_XGPHY_STRAP1_REG = 0x%04x\n"), config));
  10887 
  10888     switch ((config >> 3) & 0x3) {
  10889     case 0:
  10890         mac_mode = "00 - XAUI_M - Disabled, XFI - Enabled";
  10891         break;
  10892     case 1:
  10893         mac_mode = "01 - XAUI_M - Enabled, XFI - Disabled";
  10894         break;
  10895     case 2:
  10896         mac_mode = "10 - RESERVED";
  10897         break;
  10898     case 3:
  10899         mac_mode = "11 - RESERVED";
  10900         break;
  10901     default:
  10902         mac_mode = '\0';
  10903         break;
  10904     }
  10905 
  10906     switch ((config >> 5) & 0x3) {
  10907     case 0:
  10908         line_mode = "00 - XAUI_L - Disabled, XFI - Disabled";
  10909         break;
  10910     case 1:
  10911         line_mode = "01 - XAUI_L - Enabled (Autodetect with Cu), XFI - Disabled";
  10912         break;
  10913     case 2:
  10914         line_mode = "10 - XAUI_L - Disabled, XFI - Enabled (Autodetect with Cu)";
  10915         break;
  10916     case 3:
  10917         line_mode = "11 - RESERVED";
  10918         break;
  10919     default:
  10920         line_mode = '\0';
  10921         break;
  10922     }
  10923 
  10924     /* Print the config results */
  10925     LOG_CLI((BSL_META_U(unit,
  10926                         "MAC  mode        = %s\n"), mac_mode));
  10927 
  10928     LOG_CLI((BSL_META_U(unit,
  10929                         "LINE mode        = %s\n"), line_mode));
  10930 
  10931     LOG_CLI((BSL_META_U(unit,
  10932                         "CU PWRDN         = %s\n"), (config & (1U<<7)) ? "Yes" : "No"));
  10933 
  10934     LOG_CLI((BSL_META_U(unit,
  10935                         "FIBER Prio       = %s\n"), (config & (1U<<8)) ? "Yes" : "No"));
  10936 
  10937     LOG_CLI((BSL_META_U(unit,
  10938                         "SD Invert        = %s\n"), (config & (1U<<9)) ? "Yes" : "No"));
  10939 
  10940     LOG_CLI((BSL_META_U(unit,
  10941                         "RANGE            = %s\n"), (config & (1U<<10)) ? "30M" : "100M"));
  10942 
  10943     LOG_CLI((BSL_META_U(unit,
  10944                         "LED User Control = %s\n"), (config & (1U<<11)) ? "Yes" : "No"));
  10945 
  10946 
  10947     LOG_CLI((BSL_META_U(unit,
  10948                         "\nTOP_CONFIG_LINK_STATUS (400d) = 0x%04x\n"), status));
  10949 
  10950     switch ((status >> 3) & 0x3) {
  10951     case 0:
  10952         cu_speed = "00 - 10M";
  10953         break;
  10954     case 1:
  10955         cu_speed = "01 - 100M";
  10956         break;
  10957     case 2:
  10958         cu_speed = "10 - 1G";
  10959         break;
  10960     case 3:
  10961         cu_speed = "11 - 10G";
  10962         break;
  10963     default:
  10964         cu_speed = '\0';
  10965         break;
  10966     }
  10967 
  10968     switch ((status >> 6) & 0x3) {
  10969     case 0:
  10970         fiber_speed = "00 - 10M";
  10971         break;
  10972     case 1:
  10973         fiber_speed = "01 - 100M";
  10974         break;
  10975     case 2:
  10976         fiber_speed = "10 - 1G";
  10977         break;
  10978     case 3:
  10979         fiber_speed = "11 - 10G";
  10980         break;
  10981     default:
  10982         fiber_speed = '\0';
  10983         break;
  10984     }
  10985 
  10986     switch ((status >> 9) & 0x3) {
  10987     case 0:
  10988         mac_device = "00 - Reserved";
  10989         break;
  10990     case 1:
  10991         mac_device = "01 - XAUI";
  10992         break;
  10993     case 2:
  10994         mac_device = "10 - XFI";
  10995         break;
  10996     case 3:
  10997         mac_device = "11 - Reserved";
  10998         break;
  10999     default:
  11000         mac_device = '\0';
  11001         break;
  11002     }
  11003 
  11004     switch ((status >> 11) & 0x3) {
  11005     case 0:
  11006         line_device = "00 - CU";
  11007         break;
  11008     case 1:
  11009         line_device = "01 - XAUI";
  11010         break;
  11011     case 2:
  11012         line_device = "10 - XFI";
  11013         break;
  11014     case 3:
  11015         line_device = "11 - Reserved";
  11016         break;
  11017     default:
  11018         line_device = '\0';
  11019         break;
  11020     }
  11021 
  11022     switch ((status >> 14) & 0x3) {
  11023     case 0:
  11024         crc_status = "00 - CRC check going on (May indicate ARM hang)";
  11025         break;
  11026     case 1:
  11027         crc_status = "01 - Good CRC";
  11028         break;
  11029     case 2:
  11030         crc_status = "10 - Bad CRC";
  11031         break;
  11032     case 3:
  11033         crc_status = "11 - Reserved";
  11034         break;
  11035     default:
  11036         crc_status = '\0';
  11037         break;
  11038     }
  11039 
  11040     /* Print the status results */
  11041 
  11042     LOG_CLI((BSL_META_U(unit,
  11043                         "FIBER Detected   = %s\n"), (status & (1U<<0)) ? "Yes" : "No"));
  11044 
  11045     LOG_CLI((BSL_META_U(unit,
  11046                         "CU Detected      = %s\n"), (status & (1U<<1)) ? "Yes" : "No"));
  11047 
  11048     LOG_CLI((BSL_META_U(unit,
  11049                         "FIBER Prio       = %s\n"), (status & (1U<<2)) ? "Yes" : "No"));
  11050 
  11051     LOG_CLI((BSL_META_U(unit,
  11052                         "CU  speed        = %s\n"), cu_speed));
  11053 
  11054     LOG_CLI((BSL_META_U(unit,
  11055                         "CU Link          = %s\n"), (status & (1U<<5)) ? "Yes" : "No"));
  11056 
  11057     LOG_CLI((BSL_META_U(unit,
  11058                         "Fiber  speed     = %s\n"), fiber_speed));
  11059 
  11060     LOG_CLI((BSL_META_U(unit,
  11061                         "Fiber Link       = %s\n"), (status & (1U<<8)) ? "Yes" : "No"));
  11062 
  11063     LOG_CLI((BSL_META_U(unit,
  11064                         "MAC  device      = %s\n"), mac_device));
  11065 
  11066     LOG_CLI((BSL_META_U(unit,
  11067                         "LINE device      = %s\n"), line_device));
  11068 
  11069     LOG_CLI((BSL_META_U(unit,
  11070                         "MAC Link Up      = %s\n"), (status & (1U<<13)) ? "Yes" : "No"));
  11071 
  11072     LOG_CLI((BSL_META_U(unit,
  11073                         "CRC Status       = %s\n"), crc_status));
  11074 
  11075     return SOC_E_NONE;
  11076 }
  11077 #endif
  11078 
  11079 /*
  11080  * Variable:
  11081  *    phy_8481_drv
  11082  * Purpose:
  11083  *    Phy Driver for 10G (XAUI x 4) Serdes PHY. 
  11084  */
  11085 
  11086 phy_driver_t phy_8481drv_xe = {
  11087     "8481 10-Gigabit PHY Driver",
  11088     phy_8481_init,        /* Init */
  11089     phy_null_reset,       /* Reset */
  11090     phy_8481_link_get,    /* Link get   */
  11091     phy_8481_enable_set,  /* Enable set */
  11092     phy_8481_enable_get,  /* Enable get */
  11093     phy_8481_duplex_set,  /* Duplex set */
  11094     phy_8481_duplex_get,  /* Duplex get */
  11095     phy_8481_speed_set,   /* Speed set  */
  11096     phy_8481_speed_get,   /* Speed get  */
  11097     phy_8481_master_set,  /* Master set */
  11098     phy_8481_master_get,  /* Master get */
  11099     phy_8481_an_set,      /* ANA set */
  11100     phy_8481_an_get,      /* ANA get */
  11101     NULL,                 /* Local Advert set, deprecated */
  11102     NULL,                 /* Local Advert get, deprecated */
  11103     NULL,                 /* Remote Advert get, deprecated */
  11104     phy_8481_lb_set,      /* PHY loopback set */
  11105     phy_8481_lb_get,      /* PHY loopback set */
  11106     phy_null_interface_set, /* IO Interface set */
  11107     phy_8481_xehg_interface_get, /* IO Interface get */
  11108     NULL,                   /* pd_ability, deprecated */
  11109     phy_8481_link_up,
  11110     phy_8481_link_down,
  11111     phy_8481_mdix_set,
  11112     phy_8481_mdix_get,
  11113     phy_8481_mdix_status_get,
  11114     phy_8481_medium_config_set, /* medium config setting set */
  11115     phy_8481_medium_config_get, /* medium config setting get */
  11116     phy_8481_medium_status,        /* active medium */
  11117     phy_8481_cable_diag,           /* phy_cable_diag  */
  11118     NULL,                    /* phy_link_change */
  11119     phy_8481_control_set,    /* phy_control_set */
  11120     phy_8481_control_get,    /* phy_control_get */
  11121     phy_8481_reg_read,       /* phy_reg_read */
  11122     phy_8481_reg_write,      /* phy_reg_write */
  11123     phy_8481_reg_modify,     /* phy_reg_modify */
  11124     NULL,                    /* phy_notify */
  11125     phy_8481_probe,          /* pd_probe  */
  11126     phy_8481_ability_advert_set,  /* pd_ability_advert_set */
  11127     phy_8481_ability_advert_get,  /* pd_ability_advert_get */
  11128     phy_8481_ability_remote_get,  /* pd_ability_remote_get */
  11129     phy_8481_ability_local_get,   /* pd_ability_local_get  */
  11130     phy_8481_firmware_set,
  11131     phy84834_timesync_config_set,
  11132     phy84834_timesync_config_get,
  11133     phy84834_timesync_control_set,
  11134     phy84834_timesync_control_get,
  11135     phy_8481_diag_ctrl             /* pd_diag_ctrl */
  11136 };
  11137 
  11138 #else /* INCLUDE_PHY_8481 */
  11139 int _phy_8481_not_empty;
  11140 #endif /* INCLUDE_PHY_8481 */
  11141