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

phy542xx.c (365671B)


      1 /*
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  */
      6 
      7 /*
      8  * File:        phy542xx.c
      9  * Purpose:     PHY driver for BCM542xx (Non-MacSec) 
     10  *
     11  * Supported BCM542X Family of PHY devices:
     12  *
     13  *  Device    Ports        Media            MAC Interface
     14  *  --------- -----   ------------------   ---------------
     15  *  54210       1     1 Copper / Fiber        SGMII/RGMII
     16  *  54220       2     2 Copper / Fiber        SGMII/RGMII
     17  *  54240       4     4 Copper / Fiber        SGMII
     18  *  54294       4     4 Copper / Fiber        SGMII
     19  *  54140/94    4     4 Copper / Fiber        SGMII
     20  *  54290/80    8     8 Copper only           SGMII
     21  *  54180/90    8     8 Copper only           SGMII
     22  *  54292/82    8     8 Copper only          QSGMII*2
     23  *  54182       8     8 Copper only          QSGMII*2
     24  *  54192       8     8 Copper only          QSGMII*2
     25  *  54296       4     4 Copper / Fiber       QSGMII
     26  *  54295       8     8 Copper / 4 Fiber     QSGMII*2
     27  *  54185       8     8 Copper / 8 Fiber     QSGMII*2
     28  *  54195       8     8 Copper / 8 Fiber     QSGMII*2
     29  *  54285       8     8 Copper / Fiber       QSGMII*2
     30  *
     31  * Workarounds:
     32  *
     33  * Notes:
     34  */
     35 
     36 #include <sal/types.h>
     37 #include <sal/core/spl.h>
     38 #include <shared/bsl.h>
     39 #include <soc/drv.h>
     40 #include <soc/debug.h>
     41 #include <soc/error.h>
     42 #include <soc/phyreg.h>
     43 
     44 #include <soc/phy.h>
     45 #include <soc/phy/phyctrl.h>
     46 #include <soc/phy/drv.h>
     47 #include "phydefs.h"      /* Must include before other phy related includes */
     48 
     49 #if defined(INCLUDE_PHY_542XX)
     50 #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
     51 #include "phyident.h"
     52 #include "phyreg.h"
     53 #include "phyfege.h"
     54 #include "phy542xx_int.h"
     55 #include "phy542xx_regdefs.h"
     56 #ifdef INCLUDE_PLP_IMACSEC
     57 #include "bcm_imacsec.h"
     58 #include "bcm_iunimac.h"
     59 #include "phy_mac_ctrl.h"
     60 #endif
     61 #include <soc/oam.h>
     62 
     63 #define DISABLE_CLK125          0       /* Disable if unused to reduce */
     64                                         /*  EMI emissions */
     65 
     66 #define LC_CM_DISABLE_WORKAROUND
     67 #define AUTO_MDIX_WHEN_AN_DIS   0
     68 
     69 #ifdef INCLUDE_PLP_IMACSEC
     70 
     71 #define IMACSEC_MDIO_ADDR_GET(id) (id & 0x3ff)
     72 
     73 #define IMACSEC_DES_PTR_GET(_pc)\
     74 ((bcm_plp_base_t_sec_phy_access_t *)(((char *)((_pc) + 1) + (_pc)->size) - sizeof(bcm_plp_base_t_sec_phy_access_t)))
     75 
     76 extern void _bcm_plp_register_mdio_primitives(
     77     int unit, unsigned int slice, unsigned int secy_phy_id,
     78     int                 (*read)(int, uint32, uint32, uint16*), /* HW read */
     79     int                 (*write)(int, uint32, uint32, uint16));/* HW write */
     80 
     81 
     82 /*
     83  * Function:     
     84  *    imacsec_blmi_io_mmi2
     85  * Purpose:    
     86  *    Access to UNIMAC and SECY register space
     87  * Parameters:
     88  *    unit            - Switch unit  (dev_addr is overloaded by this)
     89  *    port            - Switch port  (dev_port is overloaded by this)
     90  *    op              - access type  (read/write register )
     91  *    io_addr         - Register address
     92  *    word_sz         - word size
     93  *    num_entry       - number of words
     94  *    data            - data buffer
     95  * Notes: 
     96  *    Existing  "phy_mac_ctrl" infrastructure uses dev_addr/dev_port
     97  *    for i/o access.  For IMACSEC i/o access  we will overload these 
     98  *    with  (Switch unit)/(Switch port).
     99  */
    100 static int
    101 imacsec_blmi_io_mmi2( uint32 unit,      /* Switch unit  */
    102                       int port,         /* Switch port */
    103                       blmi_io_op_t op,  /* I/O operation   */  
    104                       uint32 io_addr,   /* I/O address     */
    105                       int word_sz,      /* Word size       */
    106                       int num_entry,    /* Num entry       */
    107                       uint32 *data)     /* Data buffer     */
    108 {
    109     int rv;
    110 
    111     switch(op) {
    112 
    113         case BLMI_IO_REG_WR:
    114             rv = imacsec_plp_addr_write(unit, port, io_addr, *data);
    115             break;
    116         default:
    117             rv = imacsec_plp_addr_read(unit, port, io_addr, data);
    118             break;
    119     }
    120 
    121     return rv;
    122 }
    123 
    124 #define SPEED_MAPPING(_sp, _spr)    do { \
    125     switch ( _sp ) { \
    126     case 0:    return BLMI_E_NONE;  \
    127     case 10:   _spr = 0; break;     \
    128     case 100:  _spr = 1; break;     \
    129     case 1000: _spr = 2; break;     \
    130     default: return (BLMI_E_CONFIG); }  } while(0)\
    131 
    132 static int get_port(const bcm_plp_base_t_access_t *pa)
    133 {
    134     unsigned char lm = pa->lane_map ;
    135 
    136     switch(lm)
    137     {
    138         case 0x80:
    139             return 7;
    140         case 0x40:
    141             return 6;
    142         case 0x20:
    143             return 5;
    144         case 0x10:
    145             return 4;
    146         case 0x08:
    147             return 3;
    148         case 0x04:
    149             return 2;
    150         case 0x02:
    151             return 1;
    152         default:
    153             return 0;
    154     }
    155 }
    156 
    157 /*
    158  * Function:     
    159  *    _bcm_phy5419x_phy_mac_driver_detach
    160  * Purpose:    
    161  *    Delete Mapping of PHY device address and Device port
    162  * Parameters:
    163  *    phy_dev_addr    - PHY Device Address
    164  * Notes: 
    165  */
    166 int 
    167 _bcm_phy5419x_phy_mac_driver_detach(phy_ctrl_t     *pc)
    168 {
    169     int rv = SOC_E_NONE;
    170     bcm_plp_base_t_sec_phy_access_t *imacsec_des;
    171 
    172     imacsec_des = IMACSEC_DES_PTR_GET(pc);
    173 
    174     if (imacsec_des->unimac) {
    175         phy_mac_driver_detach((phy_mac_ctrl_t *)imacsec_des->unimac);
    176         imacsec_des->unimac = 0;
    177     }
    178     return rv;
    179 }
    180 
    181 
    182 /*
    183  * Function:     
    184  *    _bcm_phy5419x_phy_mac_driver_attach
    185  * Purpose:    
    186  *    Add Mapping of PHY device address, Device port
    187  * Parameters:
    188  *    phy_dev_addr    - PHY Device Address
    189  *    dev_port        - Port number
    190  * Notes: 
    191  */
    192 int 
    193 _bcm_phy5419x_phy_mac_driver_attach(phy_ctrl_t *pc,
    194                                  uint32 ms_dev_addr,
    195                                  int dev_port, blmi_dev_io_f mmi_cbf)
    196 {
    197     bcm_plp_base_t_sec_phy_access_t *imacsec_des;
    198 
    199     /* Delete the mapping if already present */
    200     (void)_bcm_phy5419x_phy_mac_driver_detach(pc);
    201 
    202     imacsec_des = IMACSEC_DES_PTR_GET(pc);
    203 
    204     /* Alloc unimac driver and attach */
    205     imacsec_des->unimac =  
    206             phy_mac_driver_attach(imacsec_des->macsec_dev_addr,
    207                                      PHY_MAC_CORE_UNIMAC, mmi_cbf);
    208     if (!imacsec_des->unimac) {
    209         _bcm_phy5419x_phy_mac_driver_detach(pc);
    210         return SOC_E_INTERNAL;
    211     }
    212 
    213 
    214     phy_mac_driver_config((phy_mac_ctrl_t *) imacsec_des->unimac,
    215                              PHY_MAC_CORE_UNIMAC,
    216                              PHY_MAC_CTRL_FLAG_UNIMAC_V2);
    217 
    218     phy_mac_driver_unit_set((phy_mac_ctrl_t *) imacsec_des->unimac,
    219                              PHY_MAC_CORE_UNIMAC,
    220                              pc->unit);
    221 
    222 
    223     return SOC_E_NONE;
    224 }
    225 
    226 
    227 
    228 #endif /* INCLUDE_PLP_IMACSEC */
    229 
    230 /*Copper*/
    231 #define ADVERT_ALL_COPPER_FLOW_CTRL   (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)
    232 #define ADVERT_ALL_COPPER_HD_SPEED    (SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB)
    233 #define ADVERT_ALL_COPPER_FD_SPEED    (SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB)
    234 #define ADVERT_ALL_COPPER_EEE_SPEED   (SOC_PA_EEE_100MB_BASETX | \
    235                                        SOC_PA_EEE_1GB_BASET    | \
    236                                        SOC_PA_EEE_10GB_BASET)
    237 /*Fiber*/
    238 #define ADVERT_ALL_FIBER_FLOW_CTRL    (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)
    239 #define ADVERT_ALL_FIBER_FD_SPEED     (SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB)
    240 
    241 
    242 #define SET_FLOW_CTRL_ABILITY(ability, p)  ((ability)->pause |= p)
    243 #define SET_HD_SPEED_ABILITY(ability, s)   ((ability)->speed_half_duplex |= s)
    244 #define SET_FD_SPEED_ABILITY(ability, s)   ((ability)->speed_full_duplex |= s)
    245 #define SET_EEE_SPEED_ABILITY(ability, s)  ((ability)->eee |= s)
    246 
    247 #define ADVERT_ALL_COPPER(ability)  do { \
    248             SET_FLOW_CTRL_ABILITY(ability, ADVERT_ALL_COPPER_FLOW_CTRL); \
    249             SET_HD_SPEED_ABILITY(ability, ADVERT_ALL_COPPER_HD_SPEED);   \
    250             SET_FD_SPEED_ABILITY(ability, ADVERT_ALL_COPPER_FD_SPEED);   \
    251             SET_EEE_SPEED_ABILITY(ability, ADVERT_ALL_COPPER_EEE_SPEED); \
    252         } while ( 0 )
    253 
    254 #define ADVERT_ALL_FIBER(ability)  do { \
    255             SET_FLOW_CTRL_ABILITY(ability, ADVERT_ALL_FIBER_FLOW_CTRL); \
    256             SET_FD_SPEED_ABILITY(ability, ADVERT_ALL_FIBER_FD_SPEED);   \
    257         } while ( 0 )
    258 
    259 #define PHY_IS_BCM54210(_pc) (PHY_MODEL_CHECK((_pc), \
    260                                   PHY_BCM54210_OUI,  \
    261                                   PHY_BCM54210_MODEL))
    262 #define PHY_IS_BCM54220(_pc) (PHY_MODEL_CHECK((_pc), \
    263                                   PHY_BCM54220_OUI,  \
    264                                   PHY_BCM54220_MODEL))
    265 #define PHY_IS_BCM54280(_pc) (PHY_MODEL_CHECK((_pc), \
    266                                   PHY_BCM54280_OUI,  \
    267                                   PHY_BCM54280_MODEL)) 
    268 #define PHY_IS_BCM54180(_pc) (PHY_MODEL_CHECK((_pc), \
    269                                   PHY_BCM54180_OUI,  \
    270                                   PHY_BCM54180_MODEL) \
    271                                   && (!(((_pc)->phy_rev & 0x8))) )
    272 #define PHY_IS_BCM54182(_pc) (PHY_MODEL_CHECK((_pc), \
    273                                   PHY_BCM54182_OUI,  \
    274                                   PHY_BCM54182_MODEL))
    275 #define PHY_IS_BCM54185(_pc) (PHY_MODEL_CHECK((_pc), \
    276                                   PHY_BCM54185_OUI,  \
    277                                   PHY_BCM54185_MODEL)\
    278                                   && (((_pc)->phy_rev & 0x8)) )
    279 #define PHY_IS_BCM54140(_pc) (PHY_MODEL_CHECK((_pc), \
    280                                   PHY_BCM54140_OUI,  \
    281                                   PHY_BCM54140_MODEL) \
    282                                   && (((_pc)->phy_rev & 0x8)) )
    283 #define PHY_IS_BCM54190(_pc) (PHY_MODEL_CHECK((_pc), \
    284                                   PHY_BCM54190_OUI,  \
    285                                   PHY_BCM54190_MODEL) \
    286                                   && (!(((_pc)->phy_rev & 0x8))) )
    287 #define PHY_IS_BCM54192(_pc) (PHY_MODEL_CHECK((_pc), \
    288                                   PHY_BCM54192_OUI,  \
    289                                   PHY_BCM54192_MODEL))
    290 #define PHY_IS_BCM54195(_pc) (PHY_MODEL_CHECK((_pc), \
    291                                   PHY_BCM54195_OUI,  \
    292                                   PHY_BCM54195_MODEL)\
    293                                   && (((_pc)->phy_rev & 0x8)) )
    294 #define PHY_IS_BCM54194(_pc) (PHY_MODEL_CHECK((_pc), \
    295                                   PHY_BCM54194_OUI,  \
    296                                   PHY_BCM54194_MODEL) \
    297                                   && (((_pc)->phy_rev & 0x8)) )
    298 #define PHY_IS_BCM54282(_pc) (PHY_MODEL_CHECK((_pc), \
    299                                   PHY_BCM54282_OUI,  \
    300                                   PHY_BCM54282_MODEL) \
    301                                   && ((_pc)->phy_rev & 0x8))
    302 #define PHY_IS_BCM54240(_pc) (PHY_MODEL_CHECK((_pc), \
    303                                   PHY_BCM54240_OUI,  \
    304                                   PHY_BCM54240_MODEL))
    305 #define PHY_IS_BCM54285(_pc) (PHY_MODEL_CHECK((_pc), \
    306                                   PHY_BCM54285_OUI,  \
    307                                   PHY_BCM54285_MODEL) \
    308                                   && (!((_pc)->phy_rev & 0x8)))
    309 #define PHY_IS_BCM5428x(pc)  (    PHY_IS_BCM54280(pc) \
    310                                || PHY_IS_BCM54282(pc) \
    311                                || PHY_IS_BCM54240(pc) \
    312                                || PHY_IS_BCM54285(pc) )
    313 #define PHY_IS_BCM54210_220(pc)  (PHY_IS_BCM54210(pc) \
    314                                || PHY_IS_BCM54220(pc) )
    315 #define PHY_IS_BCM5418x_19x(pc)  (PHY_IS_BCM54140(pc) \
    316                                || PHY_IS_BCM54180(pc) \
    317                                || PHY_IS_BCM54182(pc) \
    318                                || PHY_IS_BCM54185(pc) \
    319                                || PHY_IS_BCM54190(pc) \
    320                                || PHY_IS_BCM54192(pc) \
    321                                || PHY_IS_BCM54194(pc) \
    322                                || PHY_IS_BCM54195(pc) )
    323 #if 0
    324 #define PHY_BCM54282_QSGMII_DEV_ADDR(phy_base_addr) (phy_base_addr + 8)
    325 #define PHY_BCM54282_QSGMII_DEV_ADDR_SHARED(phy_base_addr) (phy_base_addr + 3)
    326 #endif
    327 
    328 #define PHY_BCM54282_QSGMII_DEV_ADDR(_pc) \
    329                 (PHY_BCM542XX_FLAGS((_pc)) & PHY_BCM542XX_PHYADDR_REVERSE) \
    330                 ? (PHY_BCM542XX_DEV_PHY_ID_BASE(_pc) + 1) \
    331                 : (PHY_BCM542XX_DEV_PHY_ID_BASE(_pc) + 8)
    332 
    333 #define PHY_BCM54282_QSGMII_DEV_ADDR_SHARED(_pc) PHY_BCM542XX_SLICE_ADDR((_pc), 3)
    334 
    335 #define PHY_BCM54240_28X_REV_BO(model, rev)  ( \
    336                                           ((rev & 0x7) == 0x1) && \
    337                                            ((model == PHY_BCM54280_MODEL) || \
    338                                             (model == PHY_BCM54282_MODEL) || \
    339                                             (model == PHY_BCM54285_MODEL) || \
    340                                             (model == PHY_BCM54240_MODEL)) )
    341 #define PHY_BCM54240_28X_REV_C1(model, rev)  ( \
    342                                           ((rev & 0x7) == 0x3) && \
    343                                            ((model == PHY_BCM54280_MODEL) || \
    344                                             (model == PHY_BCM54282_MODEL) || \
    345                                             (model == PHY_BCM54285_MODEL) || \
    346                                             (model == PHY_BCM54240_MODEL)) )
    347 #define PHY_BCM54240_28X_REV_C0_OR_OLDER(model, rev)  ( \
    348                                           ((rev & 0x7) < 0x3) && \
    349                                            ((model == PHY_BCM54280_MODEL) || \
    350                                             (model == PHY_BCM54282_MODEL) || \
    351                                             (model == PHY_BCM54285_MODEL) || \
    352                                             (model == PHY_BCM54240_MODEL)) )
    353 
    354 #define PHY_IS_BCM54290(_pc) (PHY_MODEL_CHECK((_pc), \
    355                                   PHY_BCM54290_OUI,  \
    356                                   PHY_BCM54290_MODEL) \
    357                                   && (!((_pc)->phy_rev & 0x8)) )
    358 #define PHY_IS_BCM54292(_pc) (PHY_MODEL_CHECK((_pc), \
    359                                   PHY_BCM54292_OUI,  \
    360                                   PHY_BCM54292_MODEL))
    361 #define PHY_IS_BCM54294(_pc) (PHY_MODEL_CHECK((_pc), \
    362                                   PHY_BCM54294_OUI,  \
    363                                   PHY_BCM54294_MODEL)\
    364                                   && ((_pc)->phy_rev & 0x8))
    365 #define PHY_IS_BCM54295(_pc) (PHY_MODEL_CHECK((_pc), \
    366                                   PHY_BCM54295_OUI,  \
    367                                   PHY_BCM54295_MODEL) \
    368                                   && (((_pc)->phy_rev & 0x8)))
    369 #define PHY_IS_BCM54296  PHY_IS_BCM54295
    370 #define PHY_IS_BCM5429X(pc)  (    PHY_IS_BCM54290(pc) \
    371                                || PHY_IS_BCM54294(pc) \
    372                                || PHY_IS_BCM54292(pc) \
    373                                || PHY_IS_BCM54295(pc) )
    374 
    375 #define SOC_IF_ERROR_BREAK(op, _rv)       if ( ((_rv) = (op)) < 0 ) {  break;  }
    376 #define PHY_RETAIN_SUPER_ISOLATE          0x80
    377 /* macros for ext_phy_autodetect_en and ext_phy_fiber_iface */
    378 #define EXT_PHY_AUTODETECT_DIS     0x0
    379 #define EXT_PHY_AUTODETECT_EN      0x1
    380 #define EXT_PHY_FIBER_IFACE_1000X  0x0
    381 #define EXT_PHY_FIBER_IFACE_100FX  0x1
    382 #define EXT_PHY_FIBER_IFACE_SGMII  0x2
    383 
    384 int phy_bcm542xx_reset(int unit, soc_port_t port, void *user_arg);
    385 STATIC int _phy_bcm542xx_no_reset_setup(int unit, soc_port_t port);
    386 STATIC int phy_bcm542xx_duplex_get(int unit, soc_port_t port, int *duplex);
    387 STATIC int phy_bcm542xx_duplex_set(int unit, soc_port_t port, int  duplex);
    388 STATIC int phy_bcm542xx_speed_get(int unit, soc_port_t port, int *speed);
    389 STATIC int phy_bcm542xx_speed_set(int unit, soc_port_t port, int  speed);
    390 STATIC int phy_bcm542xx_master_get(int unit, soc_port_t port, int *master);
    391 STATIC int phy_bcm542xx_master_set(int unit, soc_port_t port, int  master);
    392 STATIC int phy_bcm542xx_autoneg_get(int unit, soc_port_t port, int *autoneg, int *autoneg_done);
    393 STATIC int phy_bcm542xx_autoneg_set(int unit, soc_port_t port, int  autoneg);
    394 STATIC int phy_bcm542xx_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode);
    395 STATIC int phy_bcm542xx_mdix_set(int unit, soc_port_t port, soc_port_mdix_t  mode);
    396 STATIC int phy_bcm542xx_ability_advert_get(int unit, soc_port_t port, soc_port_ability_t *ability);
    397 STATIC int phy_bcm542xx_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability);
    398 STATIC int phy_bcm542xx_init_setup(int unit, soc_port_t port, int reset, int automedium,
    399                                    int fiber_preferred, int fiber_detect,
    400                                    int fiber_enable, int copper_enable,
    401                                    int ext_phy_autodetect_en, int ext_phy_fiber_iface);
    402 STATIC int phy_bcm542xx_control_set(int unit, soc_port_t port,
    403                                     soc_phy_control_t type, uint32 value);
    404 int phy_bcm542xx_oam_config_get(int unit, soc_port_t port, soc_port_config_phy_oam_t *conf);
    405 extern int phy_ecd_cable_diag_init_40nm(int unit, soc_port_t port);
    406 extern int phy_ecd_cable_diag_40nm(int unit, soc_port_t port,
    407                                    soc_port_cable_diag_t *status, uint16 ecd_ctrl);
    408 int _phy_bcm542xx_rgmii_to_copper_mode(int unit, soc_port_t port);
    409 int _phy_bcm542xx_rgmii_to_fiber_mode(int unit, soc_port_t port);
    410 
    411 /***********************************************************************
    412  *
    413  * HELPER FUNCTIONS
    414  */
    415 
    416 int
    417 phy_bcm542xx_reg_read(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank,
    418                       uint8 reg_addr, uint16 *data)
    419 {
    420     int rv;
    421     uint16 val;
    422 
    423     rv = SOC_E_NONE;
    424     if ( flags & PHY_BCM542XX_REG_QSGMII ) {
    425         /* Do not apply shadow register logic for QSGMII register access */
    426         rv = PHY_BCM542XX_READ_PHY_REG(unit, pc, reg_addr, data);
    427 
    428     } else if ( flags & (PHY_BCM542XX_REG_1000X |
    429                          PHY_BCM542XX_REG_PRI_SERDES) ) {  /* fiber registers */
    430         if ( reg_addr <= 0x0f ) {
    431             if ( PHY_IS_BCM54210_220(pc) && (flags & PHY_BCM542XX_REG_1000X) ) {
    432                 /* 54220/210 fiber is controlled by Secondary SerDes */
    433                 rv = phy_bcm542xx_direct_reg_read(unit, pc, (uint16)
    434                                 reg_addr | PHY_BCM542XX_2ND_SERDES_BASE_OFFSET,
    435                                 data);
    436             } else {  /* not 54220_210 or PHY_BCM542XX_REG_PRI_SERDES */
    437                 /* Map 1000X page */
    438 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
    439                 uint16 blk_sel, val;
    440                 val = 0x7c00;
    441                 SOC_IF_ERROR_RETURN
    442                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val));
    443                 SOC_IF_ERROR_RETURN
    444                     (PHY_BCM542XX_READ_PHY_REG( unit, pc, 0x1c, &blk_sel));
    445                 val = blk_sel | 0x8001;
    446                 SOC_IF_ERROR_RETURN
    447                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val));
    448 #else
    449                 SOC_IF_ERROR_RETURN(
    450                     phy_bcm542xx_direct_reg_modify(unit, pc,
    451                                     PHY_BCM542XX_MODE_CONTROL_REG_OFFSET,
    452                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN,
    453                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) );
    454 #endif
    455                 /* Read 1000X IEEE register */
    456                 SOC_IF_ERROR_RETURN
    457                     (PHY_BCM542XX_READ_PHY_REG(unit, pc, reg_addr, data));
    458 
    459                /* Restore IEEE mapping */
    460 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
    461                 val = (blk_sel & 0xfffe) | 0x8000;
    462                 SOC_IF_ERROR_RETURN
    463                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val));
    464 #else
    465                 SOC_IF_ERROR_RETURN(
    466                     phy_bcm542xx_direct_reg_modify(unit, pc,
    467                                     PHY_BCM542XX_MODE_CONTROL_REG_OFFSET,
    468                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_DIS,
    469                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) );
    470 #endif
    471             }
    472         } else {  /*  (reg_addr > 0xf)  */
    473             rv = SOC_E_PARAM;
    474         }
    475 
    476     } else {
    477         switch ( reg_addr ) {
    478         /* Map shadow registers */
    479         case 0x15:
    480             SOC_IF_ERROR_RETURN
    481                 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x17, reg_bank));
    482             break;
    483         case 0x18:
    484             if ( reg_bank <= 0x0007 ) {
    485                 val = (reg_bank << 12) | 0x7;
    486                 SOC_IF_ERROR_RETURN
    487                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, val));
    488             } else {
    489                 rv = SOC_E_PARAM;
    490             }
    491             break;
    492         case 0x1C:
    493             if ( reg_bank <= 0x001F ) {
    494                 val = (reg_bank << 10);
    495                 SOC_IF_ERROR_RETURN
    496                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, val));
    497             } else {
    498                 rv = SOC_E_PARAM;
    499             }
    500             break;
    501         case 0x1D:
    502             if ( reg_bank <= 0x0001 ) {
    503                 val = reg_bank << 15; 
    504                 SOC_IF_ERROR_RETURN
    505                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, val));
    506             } else {
    507                 rv = SOC_E_PARAM;
    508             }
    509             break;
    510         }
    511         if ( SOC_SUCCESS(rv) ) {
    512             rv = PHY_BCM542XX_READ_PHY_REG(unit, pc, reg_addr, data);
    513         }
    514     } 
    515 
    516     if ( SOC_FAILURE(rv) ) {
    517         LOG_INFO(BSL_LS_SOC_PHY,
    518                  (BSL_META_U(unit,
    519                              "phy_bcm542xx_reg_read: failed:"
    520                              "phy_id=0x%2x reg_bank=0x%04x reg_addr=0x%02x "
    521                              "rv=%d\n"), pc->phy_id, reg_bank, reg_addr, rv)); 
    522     }
    523     return rv;
    524 }
    525 
    526 
    527 int
    528 phy_bcm542xx_reg_write(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank,
    529                        uint8 reg_addr, uint16 data)
    530 {
    531     int     rv;
    532 
    533     if ( flags & PHY_BCM542XX_REG_QSGMII ) {
    534         /* Do not apply shadow register logic for QSGMII register access */
    535         SOC_IF_ERROR_RETURN
    536             (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, data));
    537         return SOC_E_NONE;
    538     }
    539 
    540     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
    541         return SOC_E_NONE;
    542     }
    543     rv = SOC_E_NONE;
    544 
    545     if ( flags & (PHY_BCM542XX_REG_1000X |
    546                   PHY_BCM542XX_REG_PRI_SERDES) ) {  /* fiber registers */
    547         if ( reg_addr <= 0x0f ) {
    548             if ( PHY_IS_BCM54210_220(pc) && (flags & PHY_BCM542XX_REG_1000X) ) {
    549                 /* 54220/210 fiber is controlled by Secondary SerDes */
    550                 rv = phy_bcm542xx_direct_reg_write(unit, pc,(uint16)
    551                                 reg_addr | PHY_BCM542XX_2ND_SERDES_BASE_OFFSET,
    552                                 data);
    553             } else {  /* not 54220_210 or PHY_BCM542XX_REG_PRI_SERDES */
    554                 /* Map 1000X page */
    555 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
    556                 uint16 blk_sel, val;
    557                 val = 0x7c00;
    558                 SOC_IF_ERROR_RETURN
    559                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val));
    560                 SOC_IF_ERROR_RETURN
    561                     (PHY_BCM542XX_READ_PHY_REG( unit, pc, 0x1c, &blk_sel));
    562                 val = blk_sel | 0x8001;
    563                 SOC_IF_ERROR_RETURN
    564                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val));
    565 #else
    566                 SOC_IF_ERROR_RETURN(
    567                     phy_bcm542xx_direct_reg_modify(unit, pc,
    568                                     PHY_BCM542XX_MODE_CONTROL_REG_OFFSET,
    569                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN,
    570                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) );
    571 #endif
    572                 /* Write 1000X IEEE register */
    573                 SOC_IF_ERROR_RETURN
    574                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, data));
    575 
    576                /* Restore IEEE mapping */
    577 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
    578                 val = (blk_sel & 0xfffe) | 0x8000;
    579                 SOC_IF_ERROR_RETURN
    580                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val));
    581 #else
    582                 SOC_IF_ERROR_RETURN(
    583                     phy_bcm542xx_direct_reg_modify(unit, pc,
    584                                     PHY_BCM542XX_MODE_CONTROL_REG_OFFSET,
    585                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_DIS,
    586                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) );
    587 #endif
    588             }
    589         } else {  /*  (reg_addr > 0xf)  */
    590             rv = SOC_E_PARAM;
    591         }
    592 
    593     } else {
    594         switch ( reg_addr ) {
    595         /* Map shadow registers */
    596         case 0x15:
    597             SOC_IF_ERROR_RETURN
    598                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x17, reg_bank));
    599             break;
    600         case 0x18:
    601             if ( reg_bank <= 0x0007 ) {
    602                 if (reg_bank == 0x0007) {
    603                     data |= 0x8000;
    604                 }
    605                 data = (data & ~(0x0007)) | reg_bank;
    606             } else {
    607                 rv = SOC_E_PARAM;
    608             }
    609             break;
    610         case 0x1C:
    611             if ( reg_bank <= 0x001F ) {
    612                 data = 0x8000 | (reg_bank << 10) | (data & 0x03FF);
    613             } else {
    614                 rv = SOC_E_PARAM;
    615             }
    616             break;
    617         case 0x1D:
    618             if ( reg_bank == 0x0000 ) {
    619                 data = data & 0x07FFF;
    620             } else {
    621                 rv = SOC_E_PARAM;
    622             }
    623             break;
    624         }
    625         if ( SOC_SUCCESS(rv) ) {
    626             rv = PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, data);
    627         }
    628     } 
    629 
    630     if ( SOC_FAILURE(rv) ) {
    631         LOG_INFO(BSL_LS_SOC_PHY,
    632                  (BSL_META_U(unit,
    633                              "phy_bcm542xx_reg_write: failed:"
    634                              "phy_id=0x%2x reg_bank=0x%04x reg_addr=0x%02x "
    635                              "rv=%d\n"), pc->phy_id, reg_bank, reg_addr, rv)); 
    636     }
    637     return rv;
    638 }
    639 
    640 int
    641 phy_bcm542xx_reg_modify(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank,
    642                         uint8 reg_addr, uint16 data, uint16 mask)
    643 {
    644     int     rv;
    645     uint16 val;
    646 
    647     if ( flags & PHY_BCM542XX_REG_QSGMII ) {
    648         /* Do not apply shadow register logic for QSGMII register access */
    649         SOC_IF_ERROR_RETURN
    650             (PHY_BCM542XX_MODIFY_PHY_REG(unit, pc, reg_addr, data, mask));
    651         return SOC_E_NONE;
    652     }
    653 
    654     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
    655         return SOC_E_NONE;
    656     }
    657     rv = SOC_E_NONE;
    658 
    659     if ( flags & (PHY_BCM542XX_REG_1000X |
    660                   PHY_BCM542XX_REG_PRI_SERDES) ) {  /* fiber registers */
    661         if ( reg_addr <= 0x0f ) {
    662             if ( PHY_IS_BCM54210_220(pc) && (flags & PHY_BCM542XX_REG_1000X) ) {
    663                 /* 54220/210 fiber is controlled by Secondary SerDes */
    664                 rv = phy_bcm542xx_direct_reg_modify(unit, pc,(uint16)
    665                                 reg_addr | PHY_BCM542XX_2ND_SERDES_BASE_OFFSET,
    666                                 data, mask);
    667             } else {  /* not 54220_210 or PHY_BCM542XX_REG_PRI_SERDES */
    668                 /* Map 1000X page */
    669 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
    670                 uint16 blk_sel;
    671                 val = 0x7c00;
    672                 SOC_IF_ERROR_RETURN
    673                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val));
    674                 SOC_IF_ERROR_RETURN
    675                     (PHY_BCM542XX_READ_PHY_REG( unit, pc, 0x1c, &blk_sel));
    676                 val = blk_sel | 0x8001;
    677                 SOC_IF_ERROR_RETURN
    678                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val));
    679 #else
    680                 SOC_IF_ERROR_RETURN(
    681                     phy_bcm542xx_direct_reg_modify(unit, pc,
    682                                     PHY_BCM542XX_MODE_CONTROL_REG_OFFSET,
    683                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN,
    684                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) );
    685 #endif
    686                 /* Modify 1000X IEEE register */
    687                 SOC_IF_ERROR_RETURN
    688                     (PHY_BCM542XX_MODIFY_PHY_REG(unit, pc, reg_addr, data, mask));
    689 
    690                /* Restore IEEE mapping */
    691 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
    692                 val = (blk_sel & 0xfffe) | 0x8000;
    693                 SOC_IF_ERROR_RETURN
    694                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val));
    695 #else
    696                 SOC_IF_ERROR_RETURN(
    697                     phy_bcm542xx_direct_reg_modify(unit, pc,
    698                                     PHY_BCM542XX_MODE_CONTROL_REG_OFFSET,
    699                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_DIS,
    700                                     PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) );
    701 #endif
    702             }
    703         } else {  /*  (reg_addr > 0xf)  */
    704             rv = SOC_E_PARAM;
    705         }
    706 
    707     } else {
    708         switch ( reg_addr ) {
    709         /* Map shadow registers */
    710         case 0x15:
    711             SOC_IF_ERROR_RETURN
    712                 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x17, reg_bank));
    713             break;
    714         case 0x18:
    715             if ( reg_bank <= 0x0007 ) {
    716                 val = (reg_bank << 12) | 0x7;
    717                 SOC_IF_ERROR_RETURN
    718                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, val));
    719 
    720                 if (reg_bank == 0x0007) {
    721                     data |= 0x8000;
    722                     mask |= 0x8000;
    723                 }
    724                 mask &= ~(0x0007);
    725             } else {
    726                 rv = SOC_E_PARAM;
    727             }
    728             break;
    729         case 0x1C:
    730             if ( reg_bank <= 0x001F ) {
    731                 val = (reg_bank << 10);
    732                 SOC_IF_ERROR_RETURN
    733                     (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, val));
    734                 data |= 0x8000;
    735                 mask |= 0x8000;
    736                 mask &= ~(0x1F << 10);
    737             } else {
    738                 rv = SOC_E_PARAM;
    739             }
    740             break;
    741         case 0x1D:
    742             if ( reg_bank == 0x0000 ) {
    743                 mask &= 0x07FFF;
    744             } else {
    745                 rv = SOC_E_PARAM;
    746             }
    747             break;
    748         }
    749         if ( SOC_SUCCESS(rv) ) {
    750             rv = PHY_BCM542XX_MODIFY_PHY_REG(unit, pc, reg_addr, data, mask);
    751         }
    752     }
    753 
    754     if ( SOC_FAILURE(rv) ) {
    755         LOG_INFO(BSL_LS_SOC_PHY,
    756                  (BSL_META_U(unit,
    757                              "phy_bcm542xx_reg_modify: failed:"
    758                              "phy_id=0x%2x reg_bank=0x%04x reg_addr=0x%02x "
    759                              "rv=%d\n"), pc->phy_id, reg_bank, reg_addr, rv)); 
    760     }
    761     return rv;
    762 }
    763 
    764 int 
    765 phy_bcm542xx_reg_read_modify_write(int unit, phy_ctrl_t *pc, uint32 reg_addr,
    766                                    uint16 reg_data, uint16 reg_mask)
    767 {
    768     uint16  tmp, otmp;
    769 
    770     reg_data = reg_data & reg_mask;
    771 
    772     SOC_IF_ERROR_RETURN
    773         (PHY_BCM542XX_READ_PHY_REG(unit, pc, reg_addr, &tmp));
    774     otmp = tmp;
    775     tmp &= ~(reg_mask);
    776     tmp |= reg_data;
    777 
    778     if (otmp != tmp) {
    779         SOC_IF_ERROR_RETURN
    780             (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, tmp));
    781     }
    782     return SOC_E_NONE;
    783 }
    784 
    785 
    786 /*
    787  * Function:
    788  *     phy_bcm542xx_rdb_reg_read
    789  * Purpose:  RDB register read
    790  *           (works ONLY under RDB register addressing mode !!)
    791  * Parameters:
    792  *     reg_addr - RDB register address
    793  *     data     - the 16-bit value got from the specific RDB register
    794  * Returns:
    795  */
    796 int phy_bcm542xx_rdb_reg_read(int unit, phy_ctrl_t *pc,
    797                               uint16 reg_addr, uint16 *data)
    798 {
    799     int rv;
    800 
    801     /* MDIO write the RDB reg. address to reg.0x1E = <reg_addr> */
    802     rv = PHY_BCM542XX_WRITE_PHY_REG(unit, pc,
    803                         PHY_BCM542XX_RDB_ADDR_REG_OFFSET,
    804                         PHY_BCM542XX_RDB_ADDR_REG_ADDR & reg_addr);
    805     if ( SOC_E_NONE == rv ) {
    806         /* MDIO read from reg.0x1F to get the RDB register's value as <data> */
    807         rv = PHY_BCM542XX_READ_PHY_REG(unit, pc,
    808                         PHY_BCM542XX_RDB_DATA_REG_OFFSET, data);
    809     }
    810 
    811 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
    812     if ( SOC_E_NONE != rv ) {          /* failed to access reg. 0x1e or 0x1f */
    813         PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc);   /* quit RDB assess mode */
    814         _SHR_ERROR_TRACE(rv);
    815     }
    816 #endif
    817     return (rv);
    818 }
    819 
    820 /*
    821  * Function:
    822  *     phy_bcm542xx_rdb_reg_write
    823  * Purpose:  RDB register write
    824  *           (works ONLY under RDB register addressing mode !!)
    825  * Parameters:
    826  *     reg_addr - RDB register address
    827  *     data     - 16-bit value writting to the specific RDB register
    828  * Returns:
    829  */
    830 int phy_bcm542xx_rdb_reg_write(int unit, phy_ctrl_t *pc,
    831                                uint16 reg_addr, uint16 data)
    832 {
    833     int rv;
    834 
    835     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
    836         return SOC_E_NONE;
    837     }
    838 
    839     /* MDIO write the RDB reg. address to reg.0x1E = <reg_addr> */
    840     rv = PHY_BCM542XX_WRITE_PHY_REG(unit, pc,
    841                         PHY_BCM542XX_RDB_ADDR_REG_OFFSET,
    842                         PHY_BCM542XX_RDB_ADDR_REG_ADDR & reg_addr);
    843     if ( SOC_E_NONE == rv ) {
    844         /* MDIO write to reg.0x1F to set the RDB resister's value as <data> */
    845         rv = PHY_BCM542XX_WRITE_PHY_REG(unit, pc,
    846                         PHY_BCM542XX_RDB_DATA_REG_OFFSET, data);
    847     }
    848 
    849 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
    850     if ( SOC_E_NONE != rv ) {          /* failed to access reg. 0x1e or 0x1f */
    851         PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc);   /* quit RDB assess mode */
    852         _SHR_ERROR_TRACE(rv);
    853     }
    854 #endif
    855     return (rv);
    856 }
    857 
    858 /*
    859  * Function:
    860  *     phy_bcm542xx_rdb_reg_modify
    861  * Purpose:  RDB register modification
    862  *           (works ONLY under RDB register addressing mode !!)
    863  * Parameters:
    864  *     reg_addr - RDB register address
    865  *     data     - 16-bit value writting to the specific RDB register
    866  *     mask     - bit mask
    867  * Returns:
    868  */
    869 int phy_bcm542xx_rdb_reg_modify(int unit, phy_ctrl_t *pc,
    870                                 uint16 reg_addr, uint16 data, uint16 mask)
    871 {
    872     int rv;
    873 
    874     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
    875         return SOC_E_NONE;
    876     }
    877 
    878     /* MDIO write the RDB reg. address to reg.0x1E = <reg_addr> */
    879     rv = PHY_BCM542XX_WRITE_PHY_REG(unit, pc,
    880                         PHY_BCM542XX_RDB_ADDR_REG_OFFSET,
    881                         PHY_BCM542XX_RDB_ADDR_REG_ADDR & reg_addr);
    882     if ( SOC_E_NONE == rv ) {
    883         /* MDIO read from reg.0x1F to modify the RDB register's value */
    884         rv = PHY_BCM542XX_MODIFY_PHY_REG(unit, pc,
    885                         PHY_BCM542XX_RDB_DATA_REG_OFFSET, data, mask);
    886     }
    887 
    888 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
    889     if ( SOC_E_NONE != rv ) {          /* failed to access reg. 0x1e or 0x1f */
    890         PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc);   /* quit RDB assess mode */
    891         _SHR_ERROR_TRACE(rv);
    892     }
    893 #endif
    894     return (rv);
    895 }
    896 
    897 
    898 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
    899 
    900 /*
    901  * Function:
    902  *     phy_bcm542xx_direct_reg_read
    903  * Purpose:
    904  *     switching to RDB access mode and read an RDB register,
    905  *     then back to the legacy access mode (quit the RDB mode).
    906  * Parameters:
    907  * Returns:
    908  */
    909 int phy_bcm542xx_direct_reg_read(int unit, phy_ctrl_t *pc,
    910                                  uint16 reg_addr, uint16 *data)
    911 {
    912     int  rv;
    913 
    914     PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc);   /* set RDB register access mode */
    915     rv = phy_bcm542xx_rdb_reg_read(unit, pc, reg_addr, data);
    916     PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */
    917     return (rv);
    918 }
    919 
    920 /*
    921  * Function:
    922  *    phy_bcm542xx_direct_reg_write
    923  * Purpose:
    924  *     switching to RDB access mode and write an RDB register,
    925  *     then back to the legacy access mode (quit the RDB mode).
    926  * Parameters:
    927  * Returns:
    928  */
    929 int phy_bcm542xx_direct_reg_write(int unit, phy_ctrl_t *pc,
    930                                   uint16 reg_addr, uint16 data)
    931 {
    932     int  rv;
    933 
    934     PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc);   /* set RDB register access mode */
    935     rv = phy_bcm542xx_rdb_reg_write(unit, pc, reg_addr, data);
    936     PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */
    937     return (rv);
    938 }
    939 
    940 /*
    941  * Function:
    942  *    phy_bcm542xx_direct_reg_modify
    943  * Purpose:
    944  *     switching to RDB access mode and modify an RDB register,
    945  *     then back to the legacy access mode (quit the RDB mode).
    946  * Parameters:
    947  * Returns:
    948  */
    949 int phy_bcm542xx_direct_reg_modify(int unit, phy_ctrl_t *pc,
    950                                    uint16 reg_addr, uint16 data, uint16 mask)
    951 {
    952     int  rv;
    953 
    954     PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc);   /* set RDB register access mode */
    955     rv = phy_bcm542xx_rdb_reg_modify(unit, pc, reg_addr, data, mask);
    956     PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */
    957     return (rv);
    958 }
    959 
    960 #endif /* PHY_BCM542XX_DEFAULT_TO_LEGACY_ACCESS */
    961 
    962 /*
    963  * QSGMII register READ
    964  */
    965 int 
    966 phy_bcm542xx_qsgmii_reg_read(int unit, phy_ctrl_t *pc,
    967                              int dev_port, uint16 block,
    968                              uint8 reg, uint16 *data)
    969 {
    970     uint16  val;
    971     
    972     /* Lanes from 0 to 7 */
    973     if ((dev_port < 0) || (dev_port > 7) ) {
    974         return SOC_E_FAIL;
    975     }
    976 
    977     /* Set BAR to AER */
    978     if ( PHY_IS_BCM5418x_19x(pc) ) {
    979         val = 0xFFDE;
    980     } else {
    981         val = 0xFFD0;
    982     }
    983     SOC_IF_ERROR_RETURN
    984         (phy_bcm542xx_reg_write(unit, pc, PHY_BCM542XX_REG_QSGMII,
    985                                 0, 0x1F, val));
    986 
    987     /* Set AER reg to access SGMII lane */
    988     val = dev_port;
    989     SOC_IF_ERROR_RETURN
    990         (phy_bcm542xx_reg_write(unit, pc, PHY_BCM542XX_REG_QSGMII,
    991                                 0, 0x1E, val));
    992 
    993     /* Set BAR to Register Block */
    994     val = (block & 0xfff0);
    995     SOC_IF_ERROR_RETURN
    996         (phy_bcm542xx_reg_write(unit, pc, PHY_BCM542XX_REG_QSGMII,
    997                                 0, 0x1F, val));
    998     /* Read the register */
    999     if ( block >= 0x8000 ) {
   1000         reg |= 0x10;
   1001     }
   1002 
   1003     SOC_IF_ERROR_RETURN
   1004         (phy_bcm542xx_reg_read(unit, pc, PHY_BCM542XX_REG_QSGMII,
   1005                                0, reg, data));
   1006 
   1007     return SOC_E_NONE;
   1008 
   1009 }
   1010 
   1011 /*
   1012  * QSGMII register WRITE
   1013  */
   1014 int 
   1015 phy_bcm542xx_qsgmii_reg_write(int unit, phy_ctrl_t *pc,
   1016         int dev_port, uint16 block, uint8 reg, 
   1017         uint16 data)
   1018 {
   1019     uint16  val;
   1020 
   1021     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   1022         return SOC_E_NONE;
   1023     }
   1024 
   1025     /* Lanes from 0 to 7 */
   1026     if ((dev_port < 0) || (dev_port > 7) ) {
   1027         return SOC_E_FAIL;
   1028     }
   1029 
   1030     /* Set BAR to AER */
   1031     if ( PHY_IS_BCM5418x_19x(pc) ) {
   1032         val = 0xFFDE;
   1033     } else {
   1034         val = 0xFFD0;
   1035     }
   1036 
   1037     SOC_IF_ERROR_RETURN
   1038         (phy_bcm542xx_reg_write(unit, pc,
   1039                                 PHY_BCM542XX_REG_QSGMII, 0, 0x1F, val));
   1040 
   1041     /* set aer reg to access sgmii lane */
   1042     val = dev_port;
   1043     SOC_IF_ERROR_RETURN
   1044         (phy_bcm542xx_reg_write(unit, pc,
   1045                                 PHY_BCM542XX_REG_QSGMII, 0, 0x1E, val));
   1046 
   1047     /* set bar to register block */
   1048     val = (block & 0xfff0);
   1049     SOC_IF_ERROR_RETURN
   1050         (phy_bcm542xx_reg_write(unit, pc,
   1051                                 PHY_BCM542XX_REG_QSGMII, 0, 0x1F, val));
   1052 
   1053     /* Write the register */
   1054     if (block >= 0x8000) {
   1055         reg |= 0x10;
   1056     }
   1057 
   1058     SOC_IF_ERROR_RETURN
   1059         (phy_bcm542xx_reg_write(unit, pc,
   1060                                 PHY_BCM542XX_REG_QSGMII, 0, reg, data));
   1061 
   1062     return SOC_E_NONE;
   1063 }
   1064 
   1065 /*
   1066  * QSGMII register MODIFY
   1067  */
   1068 int 
   1069 phy_bcm542xx_qsgmii_reg_modify(int unit, phy_ctrl_t *pc,
   1070                                int dev_port, uint16 block,
   1071                                uint8 reg_addr, uint16 reg_data,
   1072                                uint16 reg_mask)
   1073 {
   1074     uint16  tmp, otmp;
   1075 
   1076     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   1077         return SOC_E_NONE;
   1078     }
   1079 
   1080     reg_data = reg_data & reg_mask;
   1081 
   1082     phy_bcm542xx_qsgmii_reg_read(unit, pc, dev_port, block,
   1083                                  reg_addr, &tmp);
   1084     otmp = tmp;
   1085     tmp &= ~(reg_mask);
   1086     tmp |= reg_data;
   1087 
   1088     if (otmp != tmp) {
   1089         phy_bcm542xx_qsgmii_reg_write(unit, pc, dev_port, block,
   1090                                       reg_addr, tmp);
   1091     }
   1092     return SOC_E_NONE;
   1093 }
   1094 
   1095 /*
   1096  * Function:
   1097  *      phy_bcm542xx_cl45_reg_read
   1098  * Purpose:
   1099  *      Read Clause 45 Register using Clause 22 register access
   1100  * Parameters:
   1101  *      unit      - StrataSwitch unit #.
   1102  *      pc        - Phy control
   1103  *      flags     - Flags
   1104  *      dev_addr  - Clause 45 Device
   1105  *      reg_addr  - Register Address to read
   1106  *      val       - Value Read
   1107  * Returns:
   1108  *      SOC_E_XXX
   1109  */
   1110 
   1111 int
   1112 phy_bcm542xx_cl45_reg_read(int unit, phy_ctrl_t *pc, uint8 dev_addr,
   1113                            uint16 reg_addr, uint16 *val)
   1114 {
   1115     uint16  temp16 = (dev_addr & 0x001f);
   1116 
   1117     /* Write Device Address to register 0x0D (Set Function field to Address) */
   1118     SOC_IF_ERROR_RETURN
   1119         (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0D, temp16));
   1120 
   1121     /* Select the register by writing to register address to register 0x0E */
   1122     SOC_IF_ERROR_RETURN
   1123         (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0E, reg_addr));
   1124 
   1125     temp16 = 0x4000 | (dev_addr & 0x001f);
   1126     /* Write Device Address to register 0x0D (Set Function field to Data) */
   1127     SOC_IF_ERROR_RETURN
   1128         (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0D, temp16)); 
   1129 
   1130     /* Read register 0x0E to get the value */
   1131     SOC_IF_ERROR_RETURN
   1132         (PHY_BCM542XX_READ_PHY_REG( unit, pc, 0x0E, val));
   1133 
   1134     return SOC_E_NONE;
   1135 }
   1136 
   1137 /*
   1138  * Function:
   1139  *      phy_bcm542xx_cl45_reg_write
   1140  * Purpose:
   1141  *      Write Clause 45 Register content using Clause 22 register access
   1142  * Parameters:
   1143  *      unit      - StrataSwitch unit #.
   1144  *      pc        - Phy control
   1145  *      flags     - Flags
   1146  *      dev_addr  - Clause 45 Device
   1147  *      reg_addr  - Register Address to read
   1148  *      val       - Value to be written
   1149  * Returns:
   1150  *      SOC_E_XXX
   1151  */
   1152 
   1153 int
   1154 phy_bcm542xx_cl45_reg_write(int unit, phy_ctrl_t *pc, uint8 dev_addr,
   1155                             uint16 reg_addr, uint16 val)
   1156 {
   1157     uint16  temp16 = (dev_addr & 0x001f);
   1158 
   1159     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   1160         return SOC_E_NONE;
   1161     }
   1162 
   1163     /* Write Device Address to register 0x0D (Set Function field to Address)*/
   1164     SOC_IF_ERROR_RETURN
   1165         (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0D, temp16));
   1166 
   1167     /* Select the register by writing to register address to register 0x0E */
   1168     SOC_IF_ERROR_RETURN
   1169         (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0E, reg_addr));
   1170 
   1171     temp16 = 0x4000 | (dev_addr & 0x001f);
   1172     /* Write Device Address to register 0x0D (Set Function field to Data)*/
   1173     SOC_IF_ERROR_RETURN
   1174         (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0D, temp16)); 
   1175 
   1176     /* Write register 0x0E to write the value */
   1177     SOC_IF_ERROR_RETURN
   1178         (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0E, val));
   1179 
   1180     return SOC_E_NONE;
   1181 }
   1182 
   1183 /*
   1184  * Function:
   1185  *     _phy_bcm542xx_cl45_reg_modify
   1186  * Purpose:
   1187  *      Modify Clause 45 Register contents using Clause 22 register access
   1188  * Parameters:
   1189  *      unit      - StrataSwitch unit #.
   1190  *      pc        - Phy control
   1191  *      flags     - Flags
   1192  *      reg_bank  - Register bank
   1193  *      dev_addr  - Clause 45 Device
   1194  *      reg_addr  - Register Address to read
   1195  *      val       - Value 
   1196  *      mask      - Mask for modifying the contents of the register
   1197  * Returns:
   1198  *      SOC_E_XXX
   1199  */
   1200 
   1201 int
   1202 phy_bcm542xx_cl45_reg_modify(int unit, phy_ctrl_t *pc, uint8 dev_addr, 
   1203                              uint16 reg_addr, uint16 val, uint16 mask)
   1204 {
   1205     uint16  value = 0;
   1206 
   1207     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   1208         return SOC_E_NONE;
   1209     }
   1210 
   1211     phy_bcm542xx_cl45_reg_read(unit, pc, dev_addr, reg_addr, &value);
   1212 
   1213     value = (val & mask) | (value & ~mask);
   1214 
   1215     phy_bcm542xx_cl45_reg_write(unit, pc, dev_addr, reg_addr, value);
   1216     
   1217     return SOC_E_NONE;
   1218 }
   1219 
   1220 /*
   1221  * Function:
   1222  *    _phy_bcm542xx_hidden_rev_num_get
   1223  * Purpose:
   1224  *    Get hidden revision number from CORE_ExpFA - Hidden Identifier Reg.
   1225  *    For distinguishing  54296 vs. 54295  ( 0x8 vs. 0x0 )
   1226  * Parameters:
   1227  *
   1228  * Notes: 
   1229  */
   1230 STATIC uint16
   1231 _phy_bcm542xx_hidden_rev_num_get(int unit, phy_ctrl_t *pc)
   1232 {
   1233     uint16  hidden_rev;
   1234     /* CORE_ExpFA - Hidden Identifier Reg., RDB.0x0FA[3:0] HIDDEN_REV_NUM */
   1235     phy_bcm542xx_direct_reg_read(unit, pc,
   1236                         PHY_BCM542XX_HIDDEN_IDENTIFIER_REG_OFFSET, &hidden_rev);
   1237     return  (hidden_rev & PHY_BCM542XX_HIDDEN_REV_NUM_MASK);
   1238 }
   1239 
   1240 /*
   1241  * Function:
   1242  *    _phy_bcm542xx_get_model_rev
   1243  * Purpose:
   1244  *    Get OUI, Model and Revision of the PHY
   1245  * Parameters:
   1246  *    phy_dev_addr - PHY Device Address
   1247  *    oui          - (OUT) Organization Unique Identifier
   1248  *    model        - (OUT)Device Model number`
   1249  *    rev          - (OUT)Device Revision number
   1250  * Notes: 
   1251  */
   1252 STATIC int
   1253 _phy_bcm542xx_model_rev_get(int unit, phy_ctrl_t *pc,
   1254                             int *oui, int *model, int *rev)
   1255 {
   1256     uint16  id0, id1;
   1257 
   1258     SOC_IF_ERROR_RETURN
   1259         (PHY_READ_BCM542XX_MII_PHY_ID0r(unit, pc, &id0));
   1260     SOC_IF_ERROR_RETURN
   1261         (PHY_READ_BCM542XX_MII_PHY_ID1r(unit, pc, &id1));
   1262 
   1263     *oui   = PHY_OUI(id0, id1);
   1264     *model = PHY_MODEL(id0, id1);
   1265     *rev   = PHY_REV(id0, id1);
   1266 
   1267     return SOC_E_NONE;
   1268 }
   1269 
   1270 
   1271 /*
   1272  * Function:
   1273  *    _phy_bcm542xx_auto_negotiate_ew (Autoneg-ed mode with E@W on).
   1274  * Purpose:
   1275  *    Determine autoneg-ed mode between
   1276  *    two ends of a link
   1277  * Parameters:
   1278  *    unit - StrataSwitch unit #.
   1279  *    port - StrataSwitch port #. 
   1280  *    speed - (OUT) greatest common speed.
   1281  *    duplex - (OUT) greatest common duplex.
   1282  *    link - (OUT) Boolean, true indicates link established.
   1283  * Returns:
   1284  *    SOC_E_XXX
   1285  * Notes: 
   1286  *    No synchronization performed at this level.
   1287  */
   1288 
   1289 static int
   1290 _phy_bcm542xx_auto_negotiate_ew(int unit, phy_ctrl_t *pc, int *speed, int *duplex)
   1291 {
   1292     int        t_speed, t_duplex;
   1293     uint16  mii_assr;
   1294 
   1295     SOC_IF_ERROR_RETURN
   1296             (PHY_READ_BCM542XX_MII_AUX_STATUSr(unit, pc,&mii_assr));
   1297 
   1298     switch ((mii_assr >> 8) & 0x7) {
   1299     case 0x7:
   1300         t_speed = 1000;
   1301         t_duplex = TRUE;
   1302         break;
   1303     case 0x6:
   1304         t_speed = 1000;
   1305         t_duplex = FALSE;
   1306         break;
   1307     case 0x5:
   1308         t_speed = 100;
   1309         t_duplex = TRUE;
   1310         break;
   1311     case 0x3:
   1312         t_speed = 100;
   1313         t_duplex = FALSE;
   1314         break;
   1315     case 0x2:
   1316         t_speed = 10;
   1317         t_duplex = TRUE;
   1318         break;
   1319     case 0x1:
   1320         t_speed = 10;
   1321         t_duplex = FALSE;
   1322         break;
   1323     default:
   1324         t_speed = 0; /* 0x4 is 100BASE-T4 which is not supported */
   1325         t_duplex = FALSE;
   1326         break;
   1327     }
   1328 
   1329     if (speed)  *speed  = t_speed;
   1330     if (duplex)    *duplex = t_duplex;
   1331 
   1332     return(SOC_E_NONE);
   1333 }
   1334 
   1335 /*
   1336  * Function:
   1337  *    _phy_bcm542xx_auto_negotiate_gcd (greatest common denominator).
   1338  * Purpose:
   1339  *    Determine the current greatest common denominator between 
   1340  *    two ends of a link
   1341  * Parameters:
   1342  *    speed - (OUT) greatest common speed.
   1343  *    duplex - (OUT) greatest common duplex.
   1344  *    link - (OUT) Boolean, true indicates link established.
   1345  * Notes: 
   1346  */
   1347 
   1348 STATIC int
   1349 _phy_bcm542xx_auto_negotiate_gcd(int unit,soc_port_t port, phy_ctrl_t *pc, int *speed, int *duplex)
   1350 {
   1351     int       t_speed, t_duplex;
   1352     uint16 mii_ana, mii_anp, mii_stat;
   1353     uint16 mii_gb_stat, mii_esr, mii_gb_ctrl;
   1354 #ifdef INCLUDE_PLP_IMACSEC
   1355     int speed_m;
   1356     unsigned int  port_m;
   1357     bcm_plp_base_t_sec_phy_access_t *imacsec_des;
   1358     uint16 imacsec_cfg;
   1359     soc_port_t port_s;
   1360     PHY_BCM542XX_DEV_DESC_t *phy_des=NULL;
   1361     unsigned int speed_mask=0x3;
   1362 #else
   1363     COMPILER_REFERENCE(port);
   1364 #endif
   1365 #ifdef INCLUDE_PLP_IMACSEC
   1366     imacsec_des = IMACSEC_DES_PTR_GET(pc);
   1367     phy_des = (PHY_BCM542XX_DEV_DESC_t *)(pc+1);
   1368 #endif
   1369 
   1370     mii_gb_stat = 0;            /* Start off 0 */
   1371     mii_gb_ctrl = 0;            /* Start off 0 */
   1372 
   1373     SOC_IF_ERROR_RETURN(
   1374         PHY_READ_BCM542XX_MII_ANAr(unit, pc,&mii_ana));
   1375     SOC_IF_ERROR_RETURN(
   1376         PHY_READ_BCM542XX_MII_ANPr(unit, pc,&mii_anp));
   1377     SOC_IF_ERROR_RETURN(
   1378         PHY_READ_BCM542XX_MII_STATr(unit, pc,&mii_stat));
   1379 
   1380     if (mii_stat & PHY_BCM542XX_MII_STAT_ES) {    /* Supports extended status */
   1381         /*
   1382          * If the PHY supports extended status, check if it is 1000MB
   1383          * capable.  If it is, check the 1000Base status register to see
   1384          * if 1000MB negotiated.
   1385          */
   1386         SOC_IF_ERROR_RETURN(
   1387             PHY_READ_BCM542XX_MII_ESRr(unit, pc,&mii_esr));
   1388 
   1389         if (mii_esr & (PHY_BCM542XX_MII_ESR_1000_X_FD | PHY_BCM542XX_MII_ESR_1000_X_HD | 
   1390                        PHY_BCM542XX_MII_ESR_1000_T_FD | PHY_BCM542XX_MII_ESR_1000_T_HD) ) {
   1391             SOC_IF_ERROR_RETURN(
   1392                 PHY_READ_BCM542XX_MII_GB_STATr(unit, pc,
   1393                                                    &mii_gb_stat));
   1394             SOC_IF_ERROR_RETURN(
   1395                 PHY_READ_BCM542XX_MII_GB_CTRLr(unit, pc,
   1396                                                    &mii_gb_ctrl));
   1397         }
   1398     }
   1399 
   1400     /*
   1401      * At this point, if we did not see Gig status, one of mii_gb_stat or 
   1402      * mii_gb_ctrl will be 0. This will cause the first 2 cases below to 
   1403      * fail and fall into the default 10/100 cases.
   1404      */
   1405     mii_ana &= mii_anp;
   1406 
   1407     if ((mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_ADV_1000FD) &&
   1408         (mii_gb_stat & PHY_BCM542XX_MII_GB_STAT_LP_1000FD) ) {
   1409         t_speed  = 1000;
   1410         t_duplex = 1;
   1411     } else if ((mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_ADV_1000HD) &&
   1412                (mii_gb_stat & PHY_BCM542XX_MII_GB_STAT_LP_1000HD) ) {
   1413         t_speed  = 1000;
   1414         t_duplex = 0;
   1415     } else if (mii_ana & PHY_BCM542XX_MII_ANA_FD_100) {        /* [a] */
   1416         t_speed = 100;
   1417         t_duplex = 1;
   1418     } else if (mii_ana & PHY_BCM542XX_MII_ANA_T4) {            /* [b] */
   1419         t_speed = 100;
   1420         t_duplex = 0;
   1421     } else if (mii_ana & PHY_BCM542XX_MII_ANA_HD_100) {        /* [c] */
   1422         t_speed = 100;
   1423         t_duplex = 0;
   1424     } else if (mii_ana & PHY_BCM542XX_MII_ANA_FD_10) {         /* [d] */
   1425         t_speed = 10;
   1426         t_duplex = 1 ;
   1427     } else if (mii_ana & PHY_BCM542XX_MII_ANA_HD_10) {         /* [e] */
   1428         t_speed = 10;
   1429         t_duplex = 0;
   1430     } else {
   1431         return(SOC_E_FAIL);
   1432     }
   1433 
   1434     if (speed) {
   1435         *speed  = t_speed;
   1436     }
   1437     if (duplex) {
   1438         if (t_duplex) {
   1439             *duplex = TRUE;
   1440         } else {
   1441             *duplex = FALSE;
   1442         }
   1443     }
   1444 #ifdef INCLUDE_PLP_IMACSEC
   1445     if((phy_des->port_pre_speed != 1000) && (t_speed == 1000)){   /* If speed changed from 10M/100M to 1G speed, MAC need to be reconfigured again to restart the autoneg */
   1446         if(pc->macsec_enable){
   1447             port_m = get_port(&imacsec_des->phy_info);
   1448             SPEED_MAPPING(t_speed,speed_m);
   1449             /* Use base phy id to write top register */
   1450             pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   1451             /* SW set speed MACSEC_CONFIG2 reg */
   1452             SOC_IF_ERROR_RETURN
   1453                 (phy_bcm542xx_cl45_reg_read(unit, pc,  0x7, 0x9870, &imacsec_cfg));
   1454             imacsec_cfg |= 1<<port_m;
   1455             SOC_IF_ERROR_RETURN
   1456                 (phy_bcm542xx_cl45_reg_write(unit, pc,  0x7, 0x9870, imacsec_cfg));
   1457             /* SW set speed MACSEC_CONFIG3 reg */
   1458             SOC_IF_ERROR_RETURN
   1459                 (phy_bcm542xx_cl45_reg_read(unit, pc,  0x7, 0x9871, &imacsec_cfg));
   1460             imacsec_cfg &= ~(speed_mask << (port_m*2));
   1461             imacsec_cfg |= (speed_m << (port_m*2));
   1462             SOC_IF_ERROR_RETURN
   1463                (phy_bcm542xx_cl45_reg_write(unit, pc,  0x7, 0x9871, imacsec_cfg));
   1464             /* Restore the phy mdio address */
   1465             pc->phy_id =  PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   1466 
   1467             port_s= PHY_UNIMAC_V2_SWITCH_PORT(port);
   1468             SOC_IF_ERROR_RETURN(
   1469                BMACSEC_MAC_AUTO_CONFIG_SET((phy_mac_ctrl_t *)imacsec_des->unimac, port_s, 0));
   1470 
   1471             SOC_IF_ERROR_RETURN(
   1472             BMACSEC_MAC_AUTO_CONFIG_SET((phy_mac_ctrl_t *)imacsec_des->unimac, port_s, 1));
   1473         }
   1474     }
   1475     phy_des->port_pre_speed = t_speed;
   1476 #endif
   1477 
   1478     return SOC_E_NONE;
   1479 }
   1480 
   1481 
   1482 STATIC int
   1483 _phy_bcm542xx_serdes_update(int unit, soc_port_t port)
   1484 {
   1485     phy_ctrl_t  *pc;
   1486     pc = EXT_PHY_SW_STATE(unit, port);
   1487 
   1488     /* check if ( Copper_disabled ) or ( fiber enabled and preferred ) */
   1489     if ( (!(pc->copper.enable)) ||
   1490           ((pc->fiber.enable) && (pc->fiber.preferred)) ) {
   1491         /* turn on the passive external SerDes 100FX if fiber 100FX mode */
   1492         uint16 serdes_mode = (pc->fiber.force_speed== 100)
   1493                            ? PHY_BCM542XX_EXT_SERDES_FX : 0;
   1494         /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */
   1495         SOC_IF_ERROR_RETURN(
   1496             PHY_MODIFY_BCM542XX_EXT_SERDES_CTRLr(unit, pc, serdes_mode,
   1497                                         PHY_BCM542XX_EXT_SERDES_FX_MASK) );
   1498     }
   1499     return SOC_E_NONE;
   1500 }
   1501 
   1502 /*
   1503  * Function:
   1504  *      phy_bcm542xx_medium_status
   1505  * Purpose:
   1506  *      Indicate the current active medium
   1507  * Parameters:
   1508  *      unit - StrataSwitch unit #.
   1509  *      port - StrataSwitch port #.
   1510  *      medium - (OUT) One of:
   1511  *              SOC_PORT_MEDIUM_COPPER
   1512  *              SOC_PORT_MEDIUM_FIBER
   1513  * Returns:
   1514  *      SOC_E_NONE
   1515  */
   1516 STATIC int
   1517 phy_bcm542xx_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium)
   1518 {
   1519     if ( PHY_COPPER_MODE(unit, port) ) {
   1520         *medium = SOC_PORT_MEDIUM_COPPER;
   1521     } else if ( PHY_FIBER_MODE(unit, port) ) {
   1522         *medium = SOC_PORT_MEDIUM_FIBER;
   1523     } else {
   1524         return SOC_E_INTERNAL;
   1525     }
   1526     return SOC_E_NONE;
   1527 }
   1528 
   1529 /*
   1530  * Function:
   1531  *      _phy_bcm542xx_medium_config_update
   1532  * Purpose:
   1533  *      Update the PHY with config parameters
   1534  * Parameters:
   1535  *      unit - StrataSwitch unit #.
   1536  *      port - StrataSwitch port #.
   1537  *      cfg - Config structure.
   1538  * Returns:
   1539  *      SOC_E_XXX
   1540  */
   1541 
   1542 STATIC int
   1543 _phy_bcm542xx_medium_config_update(int unit, soc_port_t port,
   1544                                    soc_phy_config_t *cfg)
   1545 {
   1546     SOC_IF_ERROR_RETURN
   1547         (phy_bcm542xx_speed_set(unit, port, cfg->force_speed));
   1548     SOC_IF_ERROR_RETURN
   1549         (phy_bcm542xx_duplex_set(unit, port, cfg->force_duplex));
   1550     SOC_IF_ERROR_RETURN
   1551         (phy_bcm542xx_master_set(unit, port, cfg->master));
   1552     SOC_IF_ERROR_RETURN
   1553         (phy_bcm542xx_ability_advert_set(unit, port, &cfg->advert_ability));
   1554     SOC_IF_ERROR_RETURN
   1555         (phy_bcm542xx_autoneg_set(unit, port, cfg->autoneg_enable));
   1556     SOC_IF_ERROR_RETURN
   1557         (phy_bcm542xx_mdix_set(unit, port, cfg->mdix));
   1558 
   1559     return SOC_E_NONE;
   1560 }
   1561 
   1562 /*
   1563  * Function:
   1564  *      _phy_bcm542xx_medium_check
   1565  * Purpose:
   1566  *      Determine if chip should operate in copper or fiber mode.
   1567  * Parameters:
   1568  *      unit - StrataSwitch unit #.
   1569  *      port - StrataSwitch port #.
   1570  *      medium - (OUT) SOC_PORT_MEDIUM_XXX
   1571  * Returns:
   1572  *      SOC_E_XXX
   1573  */
   1574 STATIC int
   1575 _phy_bcm542xx_medium_check(int unit, soc_port_t port, soc_port_medium_t *medium)
   1576 {
   1577     phy_ctrl_t    *pc = EXT_PHY_SW_STATE(unit, port);
   1578     uint16 mode_ctrl;
   1579 
   1580     *medium = SOC_PORT_MEDIUM_COPPER;
   1581 
   1582     if ( pc->automedium) {
   1583         SOC_IF_ERROR_RETURN
   1584             (PHY_READ_BCM542XX_MODE_CTRLr(unit, pc,&mode_ctrl));
   1585 
   1586         if ( pc->fiber.preferred) {
   1587            if ((mode_ctrl & 0x30) == 0x20) {
   1588                 /* Only Copper is linked up */
   1589                 *medium = SOC_PORT_MEDIUM_COPPER;
   1590             } else {
   1591                 *medium = SOC_PORT_MEDIUM_FIBER;
   1592             }
   1593         } else {
   1594             if ((mode_ctrl & 0x30) == 0x10) {
   1595                 /* Only Fiber is linked up */
   1596                 *medium = SOC_PORT_MEDIUM_FIBER;
   1597             } else {
   1598                 *medium = SOC_PORT_MEDIUM_COPPER;
   1599             }
   1600         }
   1601     } else {
   1602        *medium = pc->fiber.preferred ? SOC_PORT_MEDIUM_FIBER
   1603                                      : SOC_PORT_MEDIUM_COPPER; 
   1604     }
   1605     LOG_VERBOSE(BSL_LS_SOC_PHY,
   1606                 (BSL_META_U(unit, "_phy_bcm542xx_medium_check: "
   1607                             "u=%d p=%d fiber_pref=%d fiber=%d\n"),
   1608                  unit, port, pc->fiber.preferred,
   1609                  (*medium == SOC_PORT_MEDIUM_FIBER) ? 1 : 0));
   1610     return SOC_E_NONE;
   1611 }
   1612 
   1613 /*
   1614  * Function:
   1615  *      _phy_bcm542xx_medium_change
   1616  * Purpose:
   1617  *      Change medium when media change detected or forced
   1618  * Parameters:
   1619  *      unit         - StrataSwitch unit #.
   1620  *      port         - StrataSwitch port #.
   1621  *      force_update - Force update
   1622  *      force_medium - Force update medium
   1623  * Returns:
   1624  *      SOC_E_XXX
   1625  */
   1626 STATIC int
   1627 _phy_bcm542xx_medium_change(int unit, soc_port_t port,
   1628                             soc_port_medium_t force_medium)
   1629 {
   1630     phy_ctrl_t        *pc;
   1631     soc_port_medium_t  medium;
   1632 
   1633     pc = EXT_PHY_SW_STATE(unit, port);
   1634 
   1635     SOC_IF_ERROR_RETURN
   1636         (_phy_bcm542xx_medium_check(unit, port, &medium));
   1637 
   1638     if ( ((medium == SOC_PORT_MEDIUM_COPPER) && (!PHY_COPPER_MODE(unit, port)))
   1639          || (force_medium == SOC_PORT_MEDIUM_COPPER) ) {
   1640         /* Was fiber  or  being forced copper */ 
   1641         PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
   1642         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
   1643         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
   1644         PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE);
   1645 
   1646         SOC_IF_ERROR_RETURN
   1647             (_phy_bcm542xx_no_reset_setup(unit, port));
   1648         SOC_IF_ERROR_RETURN
   1649             (_phy_bcm542xx_serdes_update(unit, port));
   1650 
   1651         /* Do Not power up the interface if medium is disabled */
   1652         if ( pc->copper.enable) {
   1653             SOC_IF_ERROR_RETURN
   1654                 (_phy_bcm542xx_medium_config_update(unit, port, &pc->copper));
   1655         }
   1656         LOG_INFO(BSL_LS_SOC_PHY, (BSL_META_U(unit,
   1657                   "%s() u=%d p=%d [F->C] force_medium=%d\n"), __func__,
   1658                   unit, port, force_medium));
   1659 
   1660         /* Configure BCM542XX to RGMII-to-copper mode */
   1661         if ( IS_GMII_PORT(unit, port) && PHY_IS_BCM54210_220(pc) ) {
   1662             _phy_bcm542xx_rgmii_to_copper_mode(unit, port);
   1663         }
   1664 
   1665     } else
   1666     if ( ((medium == SOC_PORT_MEDIUM_FIBER) && (PHY_COPPER_MODE(unit, port)))
   1667          || (force_medium == SOC_PORT_MEDIUM_FIBER) ) {
   1668         /* Was copper  or  being forced fiber */ 
   1669         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
   1670         PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   1671         PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE);
   1672 
   1673         SOC_IF_ERROR_RETURN
   1674             (_phy_bcm542xx_no_reset_setup(unit, port));
   1675         SOC_IF_ERROR_RETURN
   1676             (_phy_bcm542xx_serdes_update(unit, port));
   1677 
   1678         if ( pc->fiber.enable ) {
   1679             SOC_IF_ERROR_RETURN
   1680                 (_phy_bcm542xx_medium_config_update(unit, port, &pc->fiber));
   1681         }
   1682         LOG_INFO(BSL_LS_SOC_PHY, (BSL_META_U(unit,
   1683               "%s() u=%d p=%d [C->F] force_medium=%d\n"), __func__,
   1684               unit, port, force_medium));
   1685        
   1686         /* Configure BCM542XX to RGMII-to-Fiber mode */
   1687         if ( IS_GMII_PORT(unit, port) && PHY_IS_BCM54210_220(pc) ) {
   1688             _phy_bcm542xx_rgmii_to_fiber_mode(unit, port);
   1689         } 
   1690     }
   1691 
   1692     return SOC_E_NONE;
   1693 }
   1694 
   1695 /***********************************************************************
   1696  *
   1697  * PHY542xx DRIVER ROUTINES
   1698  */
   1699 
   1700 /*
   1701  * Function:
   1702  *      phy_bcm542xx_medium_config_set
   1703  * Purpose:
   1704  *      Set the operating parameters that are automatically selected
   1705  *      when medium switches type.
   1706  * Parameters:
   1707  *      unit - StrataSwitch unit #
   1708  *      port - Port number
   1709  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
   1710  *      cfg - Operating parameters
   1711  * Returns:
   1712  *      SOC_E_XXX
   1713  */
   1714 STATIC int
   1715 phy_bcm542xx_medium_config_set(int unit, soc_port_t port, 
   1716                                soc_port_medium_t  medium,
   1717                                soc_phy_config_t  *cfg)
   1718 {
   1719     phy_ctrl_t        *pc;
   1720     soc_phy_config_t  *active_medium;  /* Currently active medium */
   1721     soc_phy_config_t  *change_medium;  /* Requested medium */
   1722     soc_phy_config_t  *other_medium;   /* The other medium */
   1723     soc_port_ability_t advert_ability;
   1724     int                medium_update;
   1725 
   1726     if ( NULL == cfg ) {
   1727         return SOC_E_PARAM;
   1728     }
   1729     pc            = EXT_PHY_SW_STATE(unit, port);
   1730     medium_update = FALSE;
   1731     /* clear the struct advert_ability */
   1732     sal_memset(&advert_ability, 0, sizeof(soc_port_ability_t));
   1733 
   1734     switch ( medium ) {
   1735     case  SOC_PORT_MEDIUM_COPPER:
   1736         if (!pc->automedium && !PHY_COPPER_MODE(unit, port) ) {
   1737             return SOC_E_UNAVAIL;
   1738         }
   1739         change_medium  = &pc->copper;
   1740         other_medium   = &pc->fiber;
   1741         ADVERT_ALL_COPPER(&advert_ability);
   1742 
   1743         break;
   1744     case  SOC_PORT_MEDIUM_FIBER:
   1745         if (!pc->automedium && !PHY_FIBER_MODE(unit, port) ) {
   1746             return SOC_E_UNAVAIL;
   1747         }
   1748         change_medium  = &pc->fiber;
   1749         other_medium   = &pc->copper;
   1750         ADVERT_ALL_FIBER(&advert_ability);
   1751         break;
   1752     default:
   1753         return SOC_E_PARAM;
   1754     }
   1755 
   1756     /* Changes take effect immediately if the                   *\
   1757     \* target medium is active or the preferred medium changes. */
   1758     if ( change_medium->enable != cfg->enable ) {
   1759         medium_update = TRUE;
   1760     }
   1761     if ( change_medium->preferred != cfg->preferred ) {
   1762         /* Make sure that only one medium is preferred */
   1763         other_medium->preferred = !cfg->preferred;
   1764         medium_update = TRUE;
   1765     }
   1766 
   1767     /* copy given cfg to change_medium and update advert_ability */
   1768     sal_memcpy(change_medium, cfg, sizeof(*change_medium));
   1769     change_medium->advert_ability.pause &= advert_ability.pause;
   1770     change_medium->advert_ability.speed_half_duplex &= advert_ability.speed_half_duplex;
   1771     change_medium->advert_ability.speed_full_duplex &= advert_ability.speed_full_duplex;
   1772     change_medium->advert_ability.interface &= advert_ability.interface;
   1773     change_medium->advert_ability.medium &= advert_ability.medium;
   1774     change_medium->advert_ability.loopback &= advert_ability.loopback;
   1775     change_medium->advert_ability.flags &= advert_ability.flags;
   1776 
   1777     SOC_IF_ERROR_RETURN( _phy_bcm542xx_serdes_update(unit, port) );
   1778 
   1779     if ( medium_update ) {
   1780         /* The new config may cause medium change. Check and update medium */
   1781         SOC_IF_ERROR_RETURN
   1782             (_phy_bcm542xx_medium_change(unit, port, medium));
   1783     } else {
   1784         active_medium = (PHY_COPPER_MODE(unit, port)) ? &pc->copper
   1785                                                       : &pc->fiber;
   1786         if ( active_medium == change_medium ) {
   1787             /* If the medium to update is active, update the configuration */
   1788             SOC_IF_ERROR_RETURN
   1789                 (_phy_bcm542xx_medium_config_update(unit, port, change_medium));
   1790         }
   1791         else {
   1792             /* Make sure that connected medium has been updated if port is disabled */
   1793             if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE) ) {
   1794                 /* Check for medium change and update HW/SW accordingly. */
   1795                 SOC_IF_ERROR_RETURN
   1796                     (_phy_bcm542xx_medium_change(unit, port, SOC_PORT_MEDIUM_NONE));
   1797             }
   1798         } 
   1799     }
   1800     return SOC_E_NONE;
   1801 }
   1802 
   1803 /*
   1804  * Function:
   1805  *      phy_bcm542xx_medium_config_get
   1806  * Purpose:
   1807  *      Get the operating parameters that are automatically selected
   1808  *      when medium switches type.
   1809  * Parameters:
   1810  *      unit - StrataSwitch unit #
   1811  *      port - Port number
   1812  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
   1813  *      cfg - (OUT) Operating parameters
   1814  * Returns:
   1815  *      SOC_E_XXX
   1816  */
   1817 
   1818 STATIC int
   1819 phy_bcm542xx_medium_config_get(int unit, soc_port_t port, 
   1820                                soc_port_medium_t medium,
   1821                                soc_phy_config_t *cfg)
   1822 {
   1823     int            rv;
   1824     phy_ctrl_t    *pc;
   1825 
   1826     pc = EXT_PHY_SW_STATE(unit, port);
   1827     rv = SOC_E_NONE;
   1828 
   1829     switch ( medium ) {
   1830     case SOC_PORT_MEDIUM_COPPER:
   1831         if ( pc->automedium || PHY_COPPER_MODE(unit, port) ) {
   1832             sal_memcpy(cfg, &pc->copper, sizeof (*cfg));
   1833         } else {
   1834             rv = SOC_E_UNAVAIL;
   1835         }
   1836         break;
   1837     case SOC_PORT_MEDIUM_FIBER:
   1838         if ( pc->automedium || PHY_FIBER_MODE(unit, port) ) {
   1839             sal_memcpy(cfg, &pc->fiber, sizeof (*cfg));
   1840         } else {
   1841             rv = SOC_E_UNAVAIL;
   1842         }
   1843         break;
   1844     default:
   1845         rv = SOC_E_PARAM;
   1846         break;
   1847     }
   1848 
   1849     return rv;
   1850 }
   1851 
   1852 /*
   1853  * Function:
   1854  *      _phy_bcm542xx_no_reset_setup
   1855  * Purpose:
   1856  *      Setup the operating parameters of the PHY without resetting PHY
   1857  * Parameters:
   1858  *      unit - StrataSwitch unit #
   1859  *      port - Port number
   1860  * Returns:
   1861  *      SOC_E_XXX
   1862  */
   1863 
   1864 STATIC int
   1865 _phy_bcm542xx_no_reset_setup(int unit, soc_port_t port)
   1866 {
   1867     phy_ctrl_t    *pc;
   1868     int rv = SOC_E_NONE;
   1869 
   1870     LOG_INFO(BSL_LS_SOC_PHY,
   1871              (BSL_META_U(unit, "%s: u=%d p=%d medium=%s\n"),
   1872               __func__, unit, port,
   1873               PHY_COPPER_MODE(unit, port) ? "COPPER" : "FIBER"));
   1874 
   1875     pc = EXT_PHY_SW_STATE(unit, port);
   1876     rv = phy_bcm542xx_init_setup(unit, port, 0, 
   1877                                      pc->automedium,
   1878                                      pc->fiber.preferred,
   1879                                      pc->fiber_detect,
   1880                                      pc->fiber.enable,
   1881                                      pc->copper.enable,
   1882                                      pc->ext_phy_autodetect_en,
   1883                                      pc->ext_phy_fiber_iface); 
   1884     if ( rv != SOC_E_NONE ) {
   1885         return SOC_E_FAIL;
   1886     }
   1887     return rv;
   1888 }
   1889 
   1890 /*
   1891  * Function:
   1892  *    phy_bcm542xx_set_led_selectors
   1893  * Purpose:
   1894  *    Set LED modes and Control.
   1895  * Parameters:
   1896  *    phy_dev_addr    - PHY's device address
   1897  *    led_mode0       - LED Mode 0
   1898  *    led_mode1       - LED Mode 1
   1899  *    led_mode2       - LED Mode 2
   1900  *    led_mode3       - LED Mode 3
   1901  *    led_select      - LED select 
   1902  *    led_select_ctrl        - LED Control
   1903  * Returns:
   1904  */
   1905 int
   1906 phy_bcm542xx_set_led_selectors(int unit, phy_ctrl_t *pc)
   1907 {
   1908     uint16 data;
   1909     uint16 led_link_speed_mode;
   1910 
   1911     /* Configure LED selectors */
   1912     data = (((pc->ledmode[1] & 0xf) << 4) | (pc->ledmode[0] & 0xf));
   1913     SOC_IF_ERROR_RETURN
   1914         (PHY_WRITE_BCM542XX_LED_SELECTOR_1r(unit, pc, data));
   1915 
   1916     data = ((pc->ledmode[3] & 0xf) << 4) | (pc->ledmode[2] & 0xf);
   1917     SOC_IF_ERROR_RETURN
   1918         (PHY_WRITE_BCM542XX_LED_SELECTOR_2r(unit, pc, data));
   1919 
   1920     data = (pc->ledctrl & 0x3ff);
   1921     SOC_IF_ERROR_RETURN
   1922         (PHY_WRITE_BCM542XX_LED_CTRLr(unit, pc, data));
   1923 
   1924     SOC_IF_ERROR_RETURN
   1925         (PHY_WRITE_BCM542XX_EXP_LED_SELECTORr(unit, pc, pc->ledselect));
   1926 
   1927     led_link_speed_mode = soc_property_port_get(unit, pc->port, 
   1928                               spn_PHY_LED_LINK_SPEED_MODE, 0x0);
   1929     switch(led_link_speed_mode) {
   1930         case 1:
   1931             SOC_IF_ERROR_RETURN
   1932                 (PHY_MODIFY_BCM542XX_SPARE_CTRLr(unit, pc,
   1933                      PHY_BCM542XX_SPARE_CTRL_REG_LINK_LED, 
   1934                      PHY_BCM542XX_SPARE_CTRL_REG_LINK_LED
   1935                      | PHY_BCM542XX_SPARE_CTRL_REG_LINK_SPEED_LED));
   1936             break;
   1937         case 2:
   1938             SOC_IF_ERROR_RETURN
   1939                 (PHY_MODIFY_BCM542XX_SPARE_CTRLr(unit, pc,
   1940                      PHY_BCM542XX_SPARE_CTRL_REG_LINK_SPEED_LED, 
   1941                      PHY_BCM542XX_SPARE_CTRL_REG_LINK_SPEED_LED
   1942                      | PHY_BCM542XX_SPARE_CTRL_REG_LINK_LED));
   1943             break;
   1944         default:
   1945             SOC_IF_ERROR_RETURN
   1946                 (PHY_MODIFY_BCM542XX_SPARE_CTRLr(unit, pc,
   1947                      0,
   1948                      PHY_BCM542XX_SPARE_CTRL_REG_LINK_LED  
   1949                      | PHY_BCM542XX_SPARE_CTRL_REG_LINK_SPEED_LED));
   1950             break;
   1951     }   
   1952 
   1953     return SOC_E_NONE;
   1954 }
   1955 
   1956 /*
   1957  * Function:
   1958  *    phy_bcm54280_init    ( for 54280 / 290 )
   1959  * Purpose:
   1960  *    54280 Device specific Initialization 
   1961  * Parameters:
   1962  *    unit, port          - 
   1963  * Notes: 
   1964  */
   1965 STATIC int
   1966 _phy_bcm54280_init(int unit, soc_port_t port)
   1967 {
   1968     phy_ctrl_t  *pc;
   1969 #ifdef INCLUDE_PLP_IMACSEC
   1970     int rv;
   1971     int uport;
   1972     unsigned int ms_dev_addr =
   1973            soc_property_port_get(unit, port, spn_MACSEC_DEV_ADDR, -1);
   1974 
   1975     unsigned int ms_slice    =
   1976            soc_property_port_get(unit, port, spn_MACSEC_PORT_INDEX, 0);
   1977 
   1978     int imacsec_mdio_addr;
   1979     bcm_plp_base_t_sec_phy_access_t *imacsec_des;
   1980 #endif
   1981 
   1982     pc = EXT_PHY_SW_STATE(unit, port);
   1983     pc->driver_data = (void *)(pc+1);
   1984 #ifdef INCLUDE_PLP_IMACSEC
   1985     /* Base PHY ID is used to access MACSEC core */
   1986     imacsec_mdio_addr = soc_property_port_get(unit, port,
   1987                                             spn_MACSEC_DEV_ADDR, -1);
   1988     pc->macsec_enable = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0);
   1989     imacsec_des = IMACSEC_DES_PTR_GET(pc);
   1990     imacsec_des->macsec_dev_addr = IMACSEC_MDIO_ADDR_GET(imacsec_mdio_addr);
   1991     imacsec_des->phy_info.lane_map = 
   1992                soc_property_port_get(unit, port, spn_MACSEC_PORT_INDEX, 0);
   1993     imacsec_des->phy_info.lane_map =  1 << imacsec_des->phy_info.lane_map ;
   1994 #endif
   1995     /*
   1996      * Configure LED mode and Jumbo frame, set max Jumbo packet length to 18KB
   1997      */
   1998 
   1999     /*
   2000      * PHY Extended Control Reg., RDB.0x000, Legacy Reg.0x10
   2001      * bit[0] GMII_FIFO_JUMBO_LSB
   2002      * bit[5] LED_TRAFFIC_EN, Enable LED traffic mode
   2003      */
   2004     SOC_IF_ERROR_RETURN
   2005         (PHY_MODIFY_BCM542XX_MII_ECRr(unit, pc,
   2006                             PHY_BCM542XX_MII_ECR_FIFO_ELAST_0
   2007                           | PHY_BCM542XX_MII_ECR_EN_LEDT,
   2008                             PHY_BCM542XX_MII_ECR_FIFO_ELAST_0
   2009                           | PHY_BCM542XX_MII_ECR_EN_LEDT));
   2010 
   2011     /*
   2012      * Pattern Generator Status Reg., RDB.0x006, Legacy EXP_Reg.0x46
   2013      * bit[14] GMII_FIFO_JUMBO_MSB
   2014      * bit[15] GMII_FIFO_JUMBO_MSB
   2015      */
   2016     SOC_IF_ERROR_RETURN
   2017         (PHY_MODIFY_BCM542XX_EXP_PATT_GEN_STATr(unit, pc,
   2018                             PHY_BCM542XX_PATT_GEN_STAT_FIFO_ELAST_1
   2019                           | PHY_BCM542XX_PATT_GEN_STAT_GMII_FIFO_JUMBO_MSB,
   2020                             PHY_BCM542XX_PATT_GEN_STAT_FIFO_ELAST_1
   2021                           | PHY_BCM542XX_PATT_GEN_STAT_GMII_FIFO_JUMBO_MSB));
   2022 
   2023     /* Disable USGMII mode. Clear RDB.0x0810 Bit[6]  */ 
   2024     if (PHY_IS_BCM54182(pc) || PHY_IS_BCM54185(pc) ||
   2025         PHY_IS_BCM54192(pc) || PHY_IS_BCM54195(pc) ) {   
   2026         SOC_IF_ERROR_RETURN(
   2027             phy_bcm542xx_rdb_reg_modify(unit, pc,
   2028                         PHY_BCM542XX_DISABLE_USGMII,
   2029                         0, PHY_BCM542XX_DISABLE_USGMII_6U_BIT_SEL) );
   2030     }
   2031 
   2032     /*
   2033      * Misc 1000-X Control 2 Reg., RDB.0x236, Legacy Reg.0x1C shadow 0x16
   2034      * bit[0] PRIMARY_SERDES_JUMBO_MSB
   2035      */
   2036     SOC_IF_ERROR_RETURN
   2037         (PHY_MODIFY_BCM542XX_1ST_SERDES_CTRLr(unit, pc,
   2038                             PHY_BCM542XX_SERDES_CTRL_JUMBO_MSB,
   2039                             PHY_BCM542XX_SERDES_CTRL_JUMBO_MSB));
   2040 
   2041     /*
   2042      * Auto Detect SGMII MC Reg., RDB.0x238
   2043      * bit[2] GMII_FIFO_JUMBO_LSB
   2044      */
   2045     SOC_IF_ERROR_RETURN
   2046         (phy_bcm542xx_direct_reg_modify(unit, pc,
   2047                             PHY_BCM542XX_AUTO_DETECT_SGMII_MC_REG_OFFSET,
   2048                             PHY_BCM542XX_AUTO_DETECT_GMII_FIFO_JUMBO_LSB,
   2049                             PHY_BCM542XX_AUTO_DETECT_GMII_FIFO_JUMBO_LSB));
   2050  
   2051     /*
   2052      * Auxiliary 1000-X Contro Reg., RDB.0x23B, Legacy Reg.0x1C shadow 0x1B
   2053      * bit[1] PRIMARY_SERDES_JUMBO_LSB
   2054      */
   2055     SOC_IF_ERROR_RETURN
   2056         (PHY_MODIFY_BCM542XX_AUX_1000X_CTRLr(unit, pc,
   2057                             PHY_BCM542XX_SERDES_CTRL_JUMBO_LSB,
   2058                             PHY_BCM542XX_SERDES_CTRL_JUMBO_LSB));
   2059 
   2060     /*
   2061      * Secondary Serdes MISC 1000-X Control 2 Reg. RDB.0xB16
   2062      * bit[0] SECONDARY_SERDES_JUMBO_MSB
   2063      */
   2064     SOC_IF_ERROR_RETURN
   2065         (phy_bcm542xx_direct_reg_modify(unit, pc,
   2066                             PHY_BCM542XX_2ND_SERDES_MISC_1000x_CTL_2_REG_OFFSET,
   2067                             PHY_BCM542XX_2ND_SERDES_MISC_1000x_CTL_2_2ND_SERDES_MSB,
   2068                             PHY_BCM542XX_2ND_SERDES_MISC_1000x_CTL_2_2ND_SERDES_MSB));
   2069 
   2070     /*
   2071      * Secondary Serdes Auxiliary 1000-X Control Reg. RDB.0xB1B
   2072      * bit[1] SECONDARY_SERDES_JUMBO_LSB
   2073      */
   2074     SOC_IF_ERROR_RETURN
   2075         (phy_bcm542xx_direct_reg_modify(unit, pc,
   2076                             PHY_BCM542XX_2ND_SERDES_AUX_1000x_CTL_REG_OFFSET,
   2077                             PHY_BCM542XX_2ND_SERDES_AUX_1000x_CTL_2ND_SERDES_LSB,
   2078                             PHY_BCM542XX_2ND_SERDES_AUX_1000x_CTL_2ND_SERDES_LSB));
   2079 
   2080     /*
   2081      * Copper Auxiliary Control Reg., RDB.0x028, Legacy Reg.0x18 shadow 0
   2082      * bit[14] EXT_PKT_LEN(100BT_JUMBO), 100BASE-Tx jumbo frames support
   2083      */
   2084     SOC_IF_ERROR_RETURN
   2085         (PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc,
   2086                             PHY_BCM542XX_MII_AUX_CTRL_REG_EXT_PKT_LEN,
   2087                             PHY_BCM542XX_MII_AUX_CTRL_REG_EXT_PKT_LEN));
   2088 
   2089     /*
   2090      * Secondary Serdes 1000-X Error Counter Setting Reg. RDB.0xB10
   2091      * bit[0] EXT_PKT_LEN
   2092      */
   2093     SOC_IF_ERROR_RETURN
   2094         (phy_bcm542xx_direct_reg_modify(unit, pc,
   2095                             PHY_BCM542XX_2ND_SERDES_1000x_ERR_CNT_SET_REG_OFFSET,
   2096                             PHY_BCM542XX_2ND_SERDES_1000x_ERR_CNT_SET_EXT_PKT_LEN,
   2097                             PHY_BCM542XX_2ND_SERDES_1000x_ERR_CNT_SET_EXT_PKT_LEN));
   2098 
   2099 
   2100 #if defined (INCLUDE_PLP_IMACSEC)  /*  */
   2101     if(pc->macsec_enable){
   2102 		/*  MACSEC  is ENABLED 
   2103         *  MACSEC  Specific Initialization
   2104         *
   2105         * Some reasonable defaults
   2106         */
   2107          /* default MACSEC MAC policy: MACSEC_SWITCH_FOLLOWS_LINE == 1 */
   2108         pc->macsec_mac_policy = soc_property_port_get(unit, port,
   2109                                               spn_MACSEC_SWITCH_SIDE_POLICY,
   2110                                               1);
   2111 
   2112         pc->macsec_switch_fixed_speed  = 0;
   2113         /* If switch mac policy is PHY_MAC_SWITCH_DUPLEX_GATEWAY set the 
   2114          * duplex mode on line side as half duplex and system side as full duplex */
   2115             
   2116         pc->macsec_switch_fixed_duplex = 1;
   2117         pc->macsec_switch_fixed_pause  = 1;
   2118         pc->macsec_pause_rx_fwd = 0;
   2119         pc->macsec_pause_tx_fwd = 0;
   2120         pc->macsec_line_ipg     = 0xc;
   2121         pc->macsec_switch_ipg   = 0xc;
   2122 
   2123 
   2124         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   2125 
   2126         /* DATAPATH_SELECT  :
   2127          * [15:8] 0 means port NOT bypassed  , [7:0] 0 means 1588 not encrypted
   2128          */
   2129         SOC_IF_ERROR_RETURN
   2130             (phy_bcm542xx_direct_reg_modify(unit, pc, 0x84a, 0x0000,
   2131                                             1 << (ms_slice + 8) | 0xff ));
   2132 
   2133         /* MACSEC_PWRDN  :
   2134          * [15]    1 means MACSEC MDIO enabled
   2135          * [14:10] 0  reset value for QUAD1 PHY addr
   2136          * [9:8] 0 means quad1,quad0 power up
   2137          * [7:0] 0 means port power up
   2138          */
   2139         SOC_IF_ERROR_RETURN
   2140             (phy_bcm542xx_direct_reg_modify(unit, pc, 0x84b, 0x8000,
   2141                                            0xff00 | 1 << (ms_slice ) ));
   2142        /* MACSEC_OVERRIDE enable
   2143         * [14] 1 means 1: overwrite with bit 13
   2144         * bit 13, 0: macsec not disabled
   2145        */
   2146 
   2147         SOC_IF_ERROR_RETURN
   2148             (phy_bcm542xx_direct_reg_modify(unit, pc, 0x84d, 0x40ff,
   2149                                            0xffff ));
   2150 
   2151         /* Switch side speed  config2 reg */
   2152         /* bit 0 to 7 value = 0 means use line side , 1 means use config3 reg */
   2153         SOC_IF_ERROR_RETURN
   2154             (phy_bcm542xx_cl45_reg_write(unit, pc,  0x7, 0x9870, 0xFF));
   2155 
   2156         /* Switch side speed  config3 reg */
   2157         SOC_IF_ERROR_RETURN
   2158             (phy_bcm542xx_cl45_reg_write(unit, pc,  0x7, 0x9871, 0xAAAA));
   2159 
   2160 
   2161         /* Restore the phy mdio address */
   2162         pc->phy_id =  PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   2163 
   2164 
   2165 
   2166         /* register mdio read/write */
   2167         _bcm_plp_register_mdio_primitives(
   2168                 unit, ms_slice, ms_dev_addr, pc->read , pc->write);
   2169 
   2170 
   2171         /* Attach MAC driver */
   2172         rv = _bcm_phy5419x_phy_mac_driver_attach( pc, 
   2173                                                   ms_dev_addr,
   2174                                                   pc->port,
   2175                                                   imacsec_blmi_io_mmi2);
   2176         if(rv != SOC_E_NONE) {
   2177              LOG_WARN(BSL_LS_SOC_PHY,
   2178                  (BSL_META_U(unit,
   2179                      "phy_mac_driver_attach "
   2180                      "returned error for u=%d p=%d\n"), unit, port));
   2181                     return SOC_E_FAIL;
   2182         }
   2183 
   2184 
   2185         /* Initialize the Line side MAC */
   2186         uport = PHY_UNIMAC_V2_LINE_PORT(pc->port);
   2187         SOC_IF_ERROR_RETURN(
   2188             BMACSEC_MAC_INIT((phy_mac_ctrl_t *)imacsec_des->unimac, uport));
   2189 
   2190         /* Initialize the Switch side MAC */
   2191         uport = PHY_UNIMAC_V2_SWITCH_PORT(pc->port);
   2192         SOC_IF_ERROR_RETURN(
   2193             BMACSEC_MAC_INIT((phy_mac_ctrl_t *)imacsec_des->unimac, uport));
   2194     }
   2195 #endif  /* INCLUDE_PLP_IMACSEC  */
   2196 
   2197     return SOC_E_NONE;
   2198 }
   2199 
   2200 /*
   2201  * Function:
   2202  *    phy_bcm54282_init    ( for 54282 / 292 )
   2203  * Purpose:
   2204  *    Initalize the PHY device. 
   2205  * Parameters:
   2206  *    unit, port          - 
   2207  * Notes: 
   2208  */
   2209 STATIC int
   2210 _phy_bcm54282_init(int unit, soc_port_t port) 
   2211 {
   2212     phy_ctrl_t  *pc;
   2213     pc = EXT_PHY_SW_STATE(unit, port);
   2214 
   2215     /* 
   2216     * Configure extended control register for led mode and 
   2217     * jumbo frame support
   2218     */
   2219     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); /* RV */
   2220 
   2221     /* Enable QSGMII MDIO sharing feature 
   2222        - Enable access to QSGMII reg space using port3's MDIO address
   2223        - Use PHYA[4:0]+3 (Port3's MDIO) instead of PHYA[4:0)+8 as MDIO address.
   2224        - It saves one MDIO address for customer.
   2225        - Access to this top level register via port 0 only
   2226      */
   2227     SOC_IF_ERROR_RETURN
   2228         (phy_bcm542xx_direct_reg_modify(unit, pc,
   2229                             PHY_BCM542XX_TOP_MISC_TOP_CFG_REG_OFFSET,
   2230                             PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_SEL
   2231                           | PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_PHYA,
   2232                             PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_SEL
   2233                           | PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_PHYA));
   2234     
   2235     /* replace it with qsgmii phy id */
   2236     pc->phy_id = PHY_BCM54282_QSGMII_DEV_ADDR_SHARED(pc);    
   2237     
   2238     /* QSGMII FIFO Elasticity */
   2239     SOC_IF_ERROR_RETURN
   2240         (phy_bcm542xx_qsgmii_reg_write(unit, pc,
   2241                             (int) PHY_BCM542XX_DEV_PHY_SLICE(pc) /*dev_port*/,
   2242                             0x8300, 0x12, 0x0006));
   2243     
   2244     /* Restore access to Copper/Fiber register space.
   2245      *  TOP lvl register, access through port0 only
   2246      */
   2247     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   2248     SOC_IF_ERROR_RETURN
   2249         (phy_bcm542xx_direct_reg_modify(unit, pc,
   2250                             PHY_BCM542XX_TOP_MISC_TOP_CFG_REG_OFFSET,
   2251                             0,
   2252                             PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_SEL
   2253                           | PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_PHYA));
   2254     /* Restore the phy mdio address */
   2255     pc->phy_id =  PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 
   2256 
   2257     /* Configure LED mode and turn on jumbo frame support */
   2258     _phy_bcm54280_init(unit, port);
   2259 
   2260     /* In case of QSGMII devices, there is a LPI pass through mode
   2261        which has to be enabled for native EEE to work. In case of VNG, 
   2262        it is already set by default. To enable it: 
   2263     SOC_IF_ERROR_RETURN
   2264        (phy_bcm542xx_qsgmii_reg_write(PHY_BCM54282_QSGMII_DEV_ADDR(_pc), 
   2265                                       (int)PHY_BCM542XX_DEV_PHY_SLICE(pc),
   2266                                       0x833e, 0x0e, 0xc000));
   2267     */
   2268     return SOC_E_NONE;
   2269 }
   2270 
   2271 int
   2272 _phy_bcm542xx_rgmii_to_copper_mode(int unit, soc_port_t port)
   2273 {
   2274     phy_ctrl_t    *pc;
   2275     pc = EXT_PHY_SW_STATE(unit, port);
   2276 
   2277     /* Configure BCM542XX to RGMII-to-copper mode */
   2278     SOC_IF_ERROR_RETURN
   2279             (PHY_WRITE_BCM542XX_MII_MISC_CTRLr(unit, pc, 0x71E7));
   2280     SOC_IF_ERROR_RETURN
   2281             (PHY_WRITE_BCM542XX_CLK_ALIGN_CTRLr(unit, pc, 0x0E00));
   2282     SOC_IF_ERROR_RETURN
   2283             (PHY_WRITE_BCM542XX_TOP_LVL_CONFGr(unit, pc, 0x00B0));
   2284     SOC_IF_ERROR_RETURN
   2285             (PHY_WRITE_BCM542XX_MODE_CTRLr(unit, pc, 0x7C01));
   2286     SOC_IF_ERROR_RETURN
   2287             (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 0x1940));
   2288     SOC_IF_ERROR_RETURN
   2289             (PHY_WRITE_BCM542XX_MODE_CTRLr(unit, pc, 0x7C00));
   2290     SOC_IF_ERROR_RETURN
   2291             (PHY_WRITE_BCM542XX_MII_GB_CTRLr(unit, pc, 0x0200));
   2292     SOC_IF_ERROR_RETURN
   2293             (PHY_WRITE_BCM542XX_1000X_MII_ANAr(unit, pc, 0x01E1));
   2294     SOC_IF_ERROR_RETURN
   2295             (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 0x1340));
   2296 
   2297     return SOC_E_NONE;
   2298 }
   2299 
   2300 int
   2301 _phy_bcm542xx_rgmii_to_fiber_mode(int unit, soc_port_t port)
   2302 {
   2303     phy_ctrl_t    *pc;
   2304     pc = EXT_PHY_SW_STATE(unit, port);
   2305 
   2306     /* Configure BCM542XX to RGMII-to-Fiber mode */
   2307     SOC_IF_ERROR_RETURN
   2308             (PHY_WRITE_BCM542XX_MII_MISC_CTRLr(unit, pc, 0x71E7));
   2309     SOC_IF_ERROR_RETURN
   2310             (PHY_WRITE_BCM542XX_CLK_ALIGN_CTRLr(unit, pc, 0x0E00));
   2311     SOC_IF_ERROR_RETURN
   2312             (PHY_WRITE_BCM542XX_TOP_LVL_CONFGr(unit, pc, 0x00B0));
   2313     SOC_IF_ERROR_RETURN
   2314             (PHY_WRITE_BCM542XX_MODE_CTRLr(unit, pc, 0x7C02));
   2315     SOC_IF_ERROR_RETURN
   2316             (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 0x1940));
   2317      SOC_IF_ERROR_RETURN
   2318             (PHY_WRITE_BCM542XX_MODE_CTRLr(unit, pc, 0x7C03));
   2319     SOC_IF_ERROR_RETURN
   2320             (PHY_WRITE_BCM542XX_AUTO_DETECT_MEDIUMr(unit, pc, 0x78E2));
   2321     SOC_IF_ERROR_RETURN
   2322             (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 0x1140));
   2323 
   2324     return SOC_E_NONE;
   2325 }
   2326 
   2327 
   2328 /*
   2329  * Function:
   2330  *    phy_bcm54200_init    ( for 54210/220/240/285/294/295/296/140 )  dual media
   2331  * Purpose:
   2332  *    Initalize the dual media (combo) PHY device.
   2333  * Parameters:
   2334  *    automedium            - Automedium select in combo ports
   2335  *    fiber_preferred       - Fiber preferrence over copper
   2336  *    fiber_detect          - Fiber Signal Detect
   2337  *    ext_phy_autodetect_en - Enable/Disable SGMII Slave Autodetect function
   2338  *    ext_phy_fiber_iface   - Fiber interface when Autodetect is disabled.
   2339  * Notes: 
   2340  * Fiber Detect  Detect Fiber signal 
   2341  *  Automedium     Fiber Preferred       Active Medium
   2342  * ------------  ------------------- -----------------------------------------
   2343  *     0                 1            Fiber  mode is forced
   2344  *     0                 0            Copper mode is forced
   2345  *     1                 1            Auto medium is enabled,  Fiber preferred
   2346  *     1                 0            Auto medium is enabled, Copper preferred
   2347  */
   2348 STATIC int
   2349 _phy_bcm54200_init(int unit, soc_port_t port, int automedium,
   2350                    int fiber_preferred, int fiber_detect,
   2351                    int fiber_enable   , int copper_enable,
   2352                    int ext_phy_autodetect_en, int ext_phy_fiber_iface)
   2353 {
   2354     uint16         data, mask;
   2355     phy_ctrl_t    *pc;
   2356     /*
   2357      * Don't power up the PHY if PHY is administratively disabled.
   2358      */
   2359     uint16 pwr_down_bit = PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE) ? PHY_BCM542XX_MII_CTRL_PWR_DOWN : 0;
   2360 
   2361     pc = EXT_PHY_SW_STATE(unit, port);
   2362 
   2363     /* Configure Auto-detect Medium (0x1c shadow 11110, RDB.0x23e) */
   2364     mask = PHY_BCM542XX_MII_AUTO_DET_MASK;    /* Auto-detect bit mask */
   2365     data = 0x0;
   2366     if ( PHY_IS_BCM54210_220(pc) ) {
   2367         /* Enable dual serdes auto-detect medium */  /* 0xfae7 */
   2368         data |= (PHY_BCM542XX_MII_AUTO_DET_MED_2ND_SERDES |
   2369                  PHY_BCM542XX_MII_FIBER_IN_USE_LED        |
   2370                  PHY_BCM542XX_MII_FIBER_LED               |
   2371                  PHY_BCM542XX_MII_FIBER_SD_SYNC);
   2372     }
   2373     if ( automedium ) {
   2374         /* Enable auto-detect medium */
   2375         data |= PHY_BCM542XX_MII_AUTO_DET_MED_EN;
   2376     }
   2377 
   2378     /* When no link partner exists, fiber should be default medium */
   2379     /* When both link partners exipc, fiber should be prefered medium
   2380      * for the following reasons.
   2381      * 1. Most fiber module generates signal detect when the fiber cable is
   2382      *    plugged in regardless of any activity even if the link partner is
   2383      *    powered down.
   2384      * 2. Fiber mode consume much lesser power than copper mode.
   2385      */
   2386     if ( fiber_preferred ) {
   2387                  /* Fiber selected when both media are active */
   2388         data |= (PHY_BCM542XX_MII_AUTO_DET_MED_PRI |
   2389                  PHY_BCM542XX_MII_AUTO_DET_MED_DEFAULT);
   2390                  /* Fiber selected when no medium is active */
   2391     }
   2392 
   2393     /* Qulalify fiber link with SYNC from PCS. */
   2394     data |= PHY_BCM542XX_MII_FIBER_SD_SYNC;
   2395     
   2396     /*
   2397      * Enable internal inversion of LED2/SD input pin.  Used only if
   2398      * the fiber module provides RX_LOS instead of Signal Detect.
   2399      */
   2400     if ( fiber_detect < 0 ) {
   2401         /* Fiber signal detect is active low from pin */
   2402         data |= PHY_BCM542XX_MII_INV_FIBER_SD;
   2403     }
   2404     
   2405     /* Auto-Detect Medium Register (DIGX_SHD1C_1E, RDB.0x23e) */
   2406     /* coverity[copy_paste_error : FALSE] */
   2407     SOC_IF_ERROR_RETURN
   2408         (PHY_MODIFY_BCM542XX_AUTO_DETECT_MEDIUMr(unit, pc, data, mask));
   2409 
   2410     if ( PHY_IS_BCM54210_220(pc) ) {
   2411         /* Power up primary SerDes, Fiber MII_CONTROL Reg. bit[11]*/
   2412         SOC_IF_ERROR_RETURN
   2413                 (PHY_MODIFY_BCM542XX_PRI_SERDES_MII_CTRLr(unit, pc, 0,
   2414                                       PHY_BCM542XX_MII_CTRL_PWR_DOWN));
   2415         data = PHY_BCM542XX_MODE_SEL_SGMII_2_COPPER;
   2416     } else {
   2417         data = PHY_BCM542XX_MODE_SEL_COPPER_2_SGMII;
   2418     }
   2419     /* MODE_CONTROL register,  DIGX_SHD_1C_1F, RDB_0x21 */
   2420     SOC_IF_ERROR_RETURN
   2421         (PHY_MODIFY_BCM542XX_MODE_CTRLr(unit, pc, data,
   2422                                       PHY_BCM542XX_MODE_CNTL_MODE_SEL_MASK));
   2423 
   2424     /*----------- COPPER INTERFACE ---------- */
   2425     if ( (! copper_enable) || (!automedium && fiber_preferred) ) {
   2426         SOC_IF_ERROR_RETURN
   2427             (PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc,
   2428                                       PHY_BCM542XX_MII_CTRL_PWR_DOWN,
   2429                                       PHY_BCM542XX_MII_CTRL_PWR_DOWN));
   2430     } else {
   2431         if (!pwr_down_bit) {
   2432         SOC_IF_ERROR_RETURN
   2433             (PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc,
   2434                                       0,
   2435                                       PHY_BCM542XX_MII_CTRL_PWR_DOWN));
   2436         }
   2437         SOC_IF_ERROR_RETURN
   2438             (PHY_WRITE_BCM542XX_MII_GB_CTRLr(unit, pc,
   2439                                       PHY_BCM542XX_MII_GB_CTRL_ADV_1000FD
   2440                                     | PHY_BCM542XX_MII_GB_CTRL_PT));
   2441         SOC_IF_ERROR_RETURN
   2442             (PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc,
   2443                                       PHY_BCM542XX_MII_CTRL_FD
   2444                                     | PHY_BCM542XX_MII_CTRL_SS_10
   2445                                     | PHY_BCM542XX_MII_CTRL_SS_100
   2446                                     | PHY_BCM542XX_MII_CTRL_AN_EN
   2447                                     | pwr_down_bit
   2448                                     | PHY_BCM542XX_MII_CTRL_RST_AN));
   2449 
   2450         /* Enable/disable auto-detection between SGMII-slave and 1000BASE-X */
   2451         if ( PHY_IS_BCM54210_220(pc) ) {
   2452             /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */
   2453             SOC_IF_ERROR_RETURN
   2454                     (PHY_MODIFY_BCM542XX_EXT_SERDES_CTRLr(unit, pc, 0x0,
   2455                                       PHY_BCM542XX_EXT_SERDES_FX_MASK));
   2456             /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */
   2457             SOC_IF_ERROR_RETURN
   2458                     (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 0,
   2459                                       PHY_BCM542XX_SGMII_SLAVE_AUTO));
   2460         } else {  /* PHY is 54240/28x/29x */
   2461             /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */
   2462             SOC_IF_ERROR_RETURN
   2463                     (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc,
   2464                                       PHY_BCM542XX_SGMII_SLAVE_AUTO,
   2465                                       PHY_BCM542XX_SGMII_SLAVE_AUTO));
   2466             SOC_IF_ERROR_RETURN        /* Power down SerDes */
   2467                     (PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc,
   2468                                       PHY_BCM542XX_MII_CTRL_PWR_DOWN,
   2469                                       PHY_BCM542XX_MII_CTRL_PWR_DOWN));
   2470         }
   2471 
   2472         /* Configure BCM542XX to RGMII-to-copper mode */
   2473         if ( IS_GMII_PORT(unit, port) && PHY_IS_BCM54210_220(pc) ) {
   2474             _phy_bcm542xx_rgmii_to_copper_mode(unit, port);
   2475         }
   2476     }
   2477 
   2478     /*----------- FIBER INTERFACE ---------- */
   2479     if ( fiber_enable && (automedium || fiber_preferred) ) {
   2480         /* remove power down of SerDes */
   2481         if (!pwr_down_bit) {
   2482         SOC_IF_ERROR_RETURN
   2483             (PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, 0,
   2484                                       PHY_BCM542XX_MII_CTRL_PWR_DOWN));
   2485         }
   2486         /* set the advertisement of serdes */
   2487         data = PHY_BCM542XX_1000X_MII_ANA_FD    |
   2488                PHY_BCM542XX_1000X_MII_ANA_HD    |
   2489                PHY_BCM542XX_1000X_MII_ANA_PAUSE |
   2490                PHY_BCM542XX_1000X_MII_ANA_ASYM_PAUSE;
   2491         /*Advertising Next Page capability in 1000X AN mode*/
   2492         if (fiber_preferred && pc->fiber.autoneg_enable &&
   2493             (ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS) &&
   2494             (ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_1000X)) {
   2495             data |= PHY_BCM542XX_1000X_MII_ANA_NP;
   2496         }
   2497 
   2498         mask = data;
   2499         SOC_IF_ERROR_RETURN
   2500             (PHY_MODIFY_BCM542XX_1000X_MII_ANAr(unit, pc, data, mask));
   2501 
   2502         /* Enable auto-detection between SGMII-slave and 1000BASE-X */
   2503         if ( PHY_IS_BCM54210_220(pc) ) {
   2504             data = PHY_BCM542XX_EXT_SERDES_LED | PHY_BCM542XX_EXT_SEL_SYNC_ST |
   2505                    PHY_BCM542XX_EXT_SELECT_SD  | PHY_BCM542XX_EXT_SERDES_SEL;
   2506             if ( fiber_preferred ) {
   2507                 data |= 0;  /* don't support PHY_BCM542XX_EXT_SERDES_AUTO_FX */
   2508             }
   2509             /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */
   2510             SOC_IF_ERROR_RETURN                              /* 0xd1cf */
   2511                     (PHY_WRITE_BCM542XX_EXT_SERDES_CTRLr(unit, pc, data));
   2512 
   2513             /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */
   2514             SOC_IF_ERROR_RETURN
   2515                 (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 0,
   2516                                       PHY_BCM542XX_SGMII_SLAVE_AUTO));
   2517             /* Miscellanous Control Reg., CORE_SHD18_111, RDB_0x02f */
   2518             SOC_IF_ERROR_RETURN
   2519                 (PHY_WRITE_BCM542XX_MII_MISC_CTRLr(unit, pc,
   2520                                       PHY_BCM542XX_MII_MISC_CTRL_CLEARALL));
   2521             /* Second SERDES 100-FX CONTROL Register, RDB_0xb17 */
   2522             SOC_IF_ERROR_RETURN
   2523                 (phy_bcm542xx_direct_reg_write(unit, pc,
   2524                             PHY_BCM542XX_2ND_SERDES_MISC_1000x_REG_OFFSET,
   2525                             PHY_BCM542XX_2ND_SERDES_MISC_1000x_INIT));
   2526 
   2527         } else {  /* PHY is 54240/28x/29x */
   2528             if (fiber_preferred && (ext_phy_autodetect_en == EXT_PHY_AUTODETECT_EN)) {
   2529                 /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */
   2530                 SOC_IF_ERROR_RETURN
   2531                         (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc,
   2532                                           PHY_BCM542XX_SGMII_SLAVE_AUTO,
   2533                                           PHY_BCM542XX_SGMII_SLAVE_AUTO));
   2534             } else if(fiber_preferred && (ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS)) {
   2535                 /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */
   2536                 SOC_IF_ERROR_RETURN
   2537                         (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 0,
   2538                                           PHY_BCM542XX_SGMII_SLAVE_AUTO));
   2539             } else {
   2540                 /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */
   2541                 SOC_IF_ERROR_RETURN
   2542                         (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc,
   2543                                           PHY_BCM542XX_SGMII_SLAVE_AUTO,
   2544                                           PHY_BCM542XX_SGMII_SLAVE_AUTO));
   2545             }
   2546             /* MODE_CONTROL register, DIGX_SHD_1C_1F, RDB_0x21 */
   2547             SOC_IF_ERROR_RETURN
   2548                 (PHY_MODIFY_BCM542XX_MODE_CTRLr(unit, pc,
   2549                                       PHY_BCM542XX_MODE_SEL_FIBER_2_SGMII,
   2550                                       PHY_BCM542XX_MODE_CNTL_MODE_SEL_MASK));
   2551         }
   2552         if (fiber_preferred && (ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS)
   2553             && (ext_phy_fiber_iface >= EXT_PHY_FIBER_IFACE_1000X)) {
   2554 
   2555             if (ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_1000X) { /*1000x Fiber more*/
   2556                 /* Enable 1000X mode. MODE_CONTROL register,  DIGX_SHD_1C_1F, RDB_0x21 */
   2557                 SOC_IF_ERROR_RETURN
   2558                     (PHY_MODIFY_BCM542XX_MODE_CTRLr(unit, pc, PHY_BCM542XX_MODE_CNTL_1000X_EN,
   2559                                       PHY_BCM542XX_MODE_CNTL_1000X_EN));
   2560 
   2561                 if (pc->fiber.autoneg_enable) {
   2562                     /*
   2563                      * Misc 1000-X Control 2 Reg., RDB.0x236, Legacy Reg.0x1C shadow 0x16
   2564                      * bit[0] SERDES_AUTONEG_PARALLEL_DETECT_EN
   2565                      */
   2566                     SOC_IF_ERROR_RETURN
   2567                         (PHY_MODIFY_BCM542XX_1ST_SERDES_CTRLr(unit, pc,
   2568                             PHY_BCM542XX_SERDES_CTRL_AN_PD_EN,
   2569                             PHY_BCM542XX_SERDES_CTRL_AN_PD_EN));
   2570 
   2571                     /* Default SerDes config & restart autonegotiation */
   2572                     SOC_IF_ERROR_RETURN
   2573                         (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc,
   2574                                       PHY_BCM542XX_MII_CTRL_FD
   2575                                     | PHY_BCM542XX_MII_CTRL_SS_1000
   2576                                     | PHY_BCM542XX_MII_CTRL_AN_EN
   2577                                     | pwr_down_bit
   2578                                     | PHY_BCM542XX_MII_CTRL_RST_AN));
   2579                  } else {
   2580                     SOC_IF_ERROR_RETURN
   2581                         (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc,
   2582                                       PHY_BCM542XX_MII_CTRL_FD
   2583                                     | PHY_BCM542XX_MII_CTRL_SS_1000));
   2584                  }
   2585             } else if (ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_100FX) {
   2586                 if (! PHY_IS_BCM54210_220(pc) ) {
   2587                     PHY_FLAGS_SET(unit, port, PHY_FLAGS_100FX);
   2588                     /* Enable 100BASE-FX mode*/
   2589                     /* SERDES 100BASE-FX Control Reg., DIGX_SHD_1C_13, RDB_0x233 */
   2590                     SOC_IF_ERROR_RETURN(
   2591                         phy_bcm542xx_direct_reg_modify(unit, pc,
   2592                                  PHY_BCM542XX_100FX_CTRL_REG_OFFSET,
   2593                                  PHY_BCM542XX_100FX_CTRL_REG_FX_SERDES_EN,
   2594                                  PHY_BCM542XX_100FX_CTRL_REG_FX_SERDES_EN) );
   2595                 }
   2596             } else if (ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_SGMII) {
   2597                 if (! PHY_IS_BCM54210_220(pc) ) {
   2598                     /* Enable SGMII Slave mode. SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */
   2599                     SOC_IF_ERROR_RETURN
   2600                         (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, PHY_BCM542XX_SGMII_SLAVE_EN,
   2601                                           PHY_BCM542XX_SGMII_SLAVE_EN));
   2602                 }
   2603             } else {
   2604                 /*
   2605                  * Incorrect fiber interface setting provided, applying
   2606                  * Default SerDes config & restart autonegotiation
   2607                  */
   2608                  SOC_IF_ERROR_RETURN
   2609                     (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc,
   2610                                       PHY_BCM542XX_MII_CTRL_FD
   2611                                     | PHY_BCM542XX_MII_CTRL_SS_1000
   2612                                     | PHY_BCM542XX_MII_CTRL_AN_EN
   2613                                     | pwr_down_bit
   2614                                     | PHY_BCM542XX_MII_CTRL_RST_AN));
   2615             }
   2616         } else {
   2617             /* Default SerDes config & restart autonegotiation */
   2618             SOC_IF_ERROR_RETURN
   2619                 (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc,
   2620                                       PHY_BCM542XX_MII_CTRL_FD
   2621                                     | PHY_BCM542XX_MII_CTRL_SS_1000
   2622                                     | PHY_BCM542XX_MII_CTRL_AN_EN
   2623                                     | pwr_down_bit
   2624                                     | PHY_BCM542XX_MII_CTRL_RST_AN));
   2625         }
   2626         /* Configure BCM542XX to RGMII-to-Fiber mode */
   2627         if ( IS_GMII_PORT(unit, port) && PHY_IS_BCM54210_220(pc) ) {
   2628             _phy_bcm542xx_rgmii_to_fiber_mode(unit, port);
   2629         }
   2630 
   2631         
   2632     }
   2633 
   2634     /* Configure LED mode and turn on jumbo frame support */
   2635     _phy_bcm54280_init(unit, port);
   2636 
   2637     return SOC_E_NONE;
   2638 }
   2639 
   2640 /*
   2641  * Function:
   2642  *    phy_bcm542xx_dev_init
   2643  * Purpose:
   2644  *    Initialize the PHY without reset.
   2645  * Parameters:
   2646  *    phy_dev_addr          - PHY Device Address
   2647  *    automedium            - Automedium select in combo ports
   2648  *    fiber_preferred       - Fiber preferrence over copper
   2649  *    fiber_detect          - Fiber Signal Detect
   2650  *    ext_phy_autodetect_en - Enable/Disable SGMII Slave Autodetect function
   2651  *    ext_phy_fiber_iface   - Fiber interface when Autodetect is disabled.
   2652  * Notes: 
   2653  */
   2654 STATIC int
   2655 phy_bcm542xx_dev_init(int unit, soc_port_t port, int automedium,
   2656                       int fiber_preferred, int fiber_detect,
   2657                       int fiber_enable   , int copper_enable,
   2658                       int ext_phy_autodetect_en, int ext_phy_fiber_iface)
   2659 {
   2660     int oui = 0, model = 0, rev = 0;
   2661     int rv = SOC_E_NONE;
   2662     phy_ctrl_t    *pc;
   2663 
   2664     pc = EXT_PHY_SW_STATE(unit, port);
   2665  
   2666     rv = _phy_bcm542xx_model_rev_get(unit, pc,&oui, &model, &rev);
   2667     if (rv != SOC_E_NONE) {
   2668         return SOC_E_FAIL;
   2669     }
   2670 
   2671     switch ( model ) {
   2672 
   2673     case (PHY_BCM54192_MODEL | PHY_BCM54195_MODEL):
   2674     case (PHY_BCM54182_MODEL | PHY_BCM54185_MODEL):
   2675         if ( rev & 0x8 ) {  /* PHY_BCM54185_MODEL */
   2676             rv = _phy_bcm54200_init(unit, port, automedium,
   2677                                     fiber_preferred,
   2678                                     fiber_detect,
   2679                                     fiber_enable,
   2680                                     copper_enable,
   2681                                     ext_phy_autodetect_en,
   2682                                     ext_phy_fiber_iface);
   2683         } else {
   2684             rv = _phy_bcm54282_init(unit, port);
   2685         }
   2686         break;
   2687    
   2688     case PHY_BCM54280_MODEL:
   2689         rv = _phy_bcm54280_init(unit, port);
   2690         break;
   2691 
   2692     case (PHY_BCM54190_MODEL | PHY_BCM54194_MODEL):    
   2693     case (PHY_BCM54180_MODEL | PHY_BCM54140_MODEL):    
   2694         if ( rev & 0x8 ) {  /* PHY_BCM54140_MODEL */
   2695             rv = _phy_bcm54200_init(unit, port, automedium,
   2696                                     fiber_preferred,
   2697                                     fiber_detect,
   2698                                     fiber_enable,
   2699                                     copper_enable,
   2700                                     ext_phy_autodetect_en,
   2701                                     ext_phy_fiber_iface); 
   2702         } else {
   2703             rv = _phy_bcm54280_init(unit, port);
   2704         }
   2705         break;
   2706 
   2707     case (PHY_BCM54282_MODEL | PHY_BCM54285_MODEL):
   2708     case PHY_BCM5428X_MODEL:
   2709         if ( rev & 0x8 ) {  /* PHY_BCM54282_MODEL */
   2710             rv = _phy_bcm54282_init(unit, port);
   2711 
   2712         } else {         /* PHY_BCM54285_MODEL */
   2713             rv = _phy_bcm54200_init(unit, port, automedium,
   2714                                     fiber_preferred,
   2715                                     fiber_detect,
   2716                                     fiber_enable,
   2717                                     copper_enable,
   2718                                     ext_phy_autodetect_en,
   2719                                     ext_phy_fiber_iface); 
   2720         }
   2721         break;
   2722     case PHY_BCM54210_MODEL:
   2723     case PHY_BCM54220_MODEL:
   2724     case PHY_BCM54240_MODEL:
   2725         rv = _phy_bcm54200_init(unit, port, automedium,
   2726                                     fiber_preferred,
   2727                                     fiber_detect,
   2728                                     fiber_enable,
   2729                                     copper_enable,
   2730                                     ext_phy_autodetect_en,
   2731                                     ext_phy_fiber_iface); 
   2732 
   2733         break;
   2734     case (PHY_BCM54292_MODEL | PHY_BCM54295_MODEL | PHY_BCM54296_MODEL):
   2735         if ( rev & 0x8 ) {    /* PHY_BCM54295/296_MODEL */
   2736             if ( 0x8 & _phy_bcm542xx_hidden_rev_num_get(unit, pc) ) {
   2737                 PHY_BCM542XX_SET_REAR_HALF(pc);
   2738             }
   2739             rv = _phy_bcm54200_init(unit, port, automedium,
   2740                                     fiber_preferred,
   2741                                     fiber_detect,
   2742                                     fiber_enable,
   2743                                     copper_enable,
   2744                                     ext_phy_autodetect_en,
   2745                                     ext_phy_fiber_iface); 
   2746         } else {         /* PHY_BCM54292_MODEL */
   2747             rv = _phy_bcm54282_init(unit, port);
   2748         }
   2749         break;
   2750     case (PHY_BCM54290_MODEL | PHY_BCM54294_MODEL):
   2751         if ( rev & 0x8 ) {  /* PHY_BCM54294_MODEL */
   2752             PHY_BCM542XX_SET_REAR_HALF(pc);
   2753             rv = _phy_bcm54200_init(unit, port, automedium,
   2754                                     fiber_preferred,
   2755                                     fiber_detect,
   2756                                     fiber_enable,
   2757                                     copper_enable,
   2758                                     ext_phy_autodetect_en,
   2759                                     ext_phy_fiber_iface); 
   2760         } else {         /* PHY_BCM54290_MODEL */
   2761             rv = _phy_bcm54280_init(unit, port);
   2762         }
   2763         break;
   2764 
   2765     default :
   2766         return SOC_E_FAIL;
   2767     }
   2768 
   2769     return rv;
   2770 }
   2771 
   2772 #if 0    /* 54240/28x do not go to production with Rev.B0 */
   2773 /*
   2774  * Function:
   2775  *    phy_bcm542xx_power_seq_war
   2776  * Purpose:   A failure to link can sometimes 
   2777  *            occur after initial power up.  
   2778  *            This is the workaround. 
   2779  *    
   2780  * Parameters:
   2781  *    phy_id        - PHY Device Address
   2782  * Notes: 
   2783  */
   2784 STATIC int
   2785 phy_bcm542xx_power_seq_war(int unit, soc_port_t port)
   2786 {
   2787     phy_ctrl_t    *pc;
   2788     int index=0, num_ports;
   2789     int oui=0, model=0, rev=0;
   2790     
   2791     pc = EXT_PHY_SW_STATE(unit, port);
   2792 
   2793     _phy_bcm542xx_model_rev_get(unit, pc,&oui, &model, &rev);
   2794  
   2795     /* Recommended: 
   2796        To be done in this fixed sequence for a power sequencing
   2797        bug. All the ports in one-go as it is not advisable to enter and exit 
   2798        test mode for each port.
   2799        Use pc_base->phy_id as the filter to escape this in context of other ports
   2800        since it will be already be done during pc_base's turn. 
   2801         - Do it after power recycle.
   2802     */
   2803     if ( pc->phy_id == PHY_BCM542XX_DEV_PHY_ID_BASE(pc) ) {
   2804         /* POWER SEQUENCE FIX */
   2805         if ( (model == PHY_BCM54240_MODEL) || (model == PHY_BCM54294_MODEL) ) {
   2806             num_ports = 4;
   2807         } else if ( model == PHY_BCM54210_MODEL ) {
   2808             num_ports = 1;
   2809         } else if ( model == PHY_BCM54220_MODEL ) {
   2810             num_ports = 2;
   2811         } else {
   2812             num_ports = 8;   
   2813         }
   2814 
   2815         for ( index = 0; index < num_ports; ++index ) {
   2816             pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc) + index;
   2817             
   2818             /* enable dsp clock */
   2819             PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc,
   2820                                       PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK, 
   2821                                       PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK);
   2822             phy_bcm542xx_direct_reg_write(unit, pc,
   2823                                       PHY_BCM542XX_LED_2_SEL_REG_OFFSET,
   2824                                       0xB8EE);
   2825             phy_bcm542xx_direct_reg_write(unit, pc,
   2826                                       PHY_BCM542XX_LED_1_SEL_REG_OFFSET,
   2827                                       0xB4EE);
   2828             phy_bcm542xx_direct_reg_write(unit, pc,
   2829                                       PHY_BCM542XX_DSP_TAP17_C0_REG_OFFSET,
   2830                                       0x0009);
   2831             phy_bcm542xx_direct_reg_write(unit, pc,
   2832                                       PHY_BCM542XX_DSP_TAP17_C1_REG_OFFSET,
   2833                                       0x0001);
   2834             phy_bcm542xx_direct_reg_write(unit, pc,
   2835                                       PHY_BCM542XX_DSP_TAP17_C1_REG_OFFSET,
   2836                                       0x0003);
   2837             /* Disable dsp clock */
   2838             PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc,
   2839                                       0, 
   2840                                       PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK);
   2841 
   2842         }   
   2843         /***********************************************************************
   2844          * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   2845          * To access TOP level registers use phy_id of port0. Override this ports 
   2846          */
   2847         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   2848 
   2849 #if 0 
   2850         phy_bcm542xx_direct_reg_write(unit, pc,
   2851                                        PHY_BCM542XX_TOP_MISC_BOOT_REG_1_OFFSET,
   2852                                        0x8800);
   2853         phy_bcm542xx_direct_reg_write(unit, pc,
   2854                                        PHY_BCM542XX_TOP_MISC_BOOT_REG_1_OFFSET,
   2855                                        0x0000);
   2856         
   2857         phy_bcm542xx_direct_reg_write(unit, pc,
   2858                                        PHY_BCM542XX_TOP_MISC_BOOT_REG_0_OFFSET,
   2859                                        0x0DA3);
   2860 
   2861         phy_bcm542xx_direct_reg_write(unit, pc,
   2862                                        PHY_BCM542XX_TOP_MISC_BOOT_REG_0_OFFSET,
   2863                                        0x0D23);
   2864         phy_bcm542xx_direct_reg_write(unit, pc,
   2865                                        PHY_BCM542XX_TOP_MISC_BOOT_REG_1_OFFSET,
   2866                                        0x8000);
   2867 #else
   2868         WRITE_PHY_REG(unit, pc,0x17, 0xD19);
   2869         WRITE_PHY_REG(unit, pc,0x15, 0x8800);
   2870         WRITE_PHY_REG(unit, pc,0x17, 0xD19);
   2871         WRITE_PHY_REG(unit, pc,0x15, 0x0000);
   2872         WRITE_PHY_REG(unit, pc,0x17, 0xD18);
   2873         WRITE_PHY_REG(unit, pc,0x15, 0x0DA3);
   2874         WRITE_PHY_REG(unit, pc,0x17, 0xD18);
   2875         WRITE_PHY_REG(unit, pc,0x15, 0x0D23);
   2876         WRITE_PHY_REG(unit, pc,0x17, 0xD19);
   2877         WRITE_PHY_REG(unit, pc,0x15, 0x8000);
   2878 #endif
   2879 
   2880         /***********************************************************************
   2881          * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   2882          * To access TOP level registers use phy_id of port0. Now restore back 
   2883          */
   2884         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   2885     }
   2886     return SOC_E_NONE;
   2887 } 
   2888 #endif /* 0 */   /* 54240/28x do not go to production with Rev.B0 */
   2889 
   2890 /*
   2891  * Function:
   2892  *    phy_bcm542xx_reset_setup 
   2893  * Purpose:
   2894  *    Reset the PHY.
   2895  * Parameters:
   2896  *    phy_id - PHY Device Address of the PHY to reset
   2897  */
   2898 int 
   2899 phy_bcm542xx_reset_setup(int unit, soc_port_t port, 
   2900                          int automedium,
   2901                          int fiber_preferred, 
   2902                          int fiber_detect,
   2903                          int fiber_enable,
   2904                          int copper_enable,
   2905                          int ext_phy_autodetect_en,
   2906                          int ext_phy_fiber_iface)
   2907 {
   2908     soc_port_t     primary_port;
   2909     int            index;
   2910     phy_ctrl_t    *pc;
   2911     int            oui = 0, model = 0, rev = 0;
   2912 
   2913     pc = EXT_PHY_SW_STATE(unit, port);
   2914 
   2915     /* Set primary port & offset */
   2916     if ( soc_phy_primary_and_offset_get(unit, port, &primary_port, &index)
   2917                                     == SOC_E_NONE) {
   2918         if ( index & 0x80 ) {
   2919             PHY_BCM542XX_FLAGS(pc) |=  PHY_BCM542XX_PHYADDR_REVERSE;
   2920         } else {
   2921             PHY_BCM542XX_FLAGS(pc) &= ~PHY_BCM542XX_PHYADDR_REVERSE;
   2922         }
   2923 
   2924         /* Do not change the order */
   2925         index &= ~0x80; /* clear reverse bit (PHYA_REV) */
   2926         PHY_BCM542XX_DEV_PHY_ID_ORIG(pc) = pc->phy_id;
   2927         PHY_BCM542XX_DEV_PHY_SLICE(pc) = index;
   2928         PHY_BCM542XX_DEV_SET_BASE_ADDR(pc); /* phy address of port 0 */
   2929 
   2930         SOC_IF_ERROR_RETURN
   2931             (phy_bcm542xx_control_set(unit, port, 
   2932                                       SOC_PHY_CONTROL_PORT_PRIMARY, 
   2933                                       primary_port));
   2934         SOC_IF_ERROR_RETURN
   2935             (phy_bcm542xx_control_set(unit, port, 
   2936                                       SOC_PHY_CONTROL_PORT_OFFSET, 
   2937                                       index ));
   2938     } else {
   2939         LOG_WARN(BSL_LS_SOC_PHY,
   2940                  (BSL_META_U(unit,
   2941                              "phy_bcm542xx_reset_setup: Config property "
   2942                              "'phy_port_primary_and_offset' "
   2943                              "not set for u=%d, p=%d\n"), unit, port));
   2944         return SOC_E_FAIL;
   2945     }
   2946 
   2947     /* PHY reset */
   2948     SOC_IF_ERROR_RETURN( phy_bcm542xx_reset(unit, port, (void*) NULL) );
   2949     if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_INIT_DONE) ) {
   2950         /* Reset the Top level register block  (RDB Reg.0x800-0xAFF) *\
   2951         \* during the 1st initialization only.                       */
   2952         phy_bcm542xx_direct_reg_modify(unit, pc,
   2953                               PHY_BCM542XX_TOP_MISC_GLOBAL_RESET_OFFSET,
   2954                               PHY_BCM542XX_TOP_MISC_GLOBAL_RESET_TOP_MII_SOFT |
   2955                               PHY_BCM542XX_TOP_MISC_GLOBAL_RESET_TIMESYNC,
   2956                               PHY_BCM542XX_TOP_MISC_GLOBAL_RESET_TOP_MII_SOFT |
   2957                               PHY_BCM542XX_TOP_MISC_GLOBAL_RESET_TIMESYNC);
   2958     }
   2959 
   2960     /* get the model & revision ID of PHY chip */
   2961     SOC_IF_ERROR_RETURN(
   2962             _phy_bcm542xx_model_rev_get(unit, pc,&oui, &model, &rev));
   2963 
   2964     if (PHY_IS_BCM54180(pc) || PHY_IS_BCM54182(pc) || PHY_IS_BCM54185(pc) || PHY_IS_BCM54140(pc) ) {
   2965         SOC_IF_ERROR_RETURN(
   2966                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E7, 0xA008));
   2967         SOC_IF_ERROR_RETURN(
   2968                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x0028, 0x0C30));
   2969         SOC_IF_ERROR_RETURN(
   2970                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x00D8, 0x0020));
   2971         SOC_IF_ERROR_RETURN(
   2972                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x012D, 0x0352));
   2973         SOC_IF_ERROR_RETURN(
   2974                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x012E, 0xA04D));
   2975         SOC_IF_ERROR_RETURN(
   2976                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x0164, 0x0500));
   2977         SOC_IF_ERROR_RETURN(
   2978                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x0165, 0x7859));
   2979         SOC_IF_ERROR_RETURN(
   2980                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x0125, 0x091B));
   2981         SOC_IF_ERROR_RETURN(
   2982                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E8, 0x00C3));
   2983         SOC_IF_ERROR_RETURN(
   2984                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E9, 0x00CC));
   2985         SOC_IF_ERROR_RETURN(
   2986                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01EA, 0x0300));
   2987         SOC_IF_ERROR_RETURN(
   2988                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E2, 0x02E3));
   2989         SOC_IF_ERROR_RETURN(
   2990                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E3, 0x7FC1));
   2991         SOC_IF_ERROR_RETURN(
   2992                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E5, 0xA7AB));
   2993         SOC_IF_ERROR_RETURN(
   2994                 phy_bcm542xx_rdb_reg_write(unit, pc, 0x0028, 0x0430));
   2995 
   2996     }
   2997 
   2998 #if 0    /* 54240/28x do not go to production with Rev.B0 */
   2999     /* WAR only for B0 rev */
   3000     if ( PHY_BCM54240_28X_REV_BO(model, rev) ) {
   3001         phy_bcm542xx_power_seq_war(unit, port);
   3002     }
   3003 #endif
   3004 
   3005     /* WAR for C0 and revisions before C0 */
   3006     if ( PHY_BCM54240_28X_REV_C0_OR_OLDER(model, rev) ) {
   3007         /* EEE: Suggested defailt settings for these registers */
   3008         /* ENable dsp clock */
   3009         phy_bcm542xx_direct_reg_write(unit, pc,
   3010                                       PHY_BCM542XX_AUX_CTRL_REG_OFFSET,
   3011                                       0x0C00);
   3012         phy_bcm542xx_direct_reg_write(unit, pc,
   3013                                       PHY_BCM542XX_DSP_TAP33_C2_REG_OFFSET,
   3014                                       0x8787);
   3015         phy_bcm542xx_direct_reg_write(unit, pc,
   3016                                       PHY_BCM542XX_DSP_TAP34_C2_REG_OFFSET,
   3017                                       0x017D);
   3018         /* DISable dsp clock */
   3019         phy_bcm542xx_direct_reg_write(unit, pc,
   3020                                       PHY_BCM542XX_AUX_CTRL_REG_OFFSET,
   3021                                       0x0400);
   3022 
   3023         /* Recommended INIT default settings for registers */
   3024         phy_bcm542xx_direct_reg_write(unit, pc,
   3025                                       PHY_BCM542XX_AFE_RXCONFIG_0_REG_OFFSET,
   3026                                       0xD771);
   3027         phy_bcm542xx_direct_reg_write(unit, pc,
   3028                                       PHY_BCM542XX_AFE_RXCONFIG_2_REG_OFFSET,
   3029                                       0x0072);
   3030         phy_bcm542xx_direct_reg_write(unit, pc,
   3031                                       PHY_BCM542XX_AFE_HPF_TRIM_REG_OFFSET,
   3032                                       0x0006);
   3033         phy_bcm542xx_direct_reg_write(unit, pc,
   3034                                       PHY_BCM542XX_HALT_AGC_CTRL_REG_OFFSET,
   3035                                       0x0020);
   3036         phy_bcm542xx_direct_reg_write(unit, pc,
   3037                                       PHY_BCM542XX_AFE_AFE_PLLCTRL_4_REG_OFFSET,
   3038                                       0x0500);
   3039         phy_bcm542xx_direct_reg_write(unit, pc,
   3040                                       PHY_BCM542XX_AFE_VDACCTRL_1_REG_OFFSET,
   3041                                       0xC100);
   3042         phy_bcm542xx_direct_reg_write(unit, pc,
   3043                                       PHY_BCM542XX_ANLOG_PWR_CTRL_OVRIDE_REG_OFFSET,
   3044                                       0x1000);
   3045         phy_bcm542xx_direct_reg_write(unit, pc,
   3046                                       PHY_BCM542XX_TDR_OVRIDE_VAL_REG_OFFSET,
   3047                                       0x7C00);
   3048         phy_bcm542xx_direct_reg_write(unit, pc,
   3049                                       PHY_BCM542XX_TDR_OVRIDE_VAL_REG_OFFSET,
   3050                                       0x0000);
   3051     }
   3052     
   3053     /* 54240/5428x C1 rev */
   3054     if ( PHY_BCM54240_28X_REV_C1(model, rev) ) {
   3055         /* 54240/5428x C1 Long Cable BER suppor, JIRA PHY-1629. *\
   3056         \*                Errata 54240-ES101-R, 54280-ES101-R   */
   3057         /* ENable dsp clock */
   3058         phy_bcm542xx_direct_reg_write(unit, pc,
   3059                                       PHY_BCM542XX_AUX_CTRL_REG_OFFSET,
   3060                                       0x0C00);
   3061         phy_bcm542xx_direct_reg_write(unit, pc,
   3062                                       PHY_BCM542XX_AFE_VDACCTRL_2_REG_OFFSET,
   3063                                       0x0007);
   3064         phy_bcm542xx_direct_reg_write(unit, pc,
   3065                                       PHY_BCM542XX_DSP_TAP33_C2_REG_OFFSET,
   3066                                       0x87F6);
   3067         phy_bcm542xx_direct_reg_write(unit, pc,
   3068                                       PHY_BCM542XX_DSP_TAP10_REG_OFFSET,
   3069                                       0x011B);
   3070         /* DISable dsp clock */
   3071         phy_bcm542xx_direct_reg_write(unit, pc,
   3072                                       PHY_BCM542XX_AUX_CTRL_REG_OFFSET,
   3073                                       0x0400);
   3074     }
   3075     
   3076     /* Recommended DSP_TAP10 setting for all the revisions */
   3077     phy_bcm542xx_direct_reg_write(unit, pc,
   3078                                   PHY_BCM542XX_AUX_CTRL_REG_OFFSET,
   3079                                   0x0C00);
   3080     phy_bcm542xx_direct_reg_write(unit, pc,
   3081                                   PHY_BCM542XX_DSP_TAP10_REG_OFFSET,
   3082                                   0x011B);
   3083     /* config property PHY_OPERATIONAL_MODE == 0x80 or 0x8000 or 0x8080    *\
   3084     \*        means to keep Super Isolate setting (depend on HW strap pin) */
   3085     if ( 0 == (PHY_RETAIN_SUPER_ISOLATE &
   3086                soc_property_port_get(unit, port, spn_PHY_OPERATIONAL_MODE, 0)) ) {
   3087         /* Remove  Super Isolate */
   3088         phy_bcm542xx_direct_reg_modify(unit, pc,
   3089                                   PHY_BCM542XX_POWER_MII_CTRL_REG_OFFSET, 0x0,
   3090                                   PHY_BCM542XX_POWER_MII_CTRL_SUPER_ISOLATE);
   3091         LOG_INFO(BSL_LS_SOC_PHY, (BSL_META_U(unit,
   3092                         "Remove Super Isolate: u=%d p=%d\n"), unit, port));
   3093     }
   3094 
   3095     /* Enable current mode LED */
   3096     phy_bcm542xx_direct_reg_write(unit, pc,
   3097                                   PHY_BCM542XX_LED_GPIO_CTRL_STATUS_REG_OFFSET,
   3098                                   0xBC00);
   3099 
   3100     SOC_IF_ERROR_RETURN(
   3101             phy_bcm542xx_dev_init(unit, port, automedium, 
   3102                                   fiber_preferred, fiber_detect,
   3103                                   fiber_enable, copper_enable,
   3104                                   ext_phy_autodetect_en,
   3105                                   ext_phy_fiber_iface));
   3106 
   3107     return SOC_E_NONE;
   3108 }
   3109 
   3110 /*
   3111  * Function:
   3112  *    phy_bcm542xx_init_setup
   3113  * Purpose:
   3114  *    Initialize the PHY with PHY reset.
   3115  * Parameters:
   3116  *    phy_dev_addr          - PHY Device Address
   3117  *    automedium            - Automedium select in combo ports
   3118  *    fiber_preferred       - Fiber preferrence over copper
   3119  *    fiber_detect          - Fiber Signal Detect
   3120  *    ext_phy_autodetect_en - Enable/Disable SGMII Slave Autodetect function
   3121  *    ext_phy_fiber_iface   - Fiber interface when Autodetect is disabled.
   3122  * Notes: 
   3123  */
   3124 STATIC int 
   3125 phy_bcm542xx_init_setup( int unit,
   3126                          soc_port_t port,
   3127                          int reset, 
   3128                          int automedium,
   3129                          int fiber_preferred, 
   3130                          int fiber_detect,
   3131                          int fiber_enable,
   3132                          int copper_enable,
   3133                          int ext_phy_autodetect_en,
   3134                          int ext_phy_fiber_iface)
   3135 {
   3136     phy_ctrl_t    *pc;
   3137     int            dev_port;
   3138 
   3139     pc = EXT_PHY_SW_STATE(unit, port);
   3140    
   3141     if ( reset ) {
   3142         SOC_IF_ERROR_RETURN(
   3143             phy_bcm542xx_reset_setup(unit, port, automedium, 
   3144                                      fiber_preferred, fiber_detect,
   3145                                      fiber_enable,
   3146                                      copper_enable,
   3147                                      ext_phy_autodetect_en,
   3148                                      ext_phy_fiber_iface));
   3149     } else {
   3150         SOC_IF_ERROR_RETURN(
   3151             phy_bcm542xx_dev_init(   unit, port, automedium, 
   3152                                      fiber_preferred, fiber_detect,
   3153                                      fiber_enable,
   3154                                      copper_enable,
   3155                                      ext_phy_autodetect_en,
   3156                                      ext_phy_fiber_iface));
   3157         /* called by _phy_bcm542xx_no_reset_setup() or _phy_bcm542xx_medium_change() *\
   3158         \* no need to do the remaining RESET process below                           */
   3159         return SOC_E_NONE;
   3160     }
   3161 
   3162     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   3163         return SOC_E_NONE;
   3164     }
   3165 
   3166     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   3167     
   3168     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   3169        of the device. For example to enable autogrEEEn on port0, 
   3170        rdb register for port 4 0x808 need to be used. 
   3171        Refer package configuration document.
   3172      */
   3173     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   3174         dev_port += 4;
   3175     }
   3176 
   3177     /* Reset EEE to default state i.e disable */
   3178     
   3179     /* Native */
   3180     /* Disable LPI feature */
   3181     SOC_IF_ERROR_RETURN(
   3182             PHY_MODIFY_BCM542XX_EEE_803Dr(unit, pc, 0x0000, 0xC000) );
   3183     /* Reset counters and other settings */   
   3184     SOC_IF_ERROR_RETURN(
   3185             PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc, 0x0000, 0x3fff) );
   3186 
   3187     /* AutogrEEEn */
   3188     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   3189     /* Disable AutogrEEEn and reset other settings */
   3190     SOC_IF_ERROR_RETURN(
   3191             phy_bcm542xx_direct_reg_write(unit, pc,
   3192                             PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port), 
   3193                             0x8000) );  
   3194 
   3195     /* Long cable EEE support */
   3196     if ( PHY_IS_BCM5429X(pc) ) {
   3197         #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
   3198         PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc);   /* set RDB register access mode */
   3199         #endif
   3200         /* ENable dsp clock */
   3201         SOC_IF_ERROR_RETURN(
   3202             phy_bcm542xx_rdb_reg_write(unit, pc,
   3203                     PHY_BCM542XX_AUX_CTRL_REG_OFFSET, 0x0C00));
   3204         
   3205         SOC_IF_ERROR_RETURN(
   3206             phy_bcm542xx_rdb_reg_write(unit, pc,
   3207                     PHY_BCM542XX_AFE_RXCONFIG_2_REG_OFFSET, 0x1872));
   3208         SOC_IF_ERROR_RETURN(
   3209             phy_bcm542xx_rdb_reg_write(unit, pc,
   3210                     0x1C1, 0xA5F5));
   3211         SOC_IF_ERROR_RETURN(
   3212             phy_bcm542xx_rdb_reg_write(unit, pc,
   3213                     0x150, 0xC70B));
   3214 
   3215         /* DISable dsp clock */
   3216         SOC_IF_ERROR_RETURN(
   3217             phy_bcm542xx_rdb_reg_write(unit, pc,
   3218                     PHY_BCM542XX_AUX_CTRL_REG_OFFSET, 0x0400));
   3219 
   3220         #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
   3221         PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */
   3222         #endif
   3223     }
   3224 
   3225     /* restore original phy_id */ 
   3226     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   3227 
   3228 #if AUTO_MDIX_WHEN_AN_DIS
   3229     /* Enable Auto-MDIX When autoneg disabled */
   3230     SOC_IF_ERROR_RETURN(
   3231         PHY_MODIFY_BCM542XX_MII_MISC_CTRLr(unit, pc,
   3232                             PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE, 
   3233                             PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE) );
   3234 #endif 
   3235 
   3236 #ifdef LC_CM_DISABLE_WORKAROUND
   3237     SOC_IF_ERROR_RETURN(      /* Disable LED current mode */
   3238         phy_bcm542xx_direct_reg_write(unit, pc, 0x1F, 0xBC0F) );
   3239 #endif
   3240 
   3241     return SOC_E_NONE;
   3242 }
   3243 
   3244 /*
   3245  * Function:
   3246  *      phy_bcm542xx_init
   3247  * Purpose:
   3248  *      Init function for 542xx PHY.
   3249  * Parameters:
   3250  *      unit - StrataSwitch unit #.
   3251  *      port - StrataSwitch port #.
   3252  * Returns:
   3253  *      SOC_E_NONE
   3254  */
   3255 
   3256 STATIC int
   3257 phy_bcm542xx_init(int unit, soc_port_t port)
   3258 {
   3259     phy_ctrl_t *pc;
   3260     int        fiber_capable = 0, rv;
   3261     int        fiber_preferred;
   3262     PHY_BCM542XX_DEV_DESC_t *pDesc;
   3263 
   3264     LOG_INFO(BSL_LS_SOC_PHY,
   3265              (BSL_META_U(unit, "phy_bcm542xxx_init: u=%d p=%d\n"),
   3266                          unit, port));
   3267 
   3268     pc = EXT_PHY_SW_STATE(unit, port);
   3269     
   3270     /* Only SGMII interface to switch MAC is supported */ 
   3271     if (IS_GMII_PORT(unit, port) && !(PHY_IS_BCM54210_220(pc)) ) {
   3272         return SOC_E_CONFIG; 
   3273     }
   3274 
   3275     if ( IS_GMII_PORT(unit, port) ) {
   3276         pc->interface = SOC_PORT_IF_GMII;
   3277     } else {
   3278         /* interface type has been determined by phy_bcm542xx_probe() */
   3279     }
   3280     
   3281     if ( ! (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)) ) {
   3282         /* if not during warmboot or reloading */
   3283         PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc);
   3284     }
   3285 
   3286     /* all 542xx support Energy-Efficient Ethernet */
   3287     PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_CAPABLE);
   3288 
   3289     /*
   3290      * get the PHY description structure, the software table
   3291      * recording the PHY address info and OAM config.
   3292      */
   3293     pDesc = (PHY_BCM542XX_DEV_DESC_t *)(pc+1);
   3294     sal_memset(pDesc, 0, sizeof(PHY_BCM542XX_DEV_DESC_t));  /* clear the memory */
   3295 
   3296     /*
   3297      * Default settings for the PHY control table (phy_ctrl_t *pc)
   3298      */
   3299 
   3300     /* fiber_capable? */
   3301     if ( PHY_IS_BCM54140(pc) || PHY_IS_BCM54185(pc) ||
   3302          PHY_IS_BCM54194(pc) || PHY_IS_BCM54195(pc) ||
   3303          PHY_IS_BCM54210(pc) || PHY_IS_BCM54220(pc) ||
   3304          PHY_IS_BCM54240(pc) || PHY_IS_BCM54285(pc) ||
   3305          PHY_IS_BCM54294(pc) || PHY_IS_BCM54295(pc) || PHY_IS_BCM54296(pc) ) {
   3306         fiber_capable = 1;
   3307     }
   3308 
   3309     if ( fiber_capable == 0 ) {    /* not fiber capable */
   3310         fiber_preferred  = 0;
   3311         pc->automedium   = 0;
   3312         pc->fiber_detect = 0;
   3313         pc->ext_phy_autodetect_en = -1;
   3314         pc->ext_phy_fiber_iface = -1;
   3315     } else {    /* Change it to copper prefer for default. */
   3316         fiber_preferred  = soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 0);
   3317         pc->automedium   = soc_property_port_get(unit, port, spn_PHY_AUTOMEDIUM, 0);
   3318         pc->fiber_detect = soc_property_port_get(unit, port, spn_PHY_FIBER_DETECT, -4);
   3319         pc->ext_phy_autodetect_en = soc_property_port_get(unit, port, spn_EXT_PHY_AUTODETECT_EN, -1);
   3320         pc->ext_phy_fiber_iface = soc_property_port_get(unit, port, spn_EXT_PHY_SERDES_FIBER_IFACE, -1);
   3321     }
   3322     LOG_INFO(BSL_LS_SOC_PHY,
   3323              (BSL_META_U(unit,
   3324                          "phy_542xx_init: u=%d p=%d type=bcm542xx%s "
   3325                          "automedium=%d fiber_pref=%d detect=%d "
   3326                          "ext_phy_autodetect_en=%d ext_phy_fiber_iface=%d\n"),
   3327               unit, port, fiber_capable ? "S" : "",
   3328               pc->automedium, fiber_preferred, pc->fiber_detect,
   3329               pc->ext_phy_autodetect_en, pc->ext_phy_fiber_iface));
   3330 
   3331     pc->copper.enable = TRUE;
   3332     pc->copper.preferred = ! fiber_preferred;
   3333     pc->copper.autoneg_enable = TRUE;
   3334     ADVERT_ALL_COPPER(&pc->copper.advert_ability);
   3335     pc->copper.force_speed = 1000;
   3336     pc->copper.force_duplex = TRUE;
   3337     pc->copper.master = SOC_PORT_MS_AUTO;
   3338     pc->copper.mdix = SOC_PORT_MDIX_AUTO;
   3339 
   3340     pc->fiber.enable = fiber_capable;
   3341     pc->fiber.preferred = fiber_preferred;
   3342     /* Auto-neg is unsupported in 100FX mode */
   3343     if (fiber_preferred && (pc->ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS) &&
   3344         (pc->ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_100FX)) {
   3345         pc->fiber.autoneg_enable = 0;
   3346     } else {
   3347         pc->fiber.autoneg_enable = fiber_capable;
   3348     }
   3349 
   3350     ADVERT_ALL_FIBER(&pc->fiber.advert_ability);
   3351     pc->fiber.force_speed = 1000;
   3352     pc->fiber.force_duplex = TRUE;
   3353     pc->fiber.master = SOC_PORT_MS_NONE;
   3354     pc->fiber.mdix = SOC_PORT_MDIX_NORMAL;
   3355 
   3356     /* Initially configure for the preferred medium. */
   3357     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
   3358     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
   3359     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU);
   3360     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
   3361     if ( pc->fiber.preferred ) {
   3362         PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   3363     } else {
   3364         PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
   3365     }
   3366     
   3367     if (fiber_preferred && (pc->ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS)) {
   3368         if (pc->ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_100FX) {
   3369             PHY_FLAGS_SET(unit, port, PHY_FLAGS_100FX);
   3370             pc->fiber.force_speed = 100;
   3371         }     
   3372     }
   3373     
   3374     /* Get Requested LED selectors (defaults are hardware defaults) */
   3375     pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0);
   3376     pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1);
   3377     pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3);
   3378     pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6);
   3379     pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8);
   3380     pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0);
   3381 
   3382    /* Init PHYS and MACs to defaults */
   3383     rv = phy_bcm542xx_init_setup(unit, port, 1,
   3384                                  pc->automedium,
   3385                                  fiber_preferred,
   3386                                  pc->fiber_detect,  
   3387                                  pc->fiber.enable,
   3388                                  pc->copper.enable, 
   3389                                  pc->ext_phy_autodetect_en,
   3390                                  pc->ext_phy_fiber_iface);
   3391     if ( rv != SOC_E_NONE ) {
   3392         return SOC_E_FAIL;
   3393     }
   3394 
   3395 #ifdef BCM_WARM_BOOT_SUPPORT
   3396     /* if WarmBoot, retrieve PHY states from PHY registers */
   3397     if ( SOC_WARM_BOOT(unit) ) {
   3398         soc_port_medium_t  medium;
   3399         int                andone;
   3400 
   3401         /* retrieve the medium mode (copper or fiber) */
   3402         SOC_IF_ERROR_RETURN( _phy_bcm542xx_medium_check(unit, port, &medium) );
   3403 
   3404         if ( medium == SOC_PORT_MEDIUM_COPPER ) {
   3405             PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
   3406             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
   3407             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
   3408             /* retrieve copper staus from MII registers */
   3409             SOC_IF_ERROR_RETURN(
   3410                 phy_bcm542xx_ability_advert_get(unit, port, &(pc->copper.advert_ability)) );
   3411             SOC_IF_ERROR_RETURN(
   3412                 phy_bcm542xx_autoneg_get(unit, port, &(pc->copper.autoneg_enable), &andone) );
   3413             SOC_IF_ERROR_RETURN(
   3414                 phy_bcm542xx_duplex_get(unit, port, &(pc->copper.force_duplex)) );
   3415             SOC_IF_ERROR_RETURN(
   3416                 phy_bcm542xx_master_get(unit, port, &(pc->copper.master)) );
   3417             SOC_IF_ERROR_RETURN(
   3418                 phy_bcm542xx_speed_get(unit, port, &(pc->copper.force_speed)) );
   3419             if ( pc->copper.force_speed == 0 ) {
   3420                 pc->copper.force_speed = 1000;    /* default speed */
   3421             }
   3422             SOC_IF_ERROR_RETURN(
   3423                 phy_bcm542xx_mdix_get(unit, port, &(pc->copper.mdix)) );
   3424         } else {      /* SOC_PORT_MEDIUM_FIBER */
   3425             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   3426             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
   3427             /* retrieve fiber status from MII registers */
   3428             SOC_IF_ERROR_RETURN(
   3429                 phy_bcm542xx_ability_advert_get(unit, port, &(pc->fiber.advert_ability)) );
   3430             SOC_IF_ERROR_RETURN(
   3431                 phy_bcm542xx_autoneg_get(unit, port, &(pc->fiber.autoneg_enable), &andone) );
   3432             SOC_IF_ERROR_RETURN(
   3433                 phy_bcm542xx_duplex_get(unit, port, &(pc->fiber.force_duplex)) );
   3434             SOC_IF_ERROR_RETURN(
   3435                 phy_bcm542xx_master_get(unit, port, &(pc->fiber.master)) );
   3436             SOC_IF_ERROR_RETURN(
   3437                 phy_bcm542xx_speed_get(unit, port, &(pc->fiber.force_speed)) );
   3438             if ( pc->fiber.force_speed == 0 ) {
   3439                 pc->fiber.force_speed = 1000;    /* default speed */
   3440             } else if ( pc->fiber.force_speed == 100 ) {
   3441                 PHY_FLAGS_SET(unit, port, PHY_FLAGS_100FX);
   3442             }
   3443         }
   3444 
   3445         if ( fiber_capable == 1 ) {
   3446             uint16  val16;
   3447             /* determine default medium, copper or fiber */
   3448             SOC_IF_ERROR_RETURN(
   3449                 PHY_READ_BCM542XX_AUTO_DETECT_MEDIUMr(unit, pc, &val16) );
   3450             pc->fiber_detect     = ( val16 & BIT(8) ) ? -4 : 0;
   3451             pc->fiber.preferred  = ( val16 & BIT(1) ) ? TRUE : FALSE;
   3452             pc->copper.preferred = ! pc->fiber.preferred;
   3453         }
   3454     } /* if (WARM_BOOT) */
   3455 
   3456     /* retreve the OAM setting from chip registers */
   3457     phy_bcm542xx_oam_config_get(unit, port, &(pDesc->oam_config));
   3458 #endif /* BCM_WARM_BOOT_SUPPORT */
   3459 
   3460     if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) {
   3461         return SOC_E_NONE;
   3462         /* if WarmBoot, skip the following steps */
   3463     }
   3464 
   3465     /* Set LED Modes and Control */
   3466     rv = phy_bcm542xx_set_led_selectors(unit, pc);
   3467     if (rv != SOC_E_NONE) {
   3468         return SOC_E_FAIL;
   3469     }
   3470 
   3471     /* Access LED related register  */
   3472     if ( soc_property_port_get(unit, port, "phy_led3_output_disable", 0) ) {
   3473         SOC_IF_ERROR_RETURN(
   3474             phy_bcm542xx_direct_reg_modify(unit, pc, 0x814, 0x0001, 0x0001) );
   3475     }
   3476 
   3477     SOC_IF_ERROR_RETURN
   3478         (_phy_bcm542xx_medium_config_update(unit, port,
   3479                                         PHY_COPPER_MODE(unit, port) ?
   3480                                         &pc->copper :
   3481                                         &pc->fiber));
   3482     return SOC_E_NONE;
   3483 }
   3484 
   3485 
   3486 /*
   3487  * Function:
   3488  *  phy_bcm542xx_reset
   3489  * Purpose: 
   3490  *  Reset PHY and wait for it to come out of reset.
   3491  * Parameters:
   3492  *  unit - StrataSwitch unit #.
   3493  *  port - StrataSwitch port #. 
   3494  * Returns: 
   3495  *  SOC_E_XXX
   3496  */
   3497 
   3498 int
   3499 phy_bcm542xx_reset(int unit, soc_port_t port, void *user_arg)
   3500 {
   3501     int rv;
   3502     phy_ctrl_t*  pc = EXT_PHY_SW_STATE(unit, port);
   3503 
   3504     rv = phy_fe_ge_reset(unit, port, NULL);
   3505     PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc);
   3506     return ( rv );
   3507 }
   3508 
   3509 /*
   3510  * Function:
   3511  *      phy_bcm542xx_enable_set
   3512  * Purpose:
   3513  *      Enable or disable the physical interface.
   3514  * Parameters:
   3515  *      unit - StrataSwitch unit #.
   3516  *      port - StrataSwitch port #.
   3517  *      enable - Boolean, true = enable PHY, false = disable.
   3518  * Returns:
   3519  *      SOC_E_XXX
   3520  */
   3521 
   3522 STATIC int
   3523 phy_bcm542xx_enable_set(int unit, soc_port_t port, int enable)
   3524 {
   3525     phy_ctrl_t  *pc    = EXT_PHY_SW_STATE(unit, port);
   3526     uint16       power = (enable) ? 0 : PHY_BCM542XX_MII_CTRL_PWR_DOWN;
   3527     /* 
   3528      * Updated _phy_bcm54200_init to not power up the fiber and
   3529      * copper PHY if port PHY is disabled. Here we need to power them up.
   3530      * There is a timing issue that the fiber medium otherwise may not
   3531      * be detected when both mediums are present at the boot time.
   3532      */
   3533     if ( PHY_COPPER_MODE(unit, port) || pc->automedium ) {
   3534         SOC_IF_ERROR_RETURN
   3535             (PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc, power,
   3536                                            PHY_BCM542XX_MII_CTRL_PWR_DOWN));
   3537     }
   3538     if ( PHY_FIBER_MODE(unit, port)  || pc->automedium ) {
   3539         SOC_IF_ERROR_RETURN
   3540             (PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, power,
   3541                                            PHY_BCM542XX_MII_CTRL_PWR_DOWN));
   3542     }
   3543 
   3544     if ( pc->automedium || PHY_FIBER_MODE(unit, port) ) {
   3545         phy_ctrl_t* int_pc = INT_PHY_SW_STATE(unit, port);
   3546 
   3547         if ( NULL != int_pc ) {
   3548             SOC_IF_ERROR_RETURN
   3549                 (PHY_ENABLE_SET(int_pc->pd, unit, port, enable));
   3550         }
   3551         LOG_INFO(BSL_LS_SOC_PHY,
   3552                  (BSL_META_U(unit, "phy_bcm542xx_enable_set: "
   3553                                    "Power %s fiber medium, u=%d p=%d\n"),
   3554                   (enable) ? "up" : "down", unit, port));
   3555     }
   3556 
   3557     /* Update software state */
   3558     SOC_IF_ERROR_RETURN(phy_fe_ge_enable_set(unit, port, enable));
   3559 
   3560     return SOC_E_NONE;
   3561 }
   3562 
   3563 /*
   3564  * Function:
   3565  *      phy_bcm542xx_enable_get
   3566  * Purpose:
   3567  *      Enable or disable the physical interface for a 542xx device.
   3568  * Parameters:
   3569  *      unit - StrataSwitch unit #.
   3570  *      port - StrataSwitch port #.
   3571  *      enable - (OUT) Boolean, true = enable PHY, false = disable.
   3572  * Returns:
   3573  *      SOC_E_XXX
   3574  */
   3575 
   3576 STATIC int
   3577 phy_bcm542xx_enable_get(int unit, soc_port_t port, int *enable)
   3578 {
   3579     return phy_fe_ge_enable_get(unit, port, enable);
   3580 }
   3581 
   3582 /*
   3583  * Function:
   3584  *      phy_bcm542xx_link_get
   3585  * Purpose:
   3586  *      Determine the current link up/down status for a 542xx device.
   3587  * Parameters:
   3588  *      unit - StrataSwitch unit #.
   3589  *      port - StrataSwitch port #.
   3590  *      link - (OUT) Boolean, true indicates link established.
   3591  * Returns:
   3592  *      SOC_E_XXX
   3593  * Notes:
   3594  *      If using automedium, also switches the mode.
   3595  */
   3596 STATIC int
   3597 phy_bcm542xx_link_get(int unit, soc_port_t port, int *link)
   3598 {
   3599     phy_ctrl_t    *pc;
   3600     uint16         powerdown;
   3601     uint16  mii_stat, temp16;
   3602     pc    = EXT_PHY_SW_STATE(unit, port);
   3603     *link = FALSE;      /* Default return */
   3604 
   3605     if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE) ) {
   3606         return SOC_E_NONE;
   3607     }
   3608 
   3609     if (!pc->fiber.enable && !pc->copper.enable) {
   3610         return SOC_E_NONE;
   3611     }
   3612     
   3613     if ( PHY_IS_BCM54240(pc) || PHY_IS_BCM54285(pc) ) {
   3614         SOC_IF_ERROR_RETURN
   3615             (phy_bcm542xx_direct_reg_read(unit, pc,
   3616                           PHY_BCM542XX_OPER_MODE_STATUS_REG_OFFSET, &temp16));
   3617         if ( (!(temp16 & BIT(5))) && ((temp16 & 0x1f) == 0xb) ) {
   3618             /* no sync and in SGMII slave */
   3619             /* Disable auto-detection between SGMII-slave and 1000BASE-X
   3620                and set mode to 1000BASE-X */
   3621             SOC_IF_ERROR_RETURN
   3622                    (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 0, 0x3));
   3623             /* Now enable auto-detection between SGMII-slave and 1000BASE-X */
   3624             SOC_IF_ERROR_RETURN
   3625                     (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 1, 1));
   3626         }
   3627     }
   3628 
   3629     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_MEDIUM_CHANGE);
   3630     if ( pc->automedium) {
   3631         /* Check for medium change and update HW/SW accordingly. */
   3632         SOC_IF_ERROR_RETURN
   3633             (_phy_bcm542xx_medium_change(unit, port, SOC_PORT_MEDIUM_NONE));
   3634     }
   3635 
   3636     if ( PHY_COPPER_MODE(unit, port) ) {
   3637         SOC_IF_ERROR_RETURN(phy_fe_ge_link_get(unit, port, link));
   3638     } else if ( PHY_FIBER_MODE(unit, port) ) {
   3639         SOC_IF_ERROR_RETURN
   3640             (PHY_READ_BCM542XX_1000X_MII_STATr(unit, pc,&mii_stat));
   3641         *link = (mii_stat & PHY_BCM542XX_MII_STAT_LA) ? TRUE : FALSE;
   3642     } else {
   3643         return  SOC_E_INTERNAL;
   3644     }
   3645 
   3646     /* If preferred medium is up, disable the other medium to prevent false link. */
   3647     if ( pc->automedium ) {
   3648         if ( pc->copper.preferred ) {
   3649             if ( PHY_IS_BCM54210_220(pc) ) {
   3650                 /* don't power down fiber at 54220/210, it impacts traffic Tx/Rx */
   3651                 powerdown = 0;
   3652             } else if ( pc->fiber.enable ) {
   3653                 /* Power down Serdes if Copper mode is up */
   3654                 powerdown = (*link && PHY_COPPER_MODE(unit, port))
   3655                              ? PHY_BCM542XX_MII_CTRL_PWR_DOWN : 0;
   3656             } else {
   3657                 powerdown = PHY_BCM542XX_MII_CTRL_PWR_DOWN;
   3658 
   3659             }
   3660             SOC_IF_ERROR_RETURN
   3661                 (PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, powerdown, 
   3662                                                PHY_BCM542XX_MII_CTRL_PWR_DOWN));
   3663         } else {  /* pc->fiber.preferred */
   3664             if ( pc->copper.enable ) {
   3665                 powerdown = (*link && PHY_FIBER_MODE(unit, port))
   3666                              ? PHY_BCM542XX_MII_CTRL_PWR_DOWN : 0;
   3667             } else {
   3668                 powerdown = PHY_BCM542XX_MII_CTRL_PWR_DOWN;
   3669             }
   3670             SOC_IF_ERROR_RETURN
   3671                 (PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc, powerdown,
   3672                                                PHY_BCM542XX_MII_CTRL_PWR_DOWN));
   3673         }
   3674     } /* if ( automedium ) */
   3675 
   3676     LOG_VERBOSE(BSL_LS_SOC_PHY,
   3677                 (BSL_META_U(unit, "phy_bcm542xx_link_get: "
   3678                                   "u=%d p=%d mode=%s%s link=%d\n"),
   3679                  unit, port,
   3680                  PHY_COPPER_MODE(unit, port) ? "C" : "F",
   3681                  PHY_FIBER_100FX_MODE(unit, port)? "(100FX)" : "",
   3682                  *link));
   3683 
   3684     return SOC_E_NONE;
   3685 }
   3686 
   3687 
   3688 /*
   3689  * Function:
   3690  *      phy_bcm542xx_duplex_set
   3691  * Purpose:
   3692  *      Set the current duplex mode (forced).
   3693  * Parameters:
   3694  *      unit - StrataSwitch unit #.
   3695  *      port - StrataSwitch port #.
   3696  *      duplex - Boolean, true indicates full duplex, false indicates half.
   3697  * Returns:
   3698  *      SOC_E_NONE
   3699  *      SOC_E_UNAVAIL - Half duplex requested, and not supported.
   3700  * Notes:
   3701  *      The duplex is set only for the ACTIVE medium.
   3702  *      No synchronization performed at this level.
   3703  *      Autonegotiation is not manipulated.
   3704  */
   3705 
   3706 STATIC int
   3707 phy_bcm542xx_duplex_set(int unit, soc_port_t port, int duplex)
   3708 {
   3709     phy_ctrl_t  *pc;
   3710     uint16       data, is_duplex;
   3711 
   3712     pc = EXT_PHY_SW_STATE(unit, port);
   3713     is_duplex = (duplex == SOC_PORT_DUPLEX_FULL) ? TRUE : FALSE;
   3714     data = (is_duplex) ? PHY_BCM542XX_MII_CTRL_FD : 0;
   3715 
   3716     if ( PHY_COPPER_MODE(unit, port) ) {
   3717         SOC_IF_ERROR_RETURN(
   3718             PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc, data,
   3719                                     PHY_BCM542XX_MII_CTRL_FD) );
   3720         pc->copper.force_duplex = duplex;
   3721 
   3722     } else if ( PHY_FIBER_MODE(unit, port) ) {
   3723         SOC_IF_ERROR_RETURN(
   3724             PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, data,
   3725                                     PHY_BCM542XX_MII_CTRL_FD) );
   3726 
   3727         if ( PHY_FIBER_100FX_MODE(unit, port) ) {
   3728             data = (is_duplex) ? PHY_BCM542XX_100FX_CTRL_REG_FD_FX_SERDES : 0;
   3729             SOC_IF_ERROR_RETURN(
   3730                 phy_bcm542xx_direct_reg_modify(unit, pc,
   3731                                     PHY_BCM542XX_100FX_CTRL_REG_OFFSET, data,
   3732                                     PHY_BCM542XX_100FX_CTRL_REG_FD_FX_SERDES) );
   3733             if ( PHY_IS_BCM54210_220(pc) ) {
   3734                 data = (is_duplex) ? PHY_BCM542XX_EXT_SERDES_FX_FD : 0;
   3735                 /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */
   3736                 SOC_IF_ERROR_RETURN(
   3737                     PHY_MODIFY_BCM542XX_EXT_SERDES_CTRLr(unit, pc, data,
   3738                                     PHY_BCM542XX_EXT_SERDES_FX_FD) );
   3739             }
   3740             pc->fiber.force_duplex = duplex;
   3741         } else {    /* 1000BASE-X */
   3742             if ( ! is_duplex ) {    /* 1000X must be full-duplex */
   3743                 return SOC_E_UNAVAIL;
   3744             }
   3745         }
   3746 
   3747     } else {
   3748         return SOC_E_INTERNAL;
   3749     }
   3750     LOG_INFO(BSL_LS_SOC_PHY,
   3751           (BSL_META_U(unit, "phy_bcm542xx_duplex_set: u=%d p=%d d=%d\n"),
   3752           unit, port, duplex));
   3753     return ( SOC_E_NONE );
   3754 }
   3755 
   3756 /*
   3757  * Function:
   3758  *      phy_bcm542xx_duplex_get
   3759  * Purpose:
   3760  *      Get the current operating duplex mode. If autoneg is enabled,
   3761  *      then operating mode is returned, otherwise forced mode is returned.
   3762  * Parameters:
   3763  *      unit - StrataSwitch unit #.
   3764  *      port - StrataSwitch port #.
   3765  *      duplex - (OUT) Boolean, true indicates full duplex, false
   3766  *              indicates half.
   3767  * Returns:
   3768  *      SOC_E_NONE
   3769  * Notes:
   3770  *      The duplex is retrieved for the ACTIVE medium.
   3771  *      No synchronization performed at this level. Autonegotiation is
   3772  *      not manipulated.
   3773  */
   3774 
   3775 STATIC int
   3776 phy_bcm542xx_duplex_get(int unit, soc_port_t port, int *duplex)
   3777 {
   3778     int          rv = SOC_E_NONE;
   3779     phy_ctrl_t  *pc;
   3780     uint16       opt_mode;
   3781     uint16       mii_ctrl, mii_stat;
   3782 
   3783     pc = EXT_PHY_SW_STATE(unit, port);
   3784 
   3785     if ( PHY_FIBER_MODE(unit, port) ) {
   3786         *duplex = TRUE;
   3787     }
   3788 
   3789     if ( PHY_COPPER_MODE(unit, port) ) {
   3790         SOC_IF_ERROR_RETURN(
   3791             PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl));
   3792         SOC_IF_ERROR_RETURN(
   3793             PHY_READ_BCM542XX_MII_STATr(unit, pc,&mii_stat));
   3794 
   3795         if ( mii_ctrl & PHY_BCM542XX_MII_CTRL_AN_EN ) {        /* Auto-negotiation enabled */
   3796             if ( ! (mii_stat & PHY_BCM542XX_MII_STAT_AN_DONE) ) { /* Auto-neg NOT complete */
   3797                 *duplex = FALSE;
   3798             } else {
   3799                 uint16  misc_ctrl;
   3800                 SOC_IF_ERROR_RETURN(
   3801                     PHY_READ_BCM542XX_MII_MISC_CTRLr(unit, pc,&misc_ctrl));
   3802                 /* First check for Ethernet@Wirespeed */
   3803                 if ( misc_ctrl & BIT(4) ) {   /* Ethernet@Wirespeed enabled */
   3804                     rv = _phy_bcm542xx_auto_negotiate_ew(unit, pc, NULL, duplex);
   3805                 } else {
   3806                     rv = _phy_bcm542xx_auto_negotiate_gcd(unit, port, pc, NULL, duplex);
   3807                 }
   3808             }
   3809         } else {                           /* Auto-negotiation disabled */
   3810             *duplex = (mii_ctrl & PHY_BCM542XX_MII_CTRL_FD) ? TRUE : FALSE;
   3811         }
   3812 
   3813     } else if ( PHY_FIBER_MODE(unit, port) ) {    /* Fiber mode */
   3814         if ( PHY_FIBER_100FX_MODE(unit, port) ) {
   3815             SOC_IF_ERROR_RETURN
   3816                 (PHY_READ_BCM542XX_EXP_OPT_MODE_STATr(unit, pc,&opt_mode));
   3817             if ( opt_mode & PHY_BCM542XX_OPER_MODE_STATUS_SERDES_DUPLEX ) {
   3818                 *duplex = TRUE;
   3819             } else {
   3820                 *duplex = FALSE;
   3821             }
   3822         } else { /* 1000X */
   3823             *duplex = TRUE;
   3824         }
   3825 
   3826     } else {
   3827         return SOC_E_INTERNAL;
   3828     }
   3829     return rv;
   3830 }
   3831 
   3832 /*
   3833  * Function:
   3834  *      phy_bcm542xx_speed_set
   3835  * Purpose:
   3836  *      Set the current operating speed (forced).
   3837  * Parameters:
   3838  *      unit - StrataSwitch unit #.
   3839  *      port - StrataSwitch port #.
   3840  *      speed - Requested speed, only 1000 supported.
   3841  * Returns:
   3842  *      SOC_E_XXX
   3843  * Notes:
   3844  *      The speed is set only for the ACTIVE medium.
   3845  */
   3846 
   3847 STATIC int
   3848 phy_bcm542xx_speed_set(int unit, soc_port_t port, int speed)
   3849 {
   3850     phy_ctrl_t  *pc;
   3851     uint16       mii_ctrl = 0;
   3852     uint16  serdes_100fx_ctrl = 0x0;
   3853     uint16  serdes_100fx_ctrl_mask = PHY_BCM542XX_100FX_CTRL_REG_RX_QUALIFY_DIS;
   3854 #ifdef INCLUDE_PLP_IMACSEC
   3855     int speed_m;
   3856     unsigned int  port_m;
   3857     bcm_plp_base_t_sec_phy_access_t *imacsec_des;
   3858     uint16 imacsec_cfg;
   3859     soc_port_t port_s;
   3860     unsigned int speed_mask=0x3;
   3861 #endif
   3862     pc = EXT_PHY_SW_STATE(unit, port);
   3863 #ifdef INCLUDE_PLP_IMACSEC
   3864     imacsec_des = IMACSEC_DES_PTR_GET(pc);
   3865 #endif
   3866 
   3867 #ifdef INCLUDE_PLP_IMACSEC
   3868     if(pc->macsec_enable){
   3869         port_m = get_port(&imacsec_des->phy_info);
   3870         SPEED_MAPPING(speed,speed_m);
   3871         /* Use base phy id to write top register */
   3872         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   3873         /* SW set speed MACSEC_CONFIG2 reg */
   3874         SOC_IF_ERROR_RETURN
   3875             (phy_bcm542xx_cl45_reg_read(unit, pc,  0x7, 0x9870, &imacsec_cfg));
   3876         imacsec_cfg |= 1<<port_m;
   3877         SOC_IF_ERROR_RETURN
   3878             (phy_bcm542xx_cl45_reg_write(unit, pc,  0x7, 0x9870, imacsec_cfg));
   3879         /* SW set speed MACSEC_CONFIG3 reg */
   3880         SOC_IF_ERROR_RETURN
   3881             (phy_bcm542xx_cl45_reg_read(unit, pc,  0x7, 0x9871, &imacsec_cfg));
   3882         imacsec_cfg &= ~(speed_mask << (port_m*2));
   3883         imacsec_cfg |= (speed_m << (port_m*2));
   3884         SOC_IF_ERROR_RETURN
   3885           (phy_bcm542xx_cl45_reg_write(unit, pc,  0x7, 0x9871, imacsec_cfg));
   3886         /* Restore the phy mdio address */
   3887         pc->phy_id =  PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   3888 
   3889         port_s= PHY_UNIMAC_V2_SWITCH_PORT(port);
   3890         SOC_IF_ERROR_RETURN(
   3891            BMACSEC_MAC_AUTO_CONFIG_SET((phy_mac_ctrl_t *)imacsec_des->unimac, port_s, 0));
   3892 
   3893         SOC_IF_ERROR_RETURN(
   3894         BMACSEC_MAC_AUTO_CONFIG_SET((phy_mac_ctrl_t *)imacsec_des->unimac, port_s, 1));
   3895      }
   3896 #endif
   3897     /* get current MII control Register */
   3898     if ( PHY_COPPER_MODE(unit, port) ) {  /* copper mode */
   3899         SOC_IF_ERROR_RETURN(
   3900             PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl) );
   3901     } else {                              /* fiber mode */
   3902         if ( speed == 10 ) {
   3903             return SOC_E_UNAVAIL;   /* nehter 1000Base-X nor 100Base-FX */
   3904         }
   3905         SOC_IF_ERROR_RETURN(
   3906             PHY_READ_BCM542XX_1000X_MII_CTRLr(unit, pc,&mii_ctrl) );
   3907     }
   3908     /* mask off the Speed Selection bit[6,13] */
   3909     mii_ctrl &= ~(PHY_BCM542XX_MII_CTRL_SS_LSB | PHY_BCM542XX_MII_CTRL_SS_MSB);
   3910 
   3911     switch ( speed ) {
   3912     case  10:
   3913         mii_ctrl |= PHY_BCM542XX_MII_CTRL_SS_10;
   3914         break;
   3915     case  100:
   3916         mii_ctrl |= PHY_BCM542XX_MII_CTRL_SS_100;
   3917         serdes_100fx_ctrl      = (PHY_IS_BCM54210_220(pc)) ?  0  :
   3918                                   PHY_BCM542XX_100FX_CTRL_REG_FX_SERDES_EN;
   3919         serdes_100fx_ctrl_mask |= PHY_BCM542XX_100FX_CTRL_REG_FX_SERDES_EN |
   3920                                   PHY_BCM542XX_100FX_CTRL_REG_FD_FX_SERDES;
   3921         if ( pc->fiber.force_duplex)  {
   3922             serdes_100fx_ctrl  |= PHY_BCM542XX_100FX_CTRL_REG_FD_FX_SERDES;
   3923         }
   3924         break;
   3925     case  1000:
   3926         mii_ctrl |= PHY_BCM542XX_MII_CTRL_SS_1000;
   3927         serdes_100fx_ctrl_mask |= PHY_BCM542XX_100FX_CTRL_REG_FX_SERDES_EN;
   3928         break;
   3929     default:
   3930         return SOC_E_CONFIG;
   3931     }
   3932 
   3933     if ( PHY_COPPER_MODE(unit, port) ) {  /* COPPER mode */
   3934         SOC_IF_ERROR_RETURN(
   3935             PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, mii_ctrl) );
   3936         pc->copper.force_speed = speed;
   3937 
   3938     } else {                              /* FIBER  mode */
   3939         if ( speed == 100 ) {
   3940             /* Disable autoneg for 100Base-FX speed */ 
   3941             pc->fiber.autoneg_enable = FALSE;
   3942             if ( PHY_IS_BCM54140(pc) || PHY_IS_BCM54194(pc) ||
   3943                  PHY_IS_BCM54185(pc) || PHY_IS_BCM54195(pc)  ) {
   3944                 /* turn on RX_QUALIFY_DIS for 28nm SerDes AFE, RDB.0x233[5] */
   3945                 serdes_100fx_ctrl |= PHY_BCM542XX_100FX_CTRL_REG_RX_QUALIFY_DIS;
   3946             }
   3947         }
   3948         /* Select 1000x/100fx and duplexity in case of 100fx */ 
   3949         /* SERDES 100BASE-FX Control Reg., DIGX_SHD_1C_13, RDB_0x233 */
   3950         SOC_IF_ERROR_RETURN(
   3951             phy_bcm542xx_direct_reg_modify(unit, pc,
   3952                                  PHY_BCM542XX_100FX_CTRL_REG_OFFSET,
   3953                                  serdes_100fx_ctrl, serdes_100fx_ctrl_mask) );
   3954 
   3955         if ( pc->fiber.autoneg_enable ) {
   3956             mii_ctrl |= MII_CTRL_AE | MII_CTRL_RAN | MII_CTRL_FD;
   3957         } else {
   3958             mii_ctrl |= MII_CTRL_FD;
   3959         }
   3960 
   3961         if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE) ) {
   3962             mii_ctrl |= PHY_BCM542XX_MII_CTRL_PWR_DOWN; 
   3963         }
   3964         SOC_IF_ERROR_RETURN(
   3965             PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, mii_ctrl) );
   3966       
   3967         if ( speed == 100 ) {
   3968             if ( PHY_IS_BCM54210_220(pc) ) {
   3969                 /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */
   3970                 SOC_IF_ERROR_RETURN(
   3971                     PHY_MODIFY_BCM542XX_EXT_SERDES_CTRLr(unit, pc,
   3972                                               PHY_BCM542XX_EXT_SERDES_FX,
   3973                                               PHY_BCM542XX_EXT_SERDES_FX_MASK) );
   3974             }
   3975             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   3976             PHY_FLAGS_SET(unit, port, PHY_FLAGS_100FX);
   3977         }
   3978         /* Enforce duplexity to full for 1000X */
   3979         if ( speed == 1000 ) {
   3980             if ( PHY_IS_BCM54210_220(pc) ) {
   3981                 /* 54220_210_B0 don't support PHY_BCM542XX_EXT_SERDES_AUTO_FX, */
   3982                 /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */
   3983                 SOC_IF_ERROR_RETURN(
   3984                     PHY_MODIFY_BCM542XX_EXT_SERDES_CTRLr(unit, pc, 0,
   3985                                               PHY_BCM542XX_EXT_SERDES_FX_MASK) );
   3986             }
   3987             pc->fiber.force_duplex = TRUE;
   3988             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   3989             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
   3990         }
   3991 
   3992         pc->fiber.force_speed = speed;
   3993     }
   3994     LOG_INFO(BSL_LS_SOC_PHY,
   3995              (BSL_META_U(unit,
   3996                          "phy_bcm542xx_speed_set: u=%d p=%d s=%d fiber=%d\n"),
   3997               unit, port, speed, PHY_FIBER_MODE(unit, port)));
   3998     return ( SOC_E_NONE );
   3999 }
   4000 
   4001 /*
   4002  * Function:
   4003  *      phy_bcm542xx_speed_get
   4004  * Purpose:
   4005  *      Get the current operating speed for a bcm542xx device.
   4006  * Parameters:
   4007  *      unit - StrataSwitch unit #.
   4008  *      port - StrataSwitch port #.
   4009  *      duplex - (OUT) Boolean, true indicates full duplex, false
   4010  *              indicates half.
   4011  * Returns:
   4012  *      SOC_E_NONE
   4013  * Notes:
   4014  *      The speed is retrieved for the ACTIVE medium.
   4015  */
   4016 
   4017 STATIC int
   4018 phy_bcm542xx_speed_get(int unit, soc_port_t port, int *speed)
   4019 {
   4020     phy_ctrl_t  *pc;
   4021     uint16       mii_ctrl, mii_aux_stat, temp16;
   4022 #ifdef INCLUDE_PLP_IMACSEC  
   4023     int speed_m;
   4024     bcm_plp_base_t_sec_phy_access_t *imacsec_des;
   4025 #endif
   4026     pc = EXT_PHY_SW_STATE(unit, port);
   4027 #ifdef INCLUDE_PLP_IMACSEC
   4028     imacsec_des = IMACSEC_DES_PTR_GET(pc);
   4029 #endif
   4030 
   4031     if ( PHY_COPPER_MODE(unit, port) ) {
   4032         SOC_IF_ERROR_RETURN(
   4033             PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl));
   4034 
   4035         if ( mii_ctrl & PHY_BCM542XX_MII_CTRL_AN_EN ) {  /* Auto-negotiation enabled */
   4036             SOC_IF_ERROR_RETURN(
   4037                     PHY_READ_BCM542XX_MII_AUX_STATUSr(unit, pc,&mii_aux_stat));
   4038 
   4039             if ( ! (mii_aux_stat & PHY_BCM542XX_MII_ASSR_ANC) ) {
   4040                 /* Auto-neg NOT complete */
   4041                 *speed = 0;
   4042             } else {
   4043                 switch ( mii_aux_stat & PHY_BCM542XX_MII_ASSR_AUTONEG_HCD_MASK ) {
   4044                 case PHY_BCM542XX_MII_ASSR_HCD_FD_1000:
   4045                 case PHY_BCM542XX_MII_ASSR_HCD_HD_1000:
   4046                     *speed = 1000;
   4047                 break;
   4048                 case PHY_BCM542XX_MII_ASSR_HCD_FD_100:
   4049                 case PHY_BCM542XX_MII_ASSR_HCD_HD_100:
   4050                 case PHY_BCM542XX_MII_ASSR_HCD_T4_100:
   4051                     *speed = 100;
   4052                     break;
   4053                 case PHY_BCM542XX_MII_ASSR_HCD_FD_10:
   4054                 case PHY_BCM542XX_MII_ASSR_HCD_HD_10:
   4055                     *speed = 10;
   4056                     break;
   4057                 default:
   4058                     *speed = 0;
   4059                 }
   4060             }
   4061         } else {    /* Auto-negotiation disabled */
   4062             /* Pick up the values we force in CTRL register */
   4063             switch(PHY_BCM542XX_MII_CTRL_SS(mii_ctrl) ) {
   4064             case PHY_BCM542XX_MII_CTRL_SS_10:
   4065                 *speed = 10;
   4066                 break;
   4067             case PHY_BCM542XX_MII_CTRL_SS_100:
   4068                 *speed = 100;
   4069                 break;
   4070             case PHY_BCM542XX_MII_CTRL_SS_1000:
   4071                 *speed = 1000;
   4072                 break;
   4073             default:   /* Pass error back */
   4074                 return SOC_E_UNAVAIL;
   4075             }
   4076         }
   4077 
   4078     } else if ( PHY_FIBER_MODE(unit, port) ) {
   4079         if (pc->ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS && 
   4080             pc->ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_SGMII) {
   4081             SOC_IF_ERROR_RETURN(
   4082                 PHY_READ_BCM542XX_SGMII_SLAVEr(unit, pc, &temp16));
   4083             switch ( temp16 & PHY_BCM542XX_SGMII_SPEED )  {
   4084             case PHY_BCM542XX_SGMII_SPEED_10:
   4085                 *speed = 10;
   4086                 break;
   4087             case PHY_BCM542XX_SGMII_SPEED_100:
   4088                 *speed = 100;
   4089                 break;
   4090             case PHY_BCM542XX_SGMII_SPEED_1000:
   4091                 *speed = 1000;
   4092                 break;
   4093             default:
   4094                 return SOC_E_UNAVAIL;
   4095             }
   4096         } else {
   4097             phy_bcm542xx_direct_reg_read(unit, pc,
   4098                     PHY_BCM542XX_OPER_MODE_STATUS_REG_OFFSET, &temp16);
   4099             switch ( temp16 & PHY_BCM542XX_OPER_MODE_STATUS_REG_SERDES_SPEED )  {
   4100             case PHY_BCM542XX_OPER_MODE_STATUS_SERDES_SPEED_10:
   4101                 *speed = 10;
   4102                 break;
   4103             case PHY_BCM542XX_OPER_MODE_STATUS_SERDES_SPEED_100:
   4104                 *speed = 100;
   4105                 break;
   4106             case PHY_BCM542XX_OPER_MODE_STATUS_SERDES_SPEED_1000:
   4107                 *speed = 1000;
   4108                 break;
   4109             default:
   4110                 return SOC_E_UNAVAIL;
   4111             }
   4112         }
   4113     } else {
   4114         return SOC_E_INTERNAL;
   4115     }
   4116 #ifdef INCLUDE_PLP_IMACSEC
   4117     if(pc->macsec_enable){  
   4118         SOC_IF_ERROR_RETURN(
   4119           BMACSEC_MAC_SPEED_GET((phy_mac_ctrl_t *)imacsec_des->unimac, port, &speed_m));
   4120         if(*speed !=0 && *speed == speed_m){
   4121             LOG_INFO(BSL_LS_SOC_PHY,
   4122                (BSL_META_U(unit, "phy_bcm542xx_speed_get: u=%d p=%d sp=%d\n"),
   4123                  unit, port, speed_m));
   4124    
   4125            return ( SOC_E_NONE );
   4126         }
   4127     }
   4128 #endif
   4129     LOG_INFO(BSL_LS_SOC_PHY,
   4130              (BSL_META_U(unit, "phy_bcm542xx_speed_get: u=%d p=%d sp=%d\n"),
   4131               unit, port, *speed));
   4132    
   4133     return ( SOC_E_NONE );
   4134 }
   4135 
   4136 /*
   4137  * Function:
   4138  *      phy_bcm542xx_master_set
   4139  * Purpose:
   4140  *      Set the current master mode
   4141  * Parameters:
   4142  *      unit - StrataSwitch unit #.
   4143  *      port - StrataSwitch port #.
   4144  *      master - SOC_PORT_MS_*
   4145  * Returns:
   4146  *      SOC_E_XXX
   4147  * Notes:
   4148  *      The master mode is set only for the ACTIVE medium.
   4149  */
   4150 STATIC int
   4151 phy_bcm542xx_master_set(int unit, soc_port_t port, int master)
   4152 {
   4153     phy_ctrl_t  *pc;
   4154     uint16       mii_gb_ctrl;
   4155 
   4156     pc = EXT_PHY_SW_STATE(unit, port);
   4157 
   4158     if ( PHY_COPPER_MODE(unit, port) ) {
   4159         SOC_IF_ERROR_RETURN(
   4160             PHY_READ_BCM542XX_MII_GB_CTRLr(unit, pc,&mii_gb_ctrl));
   4161         switch (master) {
   4162         case SOC_PORT_MS_SLAVE:
   4163             mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_MS_MAN;
   4164             mii_gb_ctrl &= ~PHY_BCM542XX_MII_GB_CTRL_MS;
   4165             break;
   4166         case SOC_PORT_MS_MASTER:
   4167             mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_MS_MAN;
   4168             mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_MS;
   4169             break;
   4170         case SOC_PORT_MS_AUTO:
   4171             mii_gb_ctrl &= ~PHY_BCM542XX_MII_GB_CTRL_MS_MAN;
   4172             break;
   4173         case SOC_PORT_MS_NONE:
   4174             break;
   4175         default:
   4176             return SOC_E_CONFIG;
   4177         }
   4178 
   4179         SOC_IF_ERROR_RETURN(
   4180             PHY_WRITE_BCM542XX_MII_GB_CTRLr(unit, pc, mii_gb_ctrl) );
   4181         pc->copper.master = master;
   4182     }
   4183 
   4184     LOG_INFO(BSL_LS_SOC_PHY,
   4185              (BSL_META_U(unit, "phy_bcm542xx_master_set: "
   4186                                "u=%d p=%d master=%d fiber=%d\n"),
   4187               unit, port, master, PHY_FIBER_MODE(unit, port)));
   4188     return ( SOC_E_NONE );
   4189 }
   4190 
   4191 /*
   4192  * Function:
   4193  *      phy_bcm542xx_master_get
   4194  * Purpose:
   4195  *      Get the current master mode for a bcm542xx device.
   4196  * Parameters:
   4197  *      unit - StrataSwitch unit #.
   4198  *      port - StrataSwitch port #.
   4199  *      master - (OUT) SOC_PORT_MS_*
   4200  * Returns:
   4201  *      SOC_E_NONE
   4202  * Notes:
   4203  *      The master mode is retrieved for the ACTIVE medium.
   4204  */
   4205 
   4206 STATIC int
   4207 phy_bcm542xx_master_get(int unit, soc_port_t port, int *master)
   4208 {
   4209     phy_ctrl_t *pc;
   4210     uint16      mii_gb_ctrl;
   4211     
   4212     pc = EXT_PHY_SW_STATE(unit, port);
   4213 
   4214     if ( PHY_COPPER_MODE(unit, port) ) {
   4215         SOC_IF_ERROR_RETURN(
   4216             PHY_READ_BCM542XX_MII_GB_CTRLr(unit, pc,&mii_gb_ctrl) );
   4217 
   4218         if ( ! (mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_MS_MAN) ) {
   4219             *master = SOC_PORT_MS_AUTO;
   4220         } else if ( mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_MS ) {
   4221             *master = SOC_PORT_MS_MASTER;
   4222         } else {
   4223             *master = SOC_PORT_MS_SLAVE;
   4224         }
   4225 
   4226     } else if ( PHY_FIBER_MODE(unit, port) ) {
   4227         *master = SOC_PORT_MS_NONE;
   4228 
   4229     } else {
   4230         return SOC_E_INTERNAL;
   4231     }
   4232 
   4233     return ( SOC_E_NONE );
   4234 }
   4235 
   4236 /*
   4237  * Function:
   4238  *      phy_bcm542xx_autoneg_set
   4239  * Purpose:
   4240  *      Enable or disable auto-negotiation on the specified port.
   4241  * Parameters:
   4242  *      unit - StrataSwitch unit #.
   4243  *      port - StrataSwitch port #.
   4244  *      autoneg - Boolean, if true, auto-negotiation is enabled
   4245  *              (and/or restarted). If false, autonegotiation is disabled.
   4246  * Returns:
   4247  *      SOC_E_XXX
   4248  * Notes:
   4249  *      The autoneg mode is set only for the ACTIVE medium.
   4250  */
   4251 
   4252 STATIC int
   4253 phy_bcm542xx_autoneg_set(int unit, soc_port_t port, int autoneg)
   4254 {
   4255     phy_ctrl_t  *pc;
   4256     uint16       mii_ctrl;
   4257     pc = EXT_PHY_SW_STATE(unit, port);
   4258 
   4259     if ( PHY_COPPER_MODE(unit, port) ) {
   4260         SOC_IF_ERROR_RETURN(
   4261             PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl));
   4262 
   4263         if (autoneg) {
   4264             mii_ctrl |= PHY_BCM542XX_MII_CTRL_AN_EN | PHY_BCM542XX_MII_CTRL_RST_AN;
   4265         } else {
   4266             mii_ctrl &= ~(PHY_BCM542XX_MII_CTRL_AN_EN | PHY_BCM542XX_MII_CTRL_RST_AN);
   4267         }
   4268         SOC_IF_ERROR_RETURN(
   4269                 PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, mii_ctrl));
   4270         
   4271         pc->copper.autoneg_enable = autoneg ? TRUE : FALSE;
   4272 
   4273     } else if ( PHY_FIBER_MODE(unit, port) ) {
   4274         if (PHY_FIBER_100FX_MODE(unit, port)) {
   4275             /* 100FX mode doesn't support autoneg*/
   4276             autoneg = 0;
   4277         }
   4278         if ( autoneg ) {
   4279            /* When enabling autoneg, set the default speed to 1000Mbps first.
   4280              * PHY will not enable autoneg if the PHY is in 100FX mode.
   4281              */
   4282             SOC_IF_ERROR_RETURN
   4283                (phy_bcm542xx_speed_set(unit, port, 1000));
   4284         }
   4285 
   4286         /* Disable/Enable auto-detection between SGMII-slave and 1000BASE-X */
   4287         /* don't change SGMII_SLAVE_AUTO_DET at 54220/210, it impacts traffic Tx/Rx */
   4288         if ( ! PHY_IS_BCM54210_220(pc) ) {
   4289             if (pc->fiber.preferred && pc->ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS) {
   4290                 /* SGMII Slave Register, DIGX_SHD1C_15 bit[1] SGMII_SLAVE_AUTO_DET*/
   4291                 SOC_IF_ERROR_RETURN(
   4292                     PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 0,
   4293                     PHY_BCM542XX_SGMII_SLAVE_AUTO) );
   4294             } else {
   4295                 /* SGMII Slave Register, DIGX_SHD1C_15 bit[0] SGMII_SLAVE_AUTO_DET*/
   4296                 SOC_IF_ERROR_RETURN(
   4297                     PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc,(autoneg ? 1 : 0), 1) );
   4298             }
   4299         }
   4300 
   4301         SOC_IF_ERROR_RETURN(
   4302             phy_bcm542xx_ability_advert_set(unit, port, &pc->fiber.advert_ability) );
   4303 
   4304         SOC_IF_ERROR_RETURN(
   4305             PHY_READ_BCM542XX_1000X_MII_CTRLr(unit, pc,&mii_ctrl) );
   4306 
   4307         if ( autoneg ) {
   4308             mii_ctrl |=   PHY_BCM542XX_MII_CTRL_AN_EN | PHY_BCM542XX_MII_CTRL_RST_AN;
   4309         } else {
   4310             mii_ctrl &= ~(PHY_BCM542XX_MII_CTRL_AN_EN | PHY_BCM542XX_MII_CTRL_RST_AN);
   4311         }
   4312         SOC_IF_ERROR_RETURN(
   4313                 PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, mii_ctrl) );
   4314 
   4315         pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE;
   4316 
   4317     } else {
   4318         return SOC_E_INTERNAL;
   4319     }
   4320 
   4321     LOG_INFO(BSL_LS_SOC_PHY,
   4322              (BSL_META_U(unit,
   4323                          "phy_bcm542xx_autoneg_set: u=%d p=%d autoneg=%d\n"),
   4324               unit, port, autoneg));
   4325     return ( SOC_E_NONE );
   4326 }
   4327 
   4328 /*
   4329  * Function:
   4330  *      phy_bcm542xx_autoneg_get
   4331  * Purpose:
   4332  *      Get the current auto-negotiation status (enabled/busy).
   4333  * Parameters:
   4334  *      unit - StrataSwitch unit #.
   4335  *      port - StrataSwitch port #.
   4336  *      autoneg - (OUT) if true, auto-negotiation is enabled.
   4337  *      autoneg_done - (OUT) if true, auto-negotiation is complete. This
   4338  *              value is undefined if autoneg == FALSE.
   4339  * Returns:
   4340  *      SOC_E_XXX
   4341  * Notes:
   4342  *      The autoneg mode is retrieved for the ACTIVE medium.
   4343  */
   4344 
   4345 STATIC int
   4346 phy_bcm542xx_autoneg_get(int unit, soc_port_t port,
   4347                          int *autoneg, int *autoneg_done)
   4348 {
   4349     phy_ctrl_t   *pc;
   4350     uint16 mii_ctrl, mii_stat;
   4351 
   4352     pc = EXT_PHY_SW_STATE(unit, port);
   4353 
   4354     *autoneg      = FALSE;
   4355     *autoneg_done = FALSE;
   4356 
   4357     if ( PHY_COPPER_MODE(unit, port) ) {
   4358         SOC_IF_ERROR_RETURN(
   4359             PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl) );
   4360         SOC_IF_ERROR_RETURN(
   4361             PHY_READ_BCM542XX_MII_STATr(unit, pc,&mii_stat) );
   4362 
   4363         *autoneg      = (mii_ctrl & PHY_BCM542XX_MII_CTRL_AN_EN)   ? 1 : 0;
   4364         *autoneg_done = (mii_stat & PHY_BCM542XX_MII_STAT_AN_DONE) ? 1 : 0;
   4365 
   4366     } else if ( PHY_FIBER_MODE(unit, port) ) {
   4367         /* autoneg is not enabled in 100FX mode */
   4368         if ( PHY_FIBER_100FX_MODE(unit, port) ) {
   4369             *autoneg      = FALSE;
   4370             *autoneg_done = TRUE;
   4371         } else {
   4372             SOC_IF_ERROR_RETURN(
   4373                 PHY_READ_BCM542XX_1000X_MII_CTRLr(unit, pc,&mii_ctrl) );
   4374             SOC_IF_ERROR_RETURN(
   4375                 PHY_READ_BCM542XX_1000X_MII_STATr(unit, pc,&mii_stat) );
   4376 
   4377             *autoneg      = (mii_ctrl & PHY_BCM542XX_MII_CTRL_AN_EN)   ? 1 : 0;
   4378             *autoneg_done = (mii_stat & PHY_BCM542XX_MII_STAT_AN_DONE) ? 1 : 0;
   4379         }
   4380 
   4381     } else {
   4382         return SOC_E_INTERNAL;
   4383     }
   4384 
   4385     return ( SOC_E_NONE );
   4386 }
   4387 
   4388 /*
   4389  * Function:
   4390  *      phy_bcm542xx_ability_advert_set
   4391  * Purpose:
   4392  *      Set the current advertisement for auto-negotiation.
   4393  * Parameters:
   4394  *      unit - StrataSwitch unit #.
   4395  *      port - StrataSwitch port #.
   4396  *      mode - Port mode mask indicating supported options/speeds.
   4397  * Returns:
   4398  *      SOC_E_XXX
   4399  * Notes:
   4400  *      The advertisement is set only for the ACTIVE medium.
   4401  *      No synchronization performed at this level.
   4402  */
   4403 STATIC int
   4404 phy_bcm542xx_ability_advert_set(int unit, soc_port_t port,
   4405                                 soc_port_ability_t *ability)
   4406 {
   4407     phy_ctrl_t  *pc;
   4408     uint16       mii_adv, mii_gb_ctrl;
   4409 
   4410     pc = EXT_PHY_SW_STATE(unit, port);
   4411 
   4412     if ( PHY_COPPER_MODE(unit, port) ) {
   4413         mii_adv = PHY_BCM542XX_MII_ANA_ASF_802_3;
   4414         SOC_IF_ERROR_RETURN
   4415             (PHY_READ_BCM542XX_MII_GB_CTRLr(unit, pc,&mii_gb_ctrl));
   4416 
   4417         mii_gb_ctrl &= ~(PHY_BCM542XX_MII_GB_CTRL_ADV_1000HD |
   4418                          PHY_BCM542XX_MII_GB_CTRL_ADV_1000FD);
   4419         mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_PT; /* repeater / switch port */
   4420 
   4421         if ( (ability->speed_half_duplex) & SOC_PA_SPEED_10MB ) {
   4422             mii_adv |= PHY_BCM542XX_MII_ANA_HD_10;
   4423         }
   4424         if ( (ability->speed_full_duplex) & SOC_PA_SPEED_10MB ) {
   4425             mii_adv |= PHY_BCM542XX_MII_ANA_FD_10;
   4426         }
   4427         if ( (ability->speed_half_duplex) & SOC_PA_SPEED_100MB ) {
   4428             mii_adv |= PHY_BCM542XX_MII_ANA_HD_100;
   4429         }
   4430         if ( (ability->speed_full_duplex) & SOC_PA_SPEED_100MB ) {
   4431             mii_adv |= PHY_BCM542XX_MII_ANA_FD_100;
   4432         }
   4433         if ( (ability->speed_half_duplex) & SOC_PA_SPEED_1000MB ) {
   4434             mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_ADV_1000HD;
   4435         }
   4436         if ( (ability->speed_full_duplex) & SOC_PA_SPEED_1000MB ) {
   4437             mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_ADV_1000FD;
   4438         }
   4439 
   4440         if ( ((ability->pause) & SOC_PA_PAUSE) == SOC_PA_PAUSE ) {
   4441             /* Advertise symmetric pause */
   4442             mii_adv |= PHY_BCM542XX_MII_ANA_PAUSE;
   4443         } else {
   4444             if ( (ability->pause) & SOC_PA_PAUSE_TX ) {
   4445                 mii_adv |= PHY_BCM542XX_MII_ANA_ASYM_PAUSE;
   4446             } else { 
   4447                 if ( (ability->pause) & SOC_PA_PAUSE_RX ) {
   4448                     mii_adv |= PHY_BCM542XX_MII_ANA_ASYM_PAUSE;
   4449                     mii_adv |= PHY_BCM542XX_MII_ANA_PAUSE;
   4450                 }
   4451             }
   4452         }
   4453 
   4454         SOC_IF_ERROR_RETURN
   4455             (PHY_WRITE_BCM542XX_MII_ANAr(unit, pc, mii_adv));
   4456         SOC_IF_ERROR_RETURN
   4457             (PHY_WRITE_BCM542XX_MII_GB_CTRLr(unit, pc, mii_gb_ctrl));
   4458 
   4459         /* EEE advertisement settings */
   4460         if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   4461             uint16 eee_ability = 0;
   4462             if (ability->eee & SOC_PA_EEE_10GB_BASET) {
   4463                 eee_ability |= PHY_BCM542XX_EEE_ADV_10G;
   4464             }
   4465             if (ability->eee & SOC_PA_EEE_1GB_BASET) {
   4466                 eee_ability |= PHY_BCM542XX_EEE_ADV_1000;
   4467             }
   4468             if (ability->eee & SOC_PA_EEE_100MB_BASETX) {
   4469                 eee_ability |= PHY_BCM542XX_EEE_ADV_100;
   4470             }
   4471             SOC_IF_ERROR_RETURN
   4472                 (PHY_MODIFY_BCM542XX_EEE_ADVr(unit, pc, eee_ability,
   4473                                               PHY_BCM542XX_EEE_ADV_MASK));
   4474         }
   4475 
   4476         /* update the PHY property software table (phy_ctrl_t) */
   4477         sal_memcpy( &(pc->copper.advert_ability), ability,
   4478                     sizeof(soc_port_ability_t) );
   4479 
   4480     } else if ( PHY_FIBER_MODE(unit, port) ) {
   4481         mii_adv = PHY_BCM542XX_MII_ANA_C37_FD;  /* Always advertise 1000X full duplex */
   4482         switch ( ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX) ) {
   4483         case SOC_PA_PAUSE_TX:
   4484             mii_adv |= PHY_BCM542XX_MII_ANA_C37_ASYM_PAUSE;
   4485             break;
   4486         case SOC_PA_PAUSE_RX:
   4487             mii_adv |= (PHY_BCM542XX_MII_ANA_C37_ASYM_PAUSE |
   4488                         PHY_BCM542XX_MII_ANA_C37_PAUSE);
   4489             break;
   4490         case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   4491             mii_adv |= PHY_BCM542XX_MII_ANA_C37_PAUSE;
   4492             break;
   4493         }
   4494         /* Write to SerDes Auto-Neg Advertisement Reg */
   4495         SOC_IF_ERROR_RETURN
   4496             (PHY_WRITE_BCM542XX_1000X_MII_ANAr(unit, pc, mii_adv));
   4497 
   4498         /* update the PHY property software table (phy_ctrl_t) */
   4499         sal_memcpy( &(pc->fiber.advert_ability), ability,
   4500                     sizeof(soc_port_ability_t) );
   4501     } else {
   4502         return SOC_E_INTERNAL;
   4503     }
   4504 
   4505     LOG_INFO(BSL_LS_SOC_PHY,
   4506              (BSL_META_U(unit, "phy_bcm542xx_adv_local_set: u=%d p=%d "
   4507                                "ability_hd_speed=0x%x, ability_fd_speed=0x%x, "
   4508                                "ability_pause=0x%x\n"),
   4509               unit, port, ability->speed_half_duplex, ability->speed_full_duplex,
   4510               ability->pause));
   4511     return ( SOC_E_NONE );
   4512 }
   4513 
   4514 /*
   4515  * Function:
   4516  *      phy_bcm542xx_ability_advert_get
   4517  * Purpose:
   4518  *      Get the current advertisement for auto-negotiation.
   4519  * Parameters:
   4520  *      unit - StrataSwitch unit #.
   4521  *      port - StrataSwitch port #.
   4522  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   4523  * Returns:
   4524  *      SOC_E_XXX
   4525  * Notes:
   4526  *      The advertisement is retrieved for the ACTIVE medium.
   4527  *      No synchronization performed at this level.
   4528  */
   4529 
   4530 STATIC int
   4531 phy_bcm542xx_ability_advert_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   4532 {
   4533     phy_ctrl_t  *pc;
   4534     uint16       mii_ana, mii_gb_ctrl, mii_adv;
   4535 
   4536     if ( NULL == ability ) {
   4537         return SOC_E_PARAM;
   4538     }
   4539     sal_memset(ability, 0,  sizeof(soc_port_ability_t)); /* zero initialize */
   4540     
   4541     pc = EXT_PHY_SW_STATE(unit, port);
   4542 
   4543     if ( PHY_COPPER_MODE(unit, port) ) {
   4544         SOC_IF_ERROR_RETURN
   4545             (PHY_READ_BCM542XX_MII_ANAr(unit, pc,&mii_ana));
   4546         SOC_IF_ERROR_RETURN
   4547             (PHY_READ_BCM542XX_MII_GB_CTRLr(unit, pc,&mii_gb_ctrl));
   4548 
   4549         if ( mii_ana & PHY_BCM542XX_MII_ANA_HD_10 ) {
   4550             ability->speed_half_duplex |= SOC_PA_SPEED_10MB;
   4551         }
   4552         if ( mii_ana & PHY_BCM542XX_MII_ANA_FD_10 ) {
   4553             ability->speed_full_duplex |= SOC_PA_SPEED_10MB;
   4554         }
   4555         if ( mii_ana & PHY_BCM542XX_MII_ANA_HD_100 ) {
   4556             ability->speed_half_duplex |= SOC_PA_SPEED_100MB;
   4557         }
   4558         if ( mii_ana & PHY_BCM542XX_MII_ANA_FD_100 ) {
   4559             ability->speed_full_duplex |= SOC_PA_SPEED_100MB;
   4560         }
   4561 
   4562         if ( mii_ana & PHY_BCM542XX_MII_ANA_ASYM_PAUSE ) {
   4563             if ( mii_ana & PHY_BCM542XX_MII_ANA_PAUSE ) {
   4564                 ability->pause |= SOC_PA_PAUSE_RX;
   4565             } else {
   4566                 ability->pause |= SOC_PA_PAUSE_TX;
   4567             }
   4568         } else if (mii_ana & PHY_BCM542XX_MII_ANA_PAUSE ) {
   4569             ability->pause |= SOC_PA_PAUSE;
   4570         }
   4571 
   4572         /* GE Specific values */
   4573         if ( mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_ADV_1000FD ) {
   4574             ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   4575         }
   4576         if ( mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_ADV_1000HD ) {
   4577             ability->speed_half_duplex |= SOC_PA_SPEED_1000MB;
   4578         }
   4579         /* EEE advertisement settings */
   4580         if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   4581             uint16 eee_ability;
   4582             SOC_IF_ERROR_RETURN
   4583                 (PHY_READ_BCM542XX_EEE_ADVr(unit, pc, &eee_ability));
   4584             if (eee_ability & PHY_BCM542XX_EEE_ADV_10G) {
   4585                 ability->eee |= SOC_PA_EEE_10GB_BASET;
   4586             }
   4587             if (eee_ability & PHY_BCM542XX_EEE_ADV_1000) {
   4588                 ability->eee |= SOC_PA_EEE_1GB_BASET;
   4589             }
   4590             if (eee_ability & PHY_BCM542XX_EEE_ADV_100) {
   4591                 ability->eee |= SOC_PA_EEE_100MB_BASETX;
   4592             }
   4593         }
   4594 
   4595     } else if ( PHY_FIBER_MODE(unit, port) ) {
   4596         SOC_IF_ERROR_RETURN(
   4597             PHY_READ_BCM542XX_1000X_MII_ANAr(unit, pc,&mii_adv) );
   4598 
   4599         if ( mii_adv & PHY_BCM542XX_MII_ANA_C37_FD ) {
   4600             ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   4601         }
   4602         if ( mii_adv & PHY_BCM542XX_MII_ANA_C37_HD ) {
   4603             ability->speed_half_duplex |= SOC_PA_SPEED_1000MB;
   4604         }
   4605 
   4606         switch ( mii_adv & (PHY_BCM542XX_MII_ANA_C37_PAUSE |
   4607                             PHY_BCM542XX_MII_ANA_C37_ASYM_PAUSE) ) {
   4608         case PHY_BCM542XX_MII_ANA_C37_PAUSE:
   4609             ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   4610             break;
   4611         case PHY_BCM542XX_MII_ANA_C37_ASYM_PAUSE:
   4612             ability->pause = SOC_PA_PAUSE_TX;
   4613             break;
   4614         case (PHY_BCM542XX_MII_ANA_C37_PAUSE | PHY_BCM542XX_MII_ANA_C37_ASYM_PAUSE):
   4615             ability->pause = SOC_PA_PAUSE_RX;
   4616             break;
   4617         }
   4618 
   4619     } else {
   4620         return SOC_E_INTERNAL;
   4621     }
   4622 
   4623     LOG_INFO(BSL_LS_SOC_PHY,
   4624              (BSL_META_U(unit, "phy_bcm542xx_adv_local_get: u=%d p=%d "
   4625                                "ability_hd_speed=0x%x, ability_fd_speed=0x%x, "
   4626                                "ability_pause=0x%x\n"),
   4627               unit, port, ability->speed_half_duplex,
   4628               ability->speed_full_duplex, ability->pause));
   4629     return ( SOC_E_NONE );
   4630 }
   4631 
   4632 /*
   4633  * Function:
   4634  *      phy_bcm542xx0_ability_remote_get
   4635  * Purpose:
   4636  *      Get partners current advertisement for auto-negotiation.
   4637  * Parameters:
   4638  *      unit - StrataSwitch unit #.
   4639  *      port - StrataSwitch port #.
   4640  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   4641  * Returns:
   4642  *      SOC_E_XXX
   4643  * Notes:
   4644  *      The remote advertisement is retrieved for the ACTIVE medium.
   4645  *      No synchronization performed at this level. If Autonegotiation is
   4646  *      disabled or in progress, this routine will return an error.
   4647  */
   4648 
   4649 STATIC int
   4650 phy_bcm542xx_ability_remote_get(int unit, soc_port_t port,
   4651                                 soc_port_ability_t *ability)
   4652 {
   4653     phy_ctrl_t  *pc;
   4654     uint16       mii_stat, mii_anp, mii_gb_stat;
   4655     uint16       eee_resolution;
   4656 
   4657     if (NULL == ability) {
   4658         return SOC_E_PARAM;
   4659     }
   4660 
   4661     sal_memset(ability, 0, sizeof(soc_port_ability_t)); /*zero init*/
   4662     pc = EXT_PHY_SW_STATE(unit, port);
   4663 
   4664     if ( PHY_COPPER_MODE(unit, port) ) {
   4665         SOC_IF_ERROR_RETURN
   4666             (PHY_READ_BCM542XX_MII_STATr(unit, pc,&mii_stat));
   4667 
   4668          if ( ! (mii_stat & PHY_BCM542XX_MII_STAT_AN_DONE) ) {
   4669             return SOC_E_NONE;
   4670         }
   4671 
   4672         SOC_IF_ERROR_RETURN
   4673             (PHY_READ_BCM542XX_MII_ANPr(unit, pc,&mii_anp));
   4674         SOC_IF_ERROR_RETURN
   4675             (PHY_READ_BCM542XX_MII_GB_STATr(unit, pc,&mii_gb_stat));
   4676         
   4677         if ( mii_anp & PHY_BCM542XX_MII_ANA_HD_10 ) {
   4678             ability->speed_half_duplex |= SOC_PA_SPEED_10MB;
   4679         }
   4680         if ( mii_anp & PHY_BCM542XX_MII_ANA_FD_10 ) {
   4681             ability->speed_full_duplex |= SOC_PA_SPEED_10MB;
   4682         }
   4683         if ( mii_anp & PHY_BCM542XX_MII_ANA_HD_100 ) {
   4684             ability->speed_half_duplex |= SOC_PA_SPEED_100MB;
   4685         }
   4686         if ( mii_anp & PHY_BCM542XX_MII_ANA_FD_100 ) {
   4687             ability->speed_full_duplex |= SOC_PA_SPEED_100MB;
   4688         }
   4689         if ( mii_gb_stat & PHY_BCM542XX_MII_GB_STAT_LP_1000HD ) {
   4690             ability->speed_half_duplex |= SOC_PA_SPEED_1000MB;
   4691         }
   4692         if ( mii_gb_stat & PHY_BCM542XX_MII_GB_STAT_LP_1000FD ) {
   4693             ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   4694         }
   4695 
   4696         if ( mii_anp & PHY_BCM542XX_MII_ANA_ASYM_PAUSE ) {
   4697             if ( mii_anp & PHY_BCM542XX_MII_ANA_PAUSE ) {
   4698                 ability->pause |= SOC_PA_PAUSE_RX;
   4699             } else {
   4700                 ability->pause |= SOC_PA_PAUSE_TX;
   4701             }
   4702         } else {
   4703             if ( mii_anp & PHY_BCM542XX_MII_ANA_PAUSE ) {
   4704                 ability->pause |= SOC_PA_PAUSE;
   4705             }
   4706         }
   4707 
   4708         /* EEE settings */
   4709         if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   4710             SOC_IF_ERROR_RETURN
   4711             (PHY_READ_BCM542XX_EEE_RESOLUTION_STATr(unit, pc,&eee_resolution));
   4712             if ( eee_resolution & 0x04 ) {
   4713                 ability->eee |= SOC_PA_EEE_1GB_BASET;
   4714             }
   4715             if ( eee_resolution & 0x02 ) {
   4716                 ability->eee |= SOC_PA_EEE_100MB_BASETX;
   4717             }
   4718         }
   4719 
   4720     } else if ( PHY_FIBER_MODE(unit, port) ) {
   4721         SOC_IF_ERROR_RETURN
   4722             (PHY_READ_BCM542XX_1000X_MII_ANPr(unit, pc,&mii_anp));
   4723         if ( mii_anp & PHY_BCM542XX_MII_ANP_SGMII_MODE ) { /* Link partner is SGMII master */
   4724             if ( mii_anp & PHY_BCM542XX_MII_ANP_SGMII_FD ) { /* Full Duplex */
   4725                 switch(mii_anp & PHY_BCM542XX_MII_ANP_SGMII_SS_MASK) {
   4726                 case PHY_BCM542XX_MII_ANP_SGMII_SS_10:
   4727                     ability->speed_full_duplex |= SOC_PA_SPEED_10MB;
   4728                     break;
   4729                 case PHY_BCM542XX_MII_ANP_SGMII_SS_100:
   4730                     ability->speed_full_duplex |= SOC_PA_SPEED_100MB;
   4731                     break;
   4732                 case PHY_BCM542XX_MII_ANP_SGMII_SS_1000:
   4733                     ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   4734                     break;
   4735                 }
   4736             } else { /* Half duplex */
   4737                 switch(mii_anp & PHY_BCM542XX_MII_ANP_SGMII_SS_MASK) {
   4738                 case PHY_BCM542XX_MII_ANP_SGMII_SS_10:
   4739                     ability->speed_half_duplex |= SOC_PA_SPEED_10MB;
   4740                     break;
   4741                 case PHY_BCM542XX_MII_ANP_SGMII_SS_100:
   4742                     ability->speed_half_duplex |= SOC_PA_SPEED_100MB;
   4743                     break;
   4744                 case PHY_BCM542XX_MII_ANP_SGMII_SS_1000:
   4745                     ability->speed_half_duplex |= SOC_PA_SPEED_1000MB;
   4746                     break;
   4747                 }
   4748             }
   4749 
   4750         } else {
   4751             if ( mii_anp & PHY_BCM542XX_MII_ANP_C37_FD ) {
   4752                 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   4753             }
   4754             if ( mii_anp & PHY_BCM542XX_MII_ANP_C37_HD ) {
   4755                 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB;
   4756             }
   4757 
   4758             switch ( mii_anp & (PHY_BCM542XX_MII_ANP_C37_PAUSE |
   4759                                 PHY_BCM542XX_MII_ANP_C37_ASYM_PAUSE) ) {
   4760             case PHY_BCM542XX_MII_ANP_C37_PAUSE:
   4761                 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   4762                 break;
   4763             case PHY_BCM542XX_MII_ANP_C37_ASYM_PAUSE:
   4764                 ability->pause = SOC_PA_PAUSE_TX;
   4765                 break;
   4766             case (PHY_BCM542XX_MII_ANP_C37_PAUSE | PHY_BCM542XX_MII_ANP_C37_ASYM_PAUSE):
   4767                 ability->pause = SOC_PA_PAUSE_RX;
   4768                 break;
   4769             }
   4770         }
   4771 
   4772     } else {
   4773         return SOC_E_INTERNAL;
   4774     }
   4775 
   4776     LOG_INFO(BSL_LS_SOC_PHY,
   4777              (BSL_META_U(unit, "phy_bcm542xx_adv_remote_get: u=%d p=%d "
   4778                                "ability_hd_speed=0x%x ability_fd_speed=0x%x "
   4779                                "ability_pause=0x%x\n"),
   4780               unit, port, ability->speed_half_duplex,
   4781               ability->speed_full_duplex, ability->pause));
   4782     return ( SOC_E_NONE );
   4783 }
   4784 
   4785 
   4786 /*
   4787  * Function:
   4788  *      phy_bcm542xx_ability_local_get
   4789  * Purpose:
   4790  *      Get the abilities of the local gigabit PHY.
   4791  * Parameters:
   4792  *      unit - StrataSwitch unit #.
   4793  *      port - StrataSwitch port #.
   4794  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   4795  * Returns:
   4796  *      SOC_E_NONE
   4797  * Notes:
   4798  *      The ability is retrieved only for the ACTIVE medium.
   4799  */
   4800 
   4801 STATIC int
   4802 phy_bcm542xx_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   4803 {
   4804     phy_ctrl_t  *pc;
   4805 
   4806     if (NULL == ability) {
   4807         return SOC_E_PARAM;
   4808     }
   4809     pc = EXT_PHY_SW_STATE(unit, port);
   4810     sal_memset(ability, 0,  sizeof(soc_port_ability_t)); /* zero initialize */
   4811 
   4812     if ( PHY_COPPER_MODE(unit, port) ) {
   4813         ability->speed_half_duplex  = SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB;
   4814         ability->speed_full_duplex  = SOC_PA_SPEED_1000MB |
   4815                                       SOC_PA_SPEED_100MB | 
   4816                                       SOC_PA_SPEED_10MB;
   4817                                       
   4818         ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   4819         ability->interface = SOC_PA_INTF_SGMII;
   4820         ability->medium    = SOC_PA_MEDIUM_COPPER; 
   4821         ability->loopback  = SOC_PA_LB_PHY;
   4822         ability->flags     = SOC_PA_AUTONEG;
   4823         
   4824         /* EEE settings */
   4825         if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   4826                 ability->eee |= SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX;
   4827         }
   4828 
   4829         if ( pc->automedium ) {
   4830             ability->flags     |= SOC_PA_COMBO;
   4831         }
   4832     } else if ( PHY_FIBER_MODE(unit, port) ) {
   4833         ability->speed_half_duplex  = SOC_PA_SPEED_100MB;
   4834         ability->speed_full_duplex  = SOC_PA_SPEED_1000MB |SOC_PA_SPEED_100MB;
   4835                                       
   4836         ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM;
   4837         ability->interface = SOC_PA_INTF_SGMII;
   4838         ability->medium    = SOC_PA_MEDIUM_FIBER; 
   4839         ability->loopback  = SOC_PA_LB_PHY;
   4840         ability->flags     = SOC_PA_AUTONEG;
   4841 
   4842         if ( pc->automedium ) {
   4843             ability->flags     |= SOC_PA_COMBO;
   4844         }
   4845 
   4846     } else {
   4847         return SOC_E_INTERNAL;
   4848     }
   4849 
   4850     LOG_INFO(BSL_LS_SOC_PHY,
   4851              (BSL_META_U(unit, "phy_bcm542xx_ability_local_get: u=%d p=%d "
   4852                                "ability_hd_speed=0x%x, ability_fd_speed=0x%x, "
   4853                                "ability_pause=0x%x\n"),
   4854               unit, port, ability->speed_half_duplex,
   4855               ability->speed_full_duplex, ability->pause));
   4856     return ( SOC_E_NONE );
   4857 }
   4858 
   4859 /*
   4860  * Function:
   4861  *      phy_bcm542xx_lb_set
   4862  * Purpose:
   4863  *      Set the local PHY loopback mode.
   4864  * Parameters:
   4865  *      unit - StrataSwitch unit #.
   4866  *      port - StrataSwitch port #.
   4867  *      loopback - Boolean: true = enable loopback, false = disable.
   4868  * Returns:
   4869  *      SOC_E_XXX
   4870  * Notes:
   4871  *      The loopback mode is set only for the ACTIVE medium.
   4872  *      No synchronization performed at this level.
   4873  */
   4874 
   4875 STATIC int
   4876 phy_bcm542xx_lb_set(int unit, soc_port_t port, int enable)
   4877 {
   4878     int          rv = SOC_E_NONE;
   4879     phy_ctrl_t  *pc;
   4880     uint16       mii_ctrl, temp16;
   4881     pc = EXT_PHY_SW_STATE(unit, port);
   4882     PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc);
   4883 
   4884     if ( PHY_COPPER_MODE(unit, port) ) {
   4885 #if AUTO_MDIX_WHEN_AN_DIS
   4886         {
   4887             /* Disable Auto-MDIX When autoneg disabled */
   4888             /* Enable Auto-MDIX When autoneg disabled */
   4889             temp16 = (enable) ? 0x0000 : PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE;
   4890             PHY_MODIFY_BCM542XX_MII_MISC_CTRLr(unit, pc, temp16, 
   4891                                         PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE);
   4892         }
   4893 #endif
   4894         /* Set loopback setting for 1G/100M/10M */
   4895         SOC_IF_ERROR_RETURN( PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl) );
   4896         mii_ctrl &= ~PHY_BCM542XX_MII_CTRL_LPBK_EN;
   4897         mii_ctrl |= (enable) ? PHY_BCM542XX_MII_CTRL_LPBK_EN : 0;
   4898         SOC_IF_ERROR_RETURN(
   4899                 PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, mii_ctrl) );
   4900         /* Force link is required for 100/10M speeds to work in loopback */
   4901         phy_bcm542xx_direct_reg_modify(unit, pc,
   4902                 PHY_BCM542XX_TEST1_REG_OFFSET, 
   4903                 (enable) ? PHY_BCM542XX_TEST1_REG_FORCE_LINK : 0,
   4904                 PHY_BCM542XX_TEST1_REG_FORCE_LINK);
   4905 
   4906     } else if ( PHY_FIBER_MODE(unit, port) ) {
   4907         temp16 = (enable) ? PHY_BCM542XX_1000BASE_X_CTRL_REG_LE : 0;
   4908         rv = PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, temp16,
   4909                                         PHY_BCM542XX_1000BASE_X_CTRL_REG_LE);
   4910 
   4911         if (enable && SOC_SUCCESS(rv) ) {
   4912             uint16         stat;
   4913             int            link;
   4914             soc_timeout_t  to;
   4915 
   4916             /* Wait up to 5000 msec for link up */
   4917             soc_timeout_init(&to, 5000000, 0);
   4918             link = 0;
   4919             while ( ! soc_timeout_check(&to) ) {
   4920                 rv = PHY_READ_BCM542XX_1000X_MII_STATr(unit, pc,&stat);
   4921                 link = stat & PHY_BCM542XX_1000BASE_X_STAT_REG_LA;
   4922                 if ( link || SOC_FAILURE(rv) ) {
   4923                     break;
   4924                 }
   4925             }
   4926             if ( ! link ) {
   4927                 LOG_WARN(BSL_LS_SOC_PHY,
   4928                          (BSL_META_U(unit,
   4929                                      "phy_bcm542xx_lb_set: u=%d p=%d TIMEOUT\n"),
   4930                           unit, port));
   4931 
   4932                 rv = SOC_E_TIMEOUT;
   4933             }
   4934         }
   4935 
   4936     } else {
   4937         return SOC_E_INTERNAL;
   4938     }
   4939 
   4940     LOG_INFO(BSL_LS_SOC_PHY,
   4941              (BSL_META_U(unit, "phy_bcm542xx_lb_set: u=%d p=%d en=%d rv=%d\n"), 
   4942               unit, port, enable, rv));
   4943     return rv; 
   4944 }
   4945 
   4946 /*
   4947  * Function:
   4948  *      phy_bcm542xx_lb_get
   4949  * Purpose:
   4950  *      Get the local PHY loopback mode.
   4951  * Parameters:
   4952  *      unit - StrataSwitch unit #.
   4953  *      port - StrataSwitch port #.
   4954  *      loopback - (OUT) Boolean: true = enable loopback, false = disable.
   4955  * Returns:
   4956  *      SOC_E_XXX
   4957  * Notes:
   4958  *      The loopback mode is retrieved for the ACTIVE medium.
   4959  */
   4960 STATIC int
   4961 phy_bcm542xx_lb_get(int unit, soc_port_t port, int *enable)
   4962 {
   4963     uint16 mii_ctrl;
   4964     phy_ctrl_t *pc;
   4965 
   4966     pc = EXT_PHY_SW_STATE(unit, port);
   4967 
   4968     if ( PHY_COPPER_MODE(unit, port) ) {
   4969         SOC_IF_ERROR_RETURN(
   4970             PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl) );
   4971         *enable = (mii_ctrl & PHY_BCM542XX_MII_CTRL_LPBK_EN) ? 1 : 0;
   4972     } else if ( PHY_FIBER_MODE(unit, port) ) {
   4973         SOC_IF_ERROR_RETURN(
   4974             PHY_READ_BCM542XX_1000X_MII_CTRLr(unit, pc,&mii_ctrl) );
   4975         *enable = (mii_ctrl & PHY_BCM542XX_1000BASE_X_CTRL_REG_LE) ? 1 : 0;
   4976     } else {
   4977         return SOC_E_INTERNAL;
   4978     }
   4979 
   4980     return ( SOC_E_NONE ); 
   4981 }
   4982 
   4983 /*
   4984  * Function:
   4985  *      phy_bcm542xx_interface_set
   4986  * Purpose:
   4987  *      Set the current operating mode of the PHY.
   4988  * Parameters:
   4989  *      unit - StrataSwitch unit #.
   4990  *      port - StrataSwitch port #.
   4991  *      pif - one of SOC_PORT_IF_*
   4992  * Returns:
   4993  *      SOC_E_NONE - success
   4994  *      SOC_E_UNAVAIL - unsupported interface
   4995  */
   4996 
   4997 STATIC int
   4998 phy_bcm542xx_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   4999 {
   5000     COMPILER_REFERENCE(unit);
   5001     COMPILER_REFERENCE(port);
   5002 
   5003     switch (pif) {
   5004     case SOC_PORT_IF_QSGMII:
   5005     case SOC_PORT_IF_SGMII:
   5006     case SOC_PORT_IF_GMII:
   5007     case SOC_PORT_IF_RGMII:    
   5008         return SOC_E_NONE;
   5009     default:
   5010         return SOC_E_UNAVAIL;
   5011     }
   5012 }
   5013 
   5014 /*
   5015  * Function:
   5016  *      phy_bcm542xx_interface_get
   5017  * Purpose:
   5018  *      Get the current operating mode of the PHY.
   5019  * Parameters:
   5020  *      unit - StrataSwitch unit #.
   5021  *      port - StrataSwitch port #.
   5022  *      pif - (OUT) one of SOC_PORT_IF_*
   5023  * Returns:
   5024  *      SOC_E_NONE
   5025  */
   5026 
   5027 STATIC int
   5028 phy_bcm542xx_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   5029 {
   5030     COMPILER_REFERENCE(unit);
   5031     COMPILER_REFERENCE(port);
   5032 
   5033     if ( IS_GMII_PORT(unit, port) ) {
   5034         *pif = SOC_PORT_IF_GMII;
   5035     } else {
   5036         *pif = SOC_PORT_IF_SGMII;
   5037     }
   5038     return SOC_E_NONE;
   5039 }
   5040 
   5041 
   5042 /*
   5043  * Function:
   5044  *      phy_bcm542xx_mdix_set
   5045  * Description:
   5046  *      Set the Auto-MDIX mode of a port/PHY
   5047  * Parameters:
   5048  *      unit - Device number
   5049  *      port - Port number
   5050  *      mode - One of:
   5051  *              SOC_PORT_MDIX_AUTO
   5052  *                      Enable auto-MDIX when autonegotiation is enabled
   5053  *              SOC_PORT_MDIX_FORCE_AUTO
   5054  *                      Enable auto-MDIX always
   5055  *              SOC_PORT_MDIX_NORMAL
   5056  *                      Disable auto-MDIX
   5057  *              SOC_PORT_MDIX_XOVER
   5058  *                      Disable auto-MDIX, and swap cable pairs
   5059  * Return Value:
   5060  *      SOC_E_XXX
   5061  */
   5062 STATIC int
   5063 phy_bcm542xx_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode)
   5064 {
   5065     int rv = SOC_E_NONE;
   5066     phy_ctrl_t *pc;
   5067     int speed = 0;
   5068 
   5069     pc = EXT_PHY_SW_STATE(unit, port);
   5070     PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc);
   5071 
   5072     if ( PHY_COPPER_MODE(unit, port) ) {
   5073         switch( mode ) {
   5074         case SOC_PORT_MDIX_AUTO:
   5075             /* Clear bit 14 for automatic MDI crossover */
   5076             SOC_IF_ERROR_RETURN(
   5077                 PHY_MODIFY_BCM542XX_MII_ECRr(unit, pc, 0,
   5078                                         PHY_BCM542XX_MII_ECR_DAMC) );
   5079             /* Clear bit 9 to disable forced auto MDI xover */
   5080             SOC_IF_ERROR_RETURN(
   5081                 PHY_MODIFY_BCM542XX_MII_MISC_CTRLr(unit, pc, 0, 
   5082                                         PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE) );
   5083             break;
   5084         case SOC_PORT_MDIX_FORCE_AUTO:
   5085             /* Clear bit 14 for automatic MDI crossover */
   5086             SOC_IF_ERROR_RETURN(
   5087                 PHY_MODIFY_BCM542XX_MII_ECRr(unit, pc, 0,
   5088                                         PHY_BCM542XX_MII_ECR_DAMC) );
   5089 
   5090             /* Set bit 9 to enable forced auto MDI xover */
   5091             SOC_IF_ERROR_RETURN(
   5092                 PHY_MODIFY_BCM542XX_MII_MISC_CTRLr(unit, pc,
   5093                                         PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE,
   5094                                         PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE) );
   5095             break;
   5096         case SOC_PORT_MDIX_NORMAL:
   5097             rv = phy_bcm542xx_speed_get(unit, port, &speed);
   5098             if (SOC_FAILURE(rv) ) {
   5099                 return SOC_E_FAIL;
   5100             }
   5101             if (speed == 0 || speed == 10 || speed == 100) {
   5102                 /* Set bit 14 for automatic MDI crossover */
   5103                 SOC_IF_ERROR_RETURN(
   5104                     PHY_MODIFY_BCM542XX_MII_ECRr(unit, pc,
   5105                                                  PHY_BCM542XX_MII_ECR_DAMC, 
   5106                                                  PHY_BCM542XX_MII_ECR_DAMC) );
   5107                 SOC_IF_ERROR_RETURN(
   5108                     PHY_WRITE_BCM542XX_TEST1r(unit, pc, 0));
   5109             } else {
   5110                 return SOC_E_UNAVAIL;
   5111             }
   5112             break;
   5113         case SOC_PORT_MDIX_XOVER:
   5114             rv = phy_bcm542xx_speed_get(unit, port, &speed);
   5115             if (SOC_FAILURE(rv) ) {
   5116                 return SOC_E_FAIL;
   5117             }
   5118             if (speed == 0 || speed == 10 || speed == 100) {
   5119                 /* Set bit 14 for automatic MDI crossover */
   5120                 SOC_IF_ERROR_RETURN(
   5121                     PHY_MODIFY_BCM542XX_MII_ECRr(unit, pc,
   5122                                                  PHY_BCM542XX_MII_ECR_DAMC, 
   5123                                                  PHY_BCM542XX_MII_ECR_DAMC) );
   5124                 SOC_IF_ERROR_RETURN(
   5125                     PHY_WRITE_BCM542XX_TEST1r(unit, pc, 0x0080));
   5126             } else {
   5127                 return SOC_E_UNAVAIL;
   5128             }
   5129             break;
   5130         default :
   5131             return SOC_E_CONFIG;
   5132         }
   5133         pc->copper.mdix = mode;
   5134 
   5135     } else if ( PHY_FIBER_MODE(unit, port) ) {
   5136         if ( mode != SOC_PORT_MDIX_NORMAL ) {
   5137             return SOC_E_UNAVAIL;
   5138         }
   5139 
   5140     } else {
   5141         return SOC_E_INTERNAL;
   5142     }
   5143 
   5144     return SOC_E_NONE;
   5145 }        
   5146 
   5147 #if defined(BCM_WARM_BOOT_SUPPORT)
   5148 /*
   5149  * Function:
   5150  *      phy_542xx_mdix_wb_update
   5151  * Description:
   5152  *      Read the hw, derive the mode and update the mdix mode in sw structure
   5153  *      during wb.
   5154  * Parameters:
   5155  *      unit - (IN) Device number
   5156  *      port - (IN) Port number
   5157  *      mode - (OUT) :One of:
   5158  *              SOC_PORT_MDIX_AUTO
   5159  *                      Enable auto-MDIX when autonegotiation is enabled
   5160  *              SOC_PORT_MDIX_FORCE_AUTO
   5161  *                      Enable auto-MDIX always
   5162  *              SOC_PORT_MDIX_NORMAL
   5163  *                      Disable auto-MDIX
   5164  *              SOC_PORT_MDIX_XOVER
   5165  *                      Disable auto-MDIX, and swap cable pairs
   5166  * Return Value:
   5167  *      SOC_E_XXX
   5168  */
   5169 STATIC int
   5170 phy_542xx_mdix_wb_update(int unit, soc_port_t port)
   5171 {
   5172     phy_ctrl_t    *pc;
   5173     int            speed;
   5174     int            mode = 0;
   5175     uint16         val = 0;
   5176 
   5177     pc = EXT_PHY_SW_STATE(unit, port);
   5178 
   5179     /* Check bit 14 for automatic MDI crossover */
   5180     SOC_IF_ERROR_RETURN (PHY_READ_BCM542XX_MII_ECRr(unit, pc, &val));
   5181     if(val & 0x4000) {
   5182         SOC_IF_ERROR_RETURN(phy_bcm542xx_speed_get(unit, port, &speed));
   5183         if (speed == 0 || speed == 10 || speed == 100) {
   5184             SOC_IF_ERROR_RETURN (PHY_READ_BCM542XX_TEST1r(unit, pc, &val));
   5185             if (0 == val) {
   5186                 mode = SOC_PORT_MDIX_NORMAL;
   5187             } else if (0x80 == val) {
   5188                 mode = SOC_PORT_MDIX_XOVER;
   5189             } else {
   5190                 return SOC_E_UNAVAIL;
   5191             }
   5192         } else {
   5193             return SOC_E_UNAVAIL;
   5194         }
   5195     } else {
   5196         /* Check bit 9 forced auto MDI xover */
   5197         SOC_IF_ERROR_RETURN (PHY_READ_BCM542XX_MII_MISC_CTRLr(unit, pc,&val));
   5198         if (val & 0x200) {
   5199             /* bit 9 Set, forced auto MDI xover */
   5200             mode = SOC_PORT_MDIX_FORCE_AUTO;
   5201         } else {
   5202             /* bit 9 Clear, forced auto MDI xover */
   5203             mode = SOC_PORT_MDIX_AUTO;
   5204         }
   5205     }
   5206     pc->copper.mdix = mode;
   5207 
   5208     return SOC_E_NONE;
   5209 }
   5210 #endif /* defined(BCM_WARM_BOOT_SUPPORT) */
   5211 
   5212 
   5213 /*
   5214  * Function:
   5215  *      phy_bcm542xx_mdix_get
   5216  * Description:
   5217  *      Get the Auto-MDIX mode of a port/PHY
   5218  * Parameters:
   5219  *      unit - Device number
   5220  *      port - Port number
   5221  *      mode - (Out) One of:
   5222  *              SOC_PORT_MDIX_AUTO
   5223  *                      Enable auto-MDIX when autonegotiation is enabled
   5224  *              SOC_PORT_MDIX_FORCE_AUTO
   5225  *                      Enable auto-MDIX always
   5226  *              SOC_PORT_MDIX_NORMAL
   5227  *                      Disable auto-MDIX
   5228  *              SOC_PORT_MDIX_XOVER
   5229  *                      Disable auto-MDIX, and swap cable pairs
   5230  * Return Value:
   5231  *      SOC_E_XXX
   5232  */
   5233 STATIC int
   5234 phy_bcm542xx_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode)
   5235 {
   5236     phy_ctrl_t *pc;
   5237     int speed = 0;
   5238 
   5239     if ( mode == NULL ) {
   5240         return SOC_E_PARAM;
   5241     }
   5242 
   5243 #if defined(BCM_WARM_BOOT_SUPPORT)
   5244     if (SOC_WARM_BOOT(unit)) {
   5245         return phy_542xx_mdix_wb_update(unit, port);
   5246     }
   5247 #endif /* defined(BCM_WARM_BOOT_SUPPORT) */
   5248 
   5249     pc = EXT_PHY_SW_STATE(unit, port);
   5250 
   5251     if ( PHY_COPPER_MODE(unit, port) ) {
   5252         SOC_IF_ERROR_RETURN(phy_bcm542xx_speed_get(unit, port, &speed));
   5253         if (speed == 1000) {
   5254            *mode = SOC_PORT_MDIX_AUTO;
   5255         } else {
   5256             *mode = pc->copper.mdix;
   5257         }
   5258     } else {
   5259         *mode = SOC_PORT_MDIX_NORMAL;
   5260     }
   5261 
   5262     return SOC_E_NONE;
   5263 }    
   5264 
   5265 /*
   5266  * Function:
   5267  *      phy_bcm542xx_mdix_status_get
   5268  * Description:
   5269  *      Get the current MDIX status on a port/PHY
   5270  * Parameters:
   5271  *      unit    - Device number
   5272  *      port    - Port number
   5273  *      status  - (OUT) One of:
   5274  *              SOC_PORT_MDIX_STATUS_NORMAL
   5275  *                      Straight connection
   5276  *              SOC_PORT_MDIX_STATUS_XOVER
   5277  *                      Crossover has been performed
   5278  * Return Value:
   5279  *      SOC_E_XXX
   5280  */
   5281 STATIC int
   5282 phy_bcm542xx_mdix_status_get(int unit, soc_port_t port, 
   5283                              soc_port_mdix_status_t *status)
   5284 {
   5285     phy_ctrl_t    *pc;
   5286     uint16 mii_esrr;
   5287 
   5288     if ( status == NULL ) {
   5289         return SOC_E_PARAM;
   5290     }
   5291     pc = EXT_PHY_SW_STATE(unit, port);
   5292 
   5293     if ( PHY_COPPER_MODE(unit, port) ) {
   5294         SOC_IF_ERROR_RETURN
   5295             (phy_bcm542xx_direct_reg_read(unit, pc,
   5296                         PHY_BCM542XX_PHY_EXT_STATUS_REG_OFFSET,
   5297                         &mii_esrr));
   5298         if ( mii_esrr & 0x2000 ) {
   5299             *status = SOC_PORT_MDIX_STATUS_XOVER;
   5300         } else {
   5301             *status = SOC_PORT_MDIX_STATUS_NORMAL;
   5302         }
   5303 
   5304     } else if ( PHY_FIBER_MODE(unit, port) ) {
   5305             *status = SOC_PORT_MDIX_STATUS_NORMAL;
   5306 
   5307     } else {
   5308         return SOC_E_INTERNAL;
   5309     }
   5310 
   5311     return SOC_E_NONE;
   5312 }    
   5313 
   5314 /*
   5315  * Function:
   5316  *     phy_bcm542xx_encode_gmode 
   5317  * Purpose:
   5318  *     Global synchronization mode selection
   5319  *     P1588 NSE DPLL NCO Register 6, RDB.0xA7F[15:14] GMODE
   5320  * Parameters:
   5321  *
   5322  * Returns:
   5323  */
   5324 void phy_bcm542xx_encode_gmode(soc_port_phy_timesync_global_mode_t mode,
   5325                                uint16 *value)
   5326 {
   5327     switch ( mode ) {
   5328     case SOC_PORT_PHY_TIMESYNC_MODE_FREE:
   5329         *value = 0x1;
   5330         break;
   5331     case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN:
   5332         *value = 0x2;
   5333         break;
   5334     case SOC_PORT_PHY_TIMESYNC_MODE_CPU:
   5335         *value = 0x3;
   5336         break;
   5337     default:
   5338         break;
   5339     }
   5340 }
   5341 
   5342 /*
   5343  * Function:
   5344  *     phy_bcm542xx_decode_gmode
   5345  * Purpose:
   5346  *     Global synchronization mode selection
   5347  *     P1588 NSE DPLL NCO Register 6, RDB.0xA7F[15:14] GMODE
   5348  * Parameters:
   5349  *
   5350  * Returns:
   5351  */
   5352 void phy_bcm542xx_decode_gmode(uint16 value,
   5353                                soc_port_phy_timesync_global_mode_t *mode)
   5354 {
   5355     switch ( value & 0x3 ) {
   5356     case 0x1:
   5357         *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   5358         break;
   5359     case 0x2:
   5360         *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN;
   5361         break;
   5362     case 0x3:
   5363         *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU;
   5364         break;
   5365     default:
   5366         break;
   5367     }
   5368 }
   5369 
   5370 /*
   5371  * Function:
   5372  *     phy_bcm542xx_encode_framesync_mode 
   5373  * Purpose:
   5374  *     FrameSync mode selection
   5375  *     P1588 NSE DPLL NCO Register 6, RDB.0xA7F[5:2] FRAMESYNC_MODE
   5376  * Parameters:
   5377  *
   5378  * Returns:
   5379  */
   5380 void phy_bcm542xx_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode,
   5381                                         uint16 *value)
   5382 {
   5383     switch ( mode & 0xf ) {
   5384     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0:
   5385         *value = BIT(0);
   5386         break;
   5387     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1:
   5388         *value = BIT(1);
   5389         break;
   5390     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT:
   5391         *value = BIT(2);
   5392         break;
   5393     case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU:
   5394         *value = BIT(3);
   5395         break;
   5396     default:
   5397         *value = 0;
   5398         break;
   5399     }
   5400 }
   5401 
   5402 /*
   5403  * Function:
   5404  *     phy_bcm542xx_decode_framesync_mode
   5405  * Purpose:
   5406  *     FrameSync mode selection
   5407  *     P1588 NSE DPLL NCO Register 6, RDB.0xA7F[5:2] FRAMESYNC_MODE
   5408  * Parameters:
   5409  *
   5410  * Returns:
   5411  */
   5412 void phy_bcm542xx_decode_framesync_mode(uint16 value,
   5413                                         soc_port_phy_timesync_framesync_mode_t *mode)
   5414 {
   5415     switch ( value & 0xf ) {
   5416     case BIT(0):
   5417         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0;
   5418         break;
   5419     case BIT(1):
   5420         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1;
   5421         break;
   5422     case BIT(2):
   5423         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT;
   5424         break;
   5425     case BIT(3):
   5426         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU;
   5427         break;
   5428     default:
   5429         *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE;
   5430         break;
   5431     }
   5432 }
   5433 
   5434 
   5435 /*
   5436  * Function:
   5437  *     phy_bcm542xx_encode_sync_out_mode
   5438  * Purpose:
   5439  *     Sync_Out mode selection
   5440  *     P1588 NSE DPLL NCO Register 6, RDB.0xA7F[1:0] SYNC_OUT_MODE
   5441  * Parameters:
   5442  *
   5443  * Returns:
   5444  */
   5445 void phy_bcm542xx_encode_sync_out_mode(soc_port_phy_timesync_syncout_mode_t mode,
   5446                                        uint16 *value)
   5447 {
   5448     switch ( mode ) {
   5449     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE:
   5450         *value = 0x0;
   5451         break;
   5452     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME:
   5453         *value = 0x1;
   5454         break;
   5455     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN:
   5456         *value = 0x2;
   5457         break;
   5458     case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC:
   5459         *value = 0x3;
   5460         break;
   5461     default:
   5462         break;
   5463     }
   5464 }
   5465 
   5466 
   5467 /*
   5468  * Function:
   5469  *     phy_bcm542xx_decode_sync_out_mode
   5470  * Purpose:
   5471  *     Sync_Out mode selection
   5472  *     P1588 NSE DPLL NCO Register 6, RDB.0xA7F[1:0] SYNC_OUT_MODE
   5473  * Parameters:
   5474  *
   5475  * Returns:
   5476  */
   5477 void phy_bcm542xx_decode_sync_out_mode(uint16 value,
   5478                                        soc_port_phy_timesync_syncout_mode_t *mode)
   5479 {
   5480     switch ( value & 0x3 ) {
   5481     case 0x0:
   5482         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   5483         break;
   5484     case 0x1:
   5485         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME;
   5486         break;
   5487     case 0x2:
   5488         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN;
   5489         break;
   5490     case 0x3:
   5491         *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC;
   5492         break;
   5493     }
   5494 }
   5495 
   5496 /*
   5497  * Function:
   5498  *     phy_bcm542xx_encode_egress_message_mode
   5499  * Purpose:
   5500  *     P1588 Port_n TX Event Message Mode1/2 Selection Reg., RDB.0xa11+(n)
   5501  *     for Message 0-3  ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp )
   5502  * Parameters:
   5503  *
   5504  * Returns:
   5505  */
   5506 void phy_bcm542xx_encode_egress_message_mode(
   5507                 soc_port_phy_timesync_event_message_egress_mode_t mode,
   5508                 int offset, uint16 *value, uint16 *mask)
   5509 {
   5510     switch ( mode ) {
   5511     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE:
   5512         *value |= (0x0 << offset);
   5513         break; 
   5514     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD:
   5515         *value |= (0x1 << offset);
   5516         break;
   5517     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN:
   5518         *value |= (0x2 << offset);
   5519         break;
   5520     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP:
   5521         *value |= (0x3 << offset);
   5522         break; 
   5523     default:
   5524         break;
   5525     }
   5526     *mask |= 0x3 << offset;
   5527 }
   5528 
   5529 /*
   5530  * Function:
   5531  *    phy_bcm542xx_decode_egress_message_mode
   5532  * Purpose:
   5533  *     P1588 Port_n TX Event Message Mode1/2 Selection Reg., RDB.0xa11+(n)
   5534  *     for Message 0-3  ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp )
   5535  * Parameters:
   5536  *
   5537  * Returns:
   5538  */
   5539 void phy_bcm542xx_decode_egress_message_mode(uint16 value, int offset,
   5540                 soc_port_phy_timesync_event_message_egress_mode_t *mode)
   5541 {
   5542     switch ( (value >> offset) & 0x3 ) {
   5543     case 0x0:
   5544         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE;
   5545         break;
   5546     case 0x1:
   5547         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD;
   5548         break;
   5549     case 0x2:
   5550         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN;
   5551         break;
   5552     case 0x3:
   5553         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP;   
   5554         break; 
   5555     }
   5556 }
   5557 
   5558 /*
   5559  * Function:
   5560  *     phy_bcm542xx_encode_ingress_message_mode
   5561  * Purpose:
   5562  *     P1588 Port_n RX Event Message Mode1/2 Selection Reg., RDB.0xa19+(n)
   5563  *     for Message 0-3  ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp )
   5564  * Parameters:
   5565  *
   5566  * Returns:
   5567  */
   5568 void phy_bcm542xx_encode_ingress_message_mode(
   5569                 soc_port_phy_timesync_event_message_ingress_mode_t mode,
   5570                 int offset, uint16 *value, uint16 *mask)
   5571 {
   5572     switch ( mode ) {
   5573     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE:
   5574         *value |= (0x0 << offset);
   5575         break;
   5576     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD:
   5577         *value |= (0x1 << offset);
   5578         break;
   5579     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP:
   5580         *value |= (0x2 << offset);
   5581         break;
   5582     case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME:
   5583         *value |= (0x3 << offset);
   5584         break;
   5585     default:
   5586         break;
   5587     }
   5588     *mask |= 0x3 << offset;
   5589 }
   5590 
   5591 /*
   5592  * Function:
   5593  *    phy_bcm542xx_decode_ingress_message_mode 
   5594  * Purpose:
   5595  *     P1588 Port_n RX Event Message Mode1/2 Selection Reg., RDB.0xa19+(n)
   5596  *     for Message 0-3  ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp )
   5597  * Parameters:
   5598  *
   5599  * Returns:
   5600  */
   5601 void phy_bcm542xx_decode_ingress_message_mode(uint16 value, int offset,
   5602                 soc_port_phy_timesync_event_message_ingress_mode_t *mode)
   5603 {
   5604     switch ((value >> offset) & 0x3) {
   5605     case 0x0:
   5606         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE;
   5607         break;
   5608     case 0x1:
   5609         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD;
   5610         break;
   5611     case 0x2:
   5612         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP;
   5613         break;
   5614     case 0x3:
   5615         *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME;
   5616         break;
   5617     }
   5618 }
   5619 
   5620 /*
   5621  * Function:
   5622  *    phy_bcm542xx_timesync_config_set
   5623  * Purpose:
   5624  *
   5625  * Parameters:
   5626  *
   5627  * Returns:
   5628  */
   5629 int
   5630 phy_bcm542xx_timesync_config_set(int unit, soc_port_t port,
   5631                                  soc_port_phy_timesync_config_t *conf)
   5632 {
   5633     uint16  dev_port = 0;
   5634     uint16  rx_control_reg = 0, tx_control_reg = 0;
   5635     uint16  en_control_reg = 0, tx_capture_en_reg = 0, rx_capture_en_reg = 0;
   5636     uint16  nse_nco_6 = 0, nse_nco_2c = 0, gmode =0, framesync_mode=0;
   5637     uint16  syncout_mode=0, tx_ts_event_cap = 0, rx_ts_event_cap = 0;
   5638     uint16  mpls_control_reg_tx = 0, mpls_control_reg_rx = 0, i;
   5639     uint16  data16 = 0, mask16 = 0;
   5640     phy_ctrl_t  *pc;
   5641 
   5642     if ( NULL == conf ) {
   5643         return SOC_E_PARAM;
   5644     }
   5645    
   5646     pc = EXT_PHY_SW_STATE(unit, port);
   5647 
   5648     /* Dev port numbers from 0-7 */
   5649     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   5650     
   5651     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   5652        of the device. For example to enable autogrEEEn on port0, 
   5653        rdb register for port 4 0x808 need to be used. 
   5654        Refer package configuration document.
   5655      */
   5656     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   5657         dev_port += 4;
   5658     }
   5659 
   5660     if ( conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE ) {
   5661         en_control_reg |= ( BIT(dev_port + 8) | BIT(dev_port) );
   5662         data16 = PHY_BCM542XX_EXPF5_TIME_SYNC_ENABLE;
   5663     } else {
   5664         data16 = 0;
   5665     }
   5666     /* CORE_EXPF5 - Time Sync control, RDB.0x0f5,  bit[0] TIMESYNC_EN */
   5667     SOC_IF_ERROR_RETURN
   5668         (PHY_MODIFY_BCM542XX_TIME_SYNC_CTRLr(unit, pc, data16,
   5669                         PHY_BCM542XX_EXPF5_TIME_SYNC_ENABLE));
   5670 
   5671     /* Enable TX SOP & RX SOP capability in 10bt. */
   5672     /* CORE_EXP45 - Pattern Generator Control, RDB.0x005, bit[12] TX_CRC_CHECKER_EN */
   5673     phy_bcm542xx_direct_reg_modify(unit, pc,
   5674                         PHY_BCM542XX_PATT_GEN_CTRL_REG_OFFSET,
   5675                         PHY_BCM542XX_PATT_GEN_CTRL_REG_TX_CRC_CHECK_EN,
   5676                         PHY_BCM542XX_PATT_GEN_CTRL_REG_TX_CRC_CHECK_EN);
   5677     /* CORE_EXPF5 - Time Sync control, RDB.0x0f5,  bit[8:7] */
   5678     phy_bcm542xx_direct_reg_modify(unit, pc,
   5679                         PHY_BCM542XX_EXPF5_TIME_SYNC_REG_OFFSET,
   5680                         PHY_BCM542XX_EXPF5_TIME_SYNC_TX_SOP_10BT_EN
   5681                       | PHY_BCM542XX_EXPF5_TIME_SYNC_RX_SOP_10BT_EN,
   5682                         PHY_BCM542XX_EXPF5_TIME_SYNC_TX_SOP_10BT_EN
   5683                       | PHY_BCM542XX_EXPF5_TIME_SYNC_RX_SOP_10BT_EN);
   5684 
   5685     /***********************************************************************
   5686      * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   5687      * To access TOP level registers use phy_id of port0. Override this ports 
   5688      */
   5689     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   5690 
   5691     if ( conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE ) {
   5692         data16 = 0;
   5693     } else {
   5694         data16 = PHY_BCM542XX_TOP_INTERRUPT_MASK;
   5695     }
   5696     /* TOP_MISCREG_INTERRUPT_MASK, RDB.0x82d */
   5697     SOC_IF_ERROR_RETURN
   5698         (phy_bcm542xx_direct_reg_modify(unit, pc,
   5699                         PHY_BCM542XX_TOP_INTERRUPT_MASK_OFFSET, data16, 
   5700                         PHY_BCM542XX_TOP_INTERRUPT_MASK));
   5701 
   5702     /* Enable/disable 1588 tx/rx per port*/
   5703     phy_bcm542xx_direct_reg_modify(unit, pc,
   5704                         PHY_BCM542XX_TOP_1588_SLICE_EN_CTRL_REG_OFFSET,  
   5705                         en_control_reg, en_control_reg);
   5706     /* TOP_1588_SLICE_ENABLE, RDB.0xa10 */
   5707     phy_bcm542xx_direct_reg_read(unit, pc,
   5708                         PHY_BCM542XX_TOP_1588_SLICE_EN_CTRL_REG_OFFSET,  
   5709                         &en_control_reg);
   5710 
   5711     /* Enable TS capture + Select TS capture for event message type */
   5712     if ( conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE ) {
   5713         tx_capture_en_reg |= BIT(dev_port);
   5714         rx_capture_en_reg |= BIT(dev_port);
   5715 
   5716         /* TOP_1588_NSE_NCO_6, RDB.0xa7f[12],  Initialize NSE Block */
   5717         phy_bcm542xx_direct_reg_modify(unit, pc,
   5718                         PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET,
   5719                         PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_EN,
   5720                         PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_EN);                    
   5721 
   5722         if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE ) {
   5723             tx_ts_event_cap |= BIT(8);
   5724         }
   5725         if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE ) { 
   5726             rx_ts_event_cap |= BIT(8);
   5727         }
   5728         if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE ) {
   5729             tx_ts_event_cap |= BIT(9);
   5730         }
   5731         if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE ) { 
   5732             rx_ts_event_cap |= BIT(9);
   5733         }
   5734         if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE ) {
   5735             tx_ts_event_cap |= BIT(10);
   5736         }
   5737         if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE ) { 
   5738             rx_ts_event_cap |= BIT(10);
   5739         }
   5740         if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE ) {
   5741             tx_ts_event_cap |= BIT(11);
   5742         }
   5743         if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE ) { 
   5744             rx_ts_event_cap |= BIT(11);
   5745         }
   5746     }
   5747 
   5748     /* Select TS capture for event message type */
   5749     /* TOP_1588_TX_PORT_n_TS_OFFSET_MSB, RDB.0xa35...,  bit[11:8] */
   5750     phy_bcm542xx_direct_reg_modify(unit, pc,
   5751                      PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_MSB(dev_port),
   5752                      tx_ts_event_cap,
   5753                      tx_ts_event_cap);
   5754     /* TOP_1588_RX_PORT_n_TS_OFFSET_MSB, RDB.0xa45...,  bit[11:8] */
   5755     phy_bcm542xx_direct_reg_modify(unit, pc,
   5756                      PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_MSB(dev_port),
   5757                      rx_ts_event_cap,
   5758                      rx_ts_event_cap);
   5759 
   5760     /* Timestamp capture enable for Rx & TX */
   5761     /* P1588 TX SOP Timestamp Capture Enable, RDB.0xa21 */
   5762     phy_bcm542xx_direct_reg_modify(unit, pc,
   5763                      PHY_BCM542XX_TOP_1588_TX_TS_CAP_REG_OFFSET, 
   5764                      tx_capture_en_reg,
   5765                      BIT(dev_port));
   5766     /* P1588 RX SOP Timestamp Capture Enable, RDB.0xa22 */
   5767     phy_bcm542xx_direct_reg_modify(unit, pc,
   5768                      PHY_BCM542XX_TOP_1588_RX_TS_CAP_REG_OFFSET, 
   5769                      rx_capture_en_reg,
   5770                      BIT(dev_port));
   5771 
   5772     /* Enable timestamp capture on the next frame sync event */
   5773     if ( conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE ) {
   5774         nse_nco_6 |= PHY_BCM542XX_TOP_1588_NSE_NCO_6_TS_CAP;
   5775     }
   5776     /* P1588 NSE DPLL NCO Reg.6, RDB.0xa7f,  bit[13] */
   5777     phy_bcm542xx_direct_reg_modify(unit, pc,
   5778                       PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET, 
   5779                       nse_nco_6, 
   5780                       PHY_BCM542XX_TOP_1588_NSE_NCO_6_TS_CAP); 
   5781                 
   5782     /* Enable the CRC check in PTP detection receiving side */
   5783     data16 = (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE)
   5784              ? PHY_BCM542XX_TOP_1588_RX_TX_CTL_REG_RX_CRC_EN : 0;
   5785     /* P1588 Receive/Transmit Control, RDB.0xa62,  bit[3] */
   5786     phy_bcm542xx_direct_reg_modify(unit, pc,
   5787                      PHY_BCM542XX_TOP_1588_RX_TX_CTL_REG_OFFSET, data16, 
   5788                      PHY_BCM542XX_TOP_1588_RX_TX_CTL_REG_RX_CRC_EN);
   5789 
   5790     /* Enable different packet detections & checks in Rx & Tx direction */
   5791     if ( conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE ) {
   5792         rx_control_reg |= PHY_BCM542XX_TOP_1588_RX_CTL_REG_RX_AS_EN;
   5793         tx_control_reg |= PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_AS_EN;
   5794     }
   5795     if ( conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE ) {
   5796         rx_control_reg |= PHY_BCM542XX_TOP_1588_RX_CTL_REG_RX_L2_EN;
   5797         tx_control_reg |= PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_L2_EN;
   5798     }
   5799     if ( conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE ) {
   5800         rx_control_reg |= PHY_BCM542XX_TOP_1588_RX_CTL_REG_RX_IPV4_UDP_EN;
   5801         tx_control_reg |= PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_IPV4_UDP_EN;
   5802     }
   5803     if ( conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE ) {
   5804         rx_control_reg |= PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_IPV6_UDP_EN;
   5805         tx_control_reg |= PHY_BCM542XX_TOP_1588_RX_CTL_REG_RX_IPV6_UDP_EN;
   5806     }
   5807     phy_bcm542xx_direct_reg_write(unit, pc,
   5808                      PHY_BCM542XX_TOP_1588_TX_CTL_REG_OFFSET, 
   5809                      tx_control_reg);
   5810     phy_bcm542xx_direct_reg_write(unit, pc,
   5811                      PHY_BCM542XX_TOP_1588_RX_CTL_REG_OFFSET, 
   5812                      rx_control_reg);
   5813 
   5814     /* Set input for NCO adder */
   5815     if ( conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) {
   5816         nse_nco_2c &= ~PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_FREQ_MDIO_SEL;
   5817     } else {
   5818         nse_nco_2c |=  PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_FREQ_MDIO_SEL;
   5819     }
   5820 
   5821      phy_bcm542xx_direct_reg_modify(unit, pc,
   5822                       PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_REG_OFFSET, 
   5823                       nse_nco_2c, 
   5824                       PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_FREQ_MDIO_SEL); 
   5825     
   5826     
   5827     /* VLAN Tags */
   5828     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID ) {
   5829         phy_bcm542xx_direct_reg_write(unit, pc,
   5830                          PHY_BCM542XX_TOP_1588_VLAN_ITPID_REG_OFFSET, 
   5831                          conf->itpid); 
   5832     }
   5833     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID ) {
   5834 
   5835         phy_bcm542xx_direct_reg_write(unit, pc,
   5836                          PHY_BCM542XX_TOP_1588_VLAN_OTPID_REG_OFFSET, 
   5837                          conf->otpid); 
   5838     }
   5839     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2 ) {
   5840         phy_bcm542xx_direct_reg_write(unit, pc,
   5841                          PHY_BCM542XX_TOP_1588_OTHER_OTPID_REG_OFFSET,
   5842                          conf->otpid2); 
   5843     }
   5844     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER ) {
   5845         phy_bcm542xx_direct_reg_write(unit, pc,
   5846                          PHY_BCM542XX_TOP_1588_NSE_NCO_4_REG_OFFSET,
   5847                          conf->ts_divider & 0xfff); 
   5848     }
   5849     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY ) {
   5850         phy_bcm542xx_direct_reg_write(unit, pc,
   5851                          PHY_BCM542XX_TOP_1588_RX_PORTN_LINK_DELAY_LSB(dev_port),
   5852                          conf->rx_link_delay & 0xffff); 
   5853         phy_bcm542xx_direct_reg_write(unit, pc,
   5854                          PHY_BCM542XX_TOP_1588_RX_PORTN_LINK_DELAY_MSB(dev_port),
   5855                          (conf->rx_link_delay>>16) & 0xffff);
   5856     }
   5857 
   5858     /* TIMECODE */
   5859     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE ) {
   5860         /* P1588 Original Time Code Register 0-4 (80 bits), RDB.0xa54-a58 */
   5861         phy_bcm542xx_direct_reg_write(unit, pc,
   5862                      PHY_BCM542XX_TOP_1588_TIME_CODE_0_REG_OFFSET, 
   5863                      (uint16)(conf->original_timecode.nanoseconds & 0xffff));
   5864         phy_bcm542xx_direct_reg_write(unit, pc,
   5865                      PHY_BCM542XX_TOP_1588_TIME_CODE_1_REG_OFFSET, 
   5866                      (uint16)((conf->original_timecode.nanoseconds >> 16) & 0xffff));
   5867         phy_bcm542xx_direct_reg_write(unit, pc,
   5868                      PHY_BCM542XX_TOP_1588_TIME_CODE_2_REG_OFFSET, 
   5869                      (uint16)(COMPILER_64_LO(conf->original_timecode.seconds) & 0xffff));
   5870         phy_bcm542xx_direct_reg_write(unit, pc,
   5871                      PHY_BCM542XX_TOP_1588_TIME_CODE_3_REG_OFFSET, 
   5872                      (uint16)((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) & 0xffff));
   5873         phy_bcm542xx_direct_reg_write(unit, pc,
   5874                      PHY_BCM542XX_TOP_1588_TIME_CODE_4_REG_OFFSET, 
   5875                      (uint16)(COMPILER_64_HI(conf->original_timecode.seconds) & 0xffff));
   5876     }
   5877 
   5878     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE ) {
   5879         /* P1588 NSE DPLL NCO Reg.6, bit[15:14] Global sync mode selection */
   5880         phy_bcm542xx_encode_gmode(conf->gmode, &gmode);
   5881     }
   5882 
   5883     /* FrameSync */
   5884     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE ) {
   5885         phy_bcm542xx_encode_framesync_mode(conf->framesync.mode, &framesync_mode);
   5886 
   5887         /* P1588 NSE DPLL NCO Register 7, RDB.0xA80-A81 */
   5888         phy_bcm542xx_direct_reg_write(unit, pc,
   5889                          PHY_BCM542XX_1588_NSE_DPLL_NCO_7_0_REG_OFFSET,
   5890                           conf->framesync.length_threshold);
   5891         phy_bcm542xx_direct_reg_write(unit, pc,
   5892                          PHY_BCM542XX_1588_NSE_DPLL_NCO_7_1_REG_OFFSET,
   5893                           conf->framesync.event_offset);
   5894     }
   5895 
   5896     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE ) {
   5897         phy_bcm542xx_encode_sync_out_mode(conf->syncout.mode, &syncout_mode);
   5898 
   5899         /* Interval & pulse width of syncout pulse */
   5900         /* P1588 NSE DPLL NCO Register 3, RDB.0xA78-A7A */
   5901         phy_bcm542xx_direct_reg_write(unit, pc,
   5902                          PHY_BCM542XX_TOP_1588_NSE_NCO_3_0_REG_OFFSET,
   5903                          conf->syncout.interval & 0xffff); 
   5904         phy_bcm542xx_direct_reg_write(unit, pc,
   5905                          PHY_BCM542XX_TOP_1588_NSE_NCO_3_1_REG_OFFSET,
   5906                          ( ((conf->syncout.pulse_1_length & 0x3) << 14) 
   5907                          | ((conf->syncout.interval >> 16) & 0x3fff   )) );
   5908         phy_bcm542xx_direct_reg_write(unit, pc,
   5909                          PHY_BCM542XX_TOP_1588_NSE_NCO_3_2_REG_OFFSET ,
   5910                          ( ((conf->syncout.pulse_2_length & 0x1ff) << 7) 
   5911                          | ((conf->syncout.pulse_1_length >> 2) & 0x7f )) );
   5912 
   5913         /* Local timer for SYNC_OUT */
   5914         /* P1588 NSE DPLL NCO Register 5, RDB.0xA7C-A7E, SYNOUT_TS_REG */
   5915         phy_bcm542xx_direct_reg_write(unit, pc,
   5916                          PHY_BCM542XX_TOP_1588_NSE_NCO_5_0_REG_OFFSET,
   5917                          (uint16)(COMPILER_64_LO(conf->syncout.syncout_ts) & 0xffff));
   5918         phy_bcm542xx_direct_reg_write(unit, pc,
   5919                          PHY_BCM542XX_TOP_1588_NSE_NCO_5_1_REG_OFFSET,
   5920                          (uint16)((COMPILER_64_LO(conf->syncout.syncout_ts) >> 16) & 0xffff));
   5921         phy_bcm542xx_direct_reg_write(unit, pc,
   5922                          PHY_BCM542XX_TOP_1588_NSE_NCO_5_2_REG_OFFSET,
   5923                          (uint16)(COMPILER_64_HI(conf->syncout.syncout_ts) & 0xffff));
   5924     }
   5925 
   5926     /* GMODE */    /* P1588 NSE DPLL NCO Register 6, RDB.0xA7F */
   5927     /* GMODE[15:14] FRAMESUNC_EN[12] FRAMESYNC_MODE[5:2] SYNC_OUT_MODE[1:0] */
   5928     phy_bcm542xx_direct_reg_modify( unit, pc,
   5929           PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET,
   5930           (gmode          << PHY_BCM542XX_TOP_1588_NSE_NCO_6_GMODE_SHIFT)       |
   5931           (framesync_mode << PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_MODE_SHIFT) |
   5932           (syncout_mode   << PHY_BCM542XX_TOP_1588_NSE_NCO_6_SYNCOUT_MODE_SHIFT)|
   5933           (framesync_mode ?  PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_EN : 0),
   5934           ( PHY_BCM542XX_TOP_1588_NSE_NCO_6_GMODE
   5935           | PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_EN
   5936           | PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_MODE
   5937           | PHY_BCM542XX_TOP_1588_NSE_NCO_6_SYNCOUT_MODE) );
   5938 
   5939     /* TX TS OFFSET */
   5940     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET ) {
   5941         phy_bcm542xx_direct_reg_write(unit, pc,
   5942                          PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_LSB(dev_port), 
   5943                          (uint16)(conf->tx_timestamp_offset & 0xffff));
   5944         phy_bcm542xx_direct_reg_modify(unit, pc,
   5945                          PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_MSB(dev_port), 
   5946                          (uint16)((conf->tx_timestamp_offset >> 16) & 0xf ),
   5947                          PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_TX_MSB);
   5948     }
   5949 
   5950     /* RX TS OFFSET */
   5951     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET ) {
   5952         phy_bcm542xx_direct_reg_write(unit, pc,
   5953                          PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_LSB(dev_port), 
   5954                          (uint16)(conf->rx_timestamp_offset & 0xffff));
   5955         phy_bcm542xx_direct_reg_modify(unit, pc,
   5956                          PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_MSB(dev_port), 
   5957                          (uint16)((conf->rx_timestamp_offset >> 16) & 0xf),
   5958                          PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_RX_MSB);
   5959     }
   5960 
   5961     /* Tx Event Message Mode  for  Message 0-3 */
   5962     /*                           ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) */
   5963     data16 = mask16 = 0;
   5964     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE ) {
   5965         phy_bcm542xx_encode_egress_message_mode(conf->tx_sync_mode,
   5966                          0, &data16, &mask16);
   5967     }
   5968     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE ) {
   5969         phy_bcm542xx_encode_egress_message_mode(conf->tx_delay_request_mode,
   5970                          2, &data16, &mask16);
   5971     }
   5972     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE ) {
   5973         phy_bcm542xx_encode_egress_message_mode(conf->tx_pdelay_request_mode,
   5974                          4, &data16, &mask16);
   5975     }
   5976     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE ) {
   5977         phy_bcm542xx_encode_egress_message_mode(conf->tx_pdelay_response_mode,
   5978                          6, &data16, &mask16);
   5979     }
   5980     /* P1588 Port_n TX Event Message Mode1/2 Selection Reg., RDB.0xa11+(n) */
   5981     phy_bcm542xx_direct_reg_modify(unit, pc,
   5982                          PHY_BCM542XX_TOP_1588_TX_MODE_PORT_N_OFFSET(dev_port),
   5983                          data16, mask16);
   5984 
   5985     /* Rx Event Message Mode  for  Message 0-3 */
   5986     /*                           ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) */
   5987     data16 = mask16 = 0;
   5988     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE ) {
   5989         phy_bcm542xx_encode_ingress_message_mode(conf->rx_sync_mode,
   5990                          0, &data16, &mask16);
   5991     }
   5992     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE ) {
   5993         phy_bcm542xx_encode_ingress_message_mode(conf->rx_delay_request_mode,
   5994                          2, &data16, &mask16);
   5995     }
   5996     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE ) {
   5997         phy_bcm542xx_encode_ingress_message_mode(conf->rx_pdelay_request_mode,
   5998                          4, &data16, &mask16);
   5999     }
   6000     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE ) {
   6001         phy_bcm542xx_encode_ingress_message_mode(conf->rx_pdelay_response_mode,
   6002                          6, &data16, &mask16);
   6003     }
   6004     /* P1588 Port_n RX Event Message Mode1/2 Selection Reg., RDB.0xa19+(n) */
   6005     phy_bcm542xx_direct_reg_modify(unit, pc,
   6006                          PHY_BCM542XX_TOP_1588_RX_MODE_PORT_N_OFFSET(dev_port),
   6007                          data16, mask16);
   6008 
   6009     /* DPLL initial reference phase */
   6010     /* P1588 NSE DPLL Register 2 ,  RDB.0xA67-0xA69  (48 bits) */
   6011     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   6012         /* REF_PHASE[15:0] */
   6013         phy_bcm542xx_direct_reg_write(unit, pc,
   6014                          PHY_BCM542XX_TOP_1588_NSE_DPLL_2_0_REG_OFFSET,
   6015                          (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 0xffff));   
   6016         /* REF_PHASE[31:16] */
   6017         phy_bcm542xx_direct_reg_write(unit, pc,
   6018                          PHY_BCM542XX_TOP_1588_NSE_DPLL_2_1_REG_OFFSET,
   6019                          (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 0xffff));   
   6020         /* REF_PHASE[47:32] */    
   6021         phy_bcm542xx_direct_reg_write(unit, pc,
   6022                          PHY_BCM542XX_TOP_1588_NSE_DPLL_2_2_REG_OFFSET,
   6023                          (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 0xffff));
   6024     }
   6025 
   6026     /* P1588 NSE DPLL Register 3 ,  RDB.0xA6A-0xA6B  (32 bits) */
   6027     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) {
   6028         /* Ref phase delta [15:0] */
   6029         phy_bcm542xx_direct_reg_write(unit, pc,
   6030                          PHY_BCM542XX_TOP_1588_NSE_DPLL_3_LSB_REG_OFFSET,
   6031                          (uint16)(conf->phy_1588_dpll_ref_phase_delta & 0xffff));
   6032         /* Ref phase delta [31:16]  */
   6033         phy_bcm542xx_direct_reg_write(unit, pc,
   6034                          PHY_BCM542XX_TOP_1588_NSE_DPLL_3_MSB_REG_OFFSET,
   6035                          (uint16)((conf->phy_1588_dpll_ref_phase_delta >> 16)& 0xffff));
   6036     }
   6037 
   6038     /* P1588 NSE DPLL Register 4/5/6 (K1/K2/K3) ,  RDB.0xA6C/0xA6D/0xA6E */
   6039     /* DPLL K1 */
   6040     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   6041         phy_bcm542xx_direct_reg_write(unit, pc,
   6042                          PHY_BCM542XX_TOP_1588_NSE_DPLL_4_REG_OFFSET,
   6043                          conf->phy_1588_dpll_k1 & 0xff);
   6044     }
   6045 
   6046     /* DPLL K2 */
   6047     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   6048         phy_bcm542xx_direct_reg_write(unit, pc,
   6049                          PHY_BCM542XX_TOP_1588_NSE_DPLL_5_REG_OFFSET,
   6050                          conf->phy_1588_dpll_k2 & 0xff);
   6051     }
   6052 
   6053     /* DPLL K3 */
   6054     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   6055         phy_bcm542xx_direct_reg_write(unit, pc,
   6056                          PHY_BCM542XX_TOP_1588_NSE_DPLL_6_REG_OFFSET,
   6057                          conf->phy_1588_dpll_k3 & 0xff);    
   6058     }
   6059 
   6060     /* P1588 NSE DPLL Register 7 ,  RDB.0xA6F-0xA72  (64 bits) */
   6061     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER) {
   6062         /* Initial loop filter[15:0] */
   6063         phy_bcm542xx_direct_reg_write(unit, pc,
   6064                          PHY_BCM542XX_TOP_1588_NSE_DPLL_7_0_REG_OFFSET,
   6065                          (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_loop_filter) & 0xffff));
   6066         /* Initial loop filter[31:16]  */
   6067         phy_bcm542xx_direct_reg_write(unit, pc,
   6068                          PHY_BCM542XX_TOP_1588_NSE_DPLL_7_1_REG_OFFSET,
   6069                          (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_loop_filter) >> 16) & 0xffff));
   6070 
   6071         /*  Initial loop filter[47:32] */
   6072         phy_bcm542xx_direct_reg_write(unit, pc,
   6073                          PHY_BCM542XX_TOP_1588_NSE_DPLL_7_2_REG_OFFSET,
   6074                          (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_loop_filter) & 0xffff));
   6075  
   6076 
   6077         /* Initial loop filter[63:48]  */
   6078         phy_bcm542xx_direct_reg_write(unit, pc,
   6079                          PHY_BCM542XX_TOP_1588_NSE_DPLL_7_3_REG_OFFSET,
   6080                          (uint16)((COMPILER_64_HI(conf->phy_1588_dpll_loop_filter) >> 16) & 0xffff));
   6081     }
   6082 
   6083     /* P1588 MPLS */
   6084     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL ) {
   6085         /* MPLS controls */
   6086         if ( conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE ) {
   6087             mpls_control_reg_tx |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN;
   6088             mpls_control_reg_rx |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN;
   6089         }
   6090 
   6091         if (!(conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE) ) {
   6092             mpls_control_reg_tx |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS;
   6093             mpls_control_reg_rx |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS;
   6094         }
   6095 
   6096         if ( conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE ) {
   6097             mpls_control_reg_tx |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN;
   6098             mpls_control_reg_rx |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN;
   6099         }
   6100 
   6101         if ( conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE ) {
   6102             mpls_control_reg_tx |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_SP_LBL_EN; 
   6103             mpls_control_reg_rx |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_SP_LBL_EN;
   6104         }
   6105 
   6106         phy_bcm542xx_direct_reg_modify(unit, pc,
   6107                          PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET, 
   6108                          mpls_control_reg_tx,
   6109                          PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN
   6110                          | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS 
   6111                          | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN
   6112                          | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_SP_LBL_EN);
   6113 
   6114 
   6115         phy_bcm542xx_direct_reg_modify(unit, pc,
   6116                          PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET, 
   6117                          mpls_control_reg_rx,
   6118                          PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN
   6119                          | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS 
   6120                          | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN
   6121                          | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_SP_LBL_EN);
   6122 
   6123         for ( i = 0 ; i < conf->mpls_control.size; i++ ) {
   6124             phy_bcm542xx_direct_reg_write( unit, pc,
   6125                     PHY_BCM542XX_TOP_1588_LABEL_N_LSB_MASK_REG_OFFSET(i), 
   6126                     (conf->mpls_control.labels[i].mask & 0xffff) );
   6127             phy_bcm542xx_direct_reg_modify( unit, pc,
   6128                     PHY_BCM542XX_TOP_1588_LABEL_N_MSB_MASK_REG_OFFSET(i), 
   6129                     ((conf->mpls_control.labels[i].mask >> 16) & 0xf), 0xf );
   6130             phy_bcm542xx_direct_reg_write( unit, pc,
   6131                     PHY_BCM542XX_TOP_1588_LABEL_N_LSB_VAL_REG_OFFSET(i), 
   6132                     (conf->mpls_control.labels[i].value & 0xffff) );
   6133             phy_bcm542xx_direct_reg_modify( unit, pc,
   6134                     PHY_BCM542XX_TOP_1588_LABEL_N_MSB_VAL_REG_OFFSET(i), 
   6135                     ((conf->mpls_control.labels[i].value >> 16) & 0xf), 0xf );
   6136             /*Enable comparison for MPLS label value N */
   6137             phy_bcm542xx_direct_reg_modify( unit, pc,
   6138                     PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET,
   6139                     (BIT(6) << i), (BIT(6) << i) );
   6140             phy_bcm542xx_direct_reg_modify( unit, pc,
   6141                     PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET,
   6142                     (BIT(6) << i), (BIT(6) << i) );
   6143         }
   6144     }
   6145 
   6146     /* P1588 direct Timer adjustment */
   6147     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TIMER_ADJUSTMENT ) {
   6148         int val32 = conf->timer_adjust.delta;
   6149 
   6150         /* Timer adjustment delta should be a 14-bit two's complement value */
   6151         if ( val32 > PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MAX ) {
   6152             /* over  the 14-bit range, set the max. */
   6153             data16 = PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MAX;
   6154         } else
   6155         if ( val32 < PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MIN ) {
   6156             /* under the 14-bit range, set the min. */
   6157             data16 = PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MIN;
   6158         } else {
   6159             /* value in range, extract the 14-bit two's complement value */
   6160             data16 = ((uint16 ) val32) &
   6161                      PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MASK;
   6162         }
   6163 
   6164         /* determine which counter to be adjusted, 80- or 48-bit or both */
   6165         if ( conf->timer_adjust.mode &
   6166                                 SOC_PORT_PHY_TIMESYNC_TIMER_MODE_48BIT ) {
   6167             data16 |= PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_48BIT;
   6168         }
   6169         if ( conf->timer_adjust.mode &
   6170                                 SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT ) {
   6171             data16 |= PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_80BIT;
   6172         }
   6173 
   6174         /* P1588 Timestamp Delta Register, RDB.0xAf7 */
   6175         phy_bcm542xx_direct_reg_write(unit, pc,
   6176                 PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_REG_OFFSET, data16);
   6177     }
   6178 
   6179     /* IEEE-1588 Gen-2 Inband operation */
   6180     if ( conf->validity_mask &
   6181                      SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL ) {
   6182         /*
   6183          *  Inband control parameters setting
   6184          */
   6185         data16 = (conf->inband_control.resv0_id
   6186                             << PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_SHIFT)
   6187                  & PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID;
   6188         if ( conf->inband_control.flags &
   6189                         SOC_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE ) {
   6190             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_SYNC_EN;
   6191         }
   6192         if ( conf->inband_control.flags &
   6193                         SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE ) {
   6194             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_DELAY_REQ_EN;
   6195         }
   6196         if ( conf->inband_control.flags &
   6197                         SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE ) {
   6198             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_PDELAY_REQ_EN;
   6199         }
   6200         if ( conf->inband_control.flags &
   6201                         SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE ) {
   6202             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_PDELAY_RESP_EN;
   6203         }
   6204 
   6205         if ( conf->inband_control.flags &
   6206                         SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK ) {
   6207             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_CHECK;
   6208         }
   6209         if ( conf->inband_control.flags &
   6210                         SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE ) {
   6211             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_UPDATE;
   6212         }
   6213         if ( (conf->flags & SOC_PORT_PHY_TIMESYNC_FOLLOW_UP_ASSIST_ENABLE) ||
   6214              (conf->inband_control.flags &
   6215                         SOC_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST) ) {
   6216             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_UPD_FOLLOW_UP |
   6217                       PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_CAP_MODE;
   6218         }
   6219         if ( (conf->flags & SOC_PORT_PHY_TIMESYNC_DELAY_RESP_ASSIST_ENABLE) ||
   6220              (conf->inband_control.flags &
   6221                         SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST) ) {
   6222             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_UPD_DELAY_RSP |
   6223                       PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_CAP_MODE;
   6224         }
   6225         if ( conf->inband_control.flags &
   6226                         SOC_PORT_PHY_TIMESYNC_INBAND_TIMER_MODE_SELECT ) {
   6227             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_SEL;
   6228         }
   6229         if ( conf->inband_control.timer_mode &
   6230                         SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT ) {
   6231             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_SEL;
   6232         }
   6233 
   6234         if ( conf->inband_control.flags &
   6235                         SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR ) {
   6236             data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_IP_ADDR_EN; 
   6237         }
   6238         if ( conf->inband_control.flags &
   6239                         SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR ) {
   6240             data16 |= (PHY_BCM542XX_TOP_1588_INBAND_CNTL_IP_ADDR_EN |
   6241                        PHY_BCM542XX_TOP_1588_INBAND_CNTL_IP_MAC_SEL);
   6242         }
   6243 
   6244         /* P1588 Inband Control Port_n Register, RDB.0xAEE~Af5 */
   6245         phy_bcm542xx_direct_reg_write(unit, pc,
   6246                 PHY_BCM542XX_TOP_1588_INBAND_CNTL_N_REG_OFFSET(dev_port),
   6247                 data16);
   6248 
   6249         /*
   6250          *  MPLS setting for the label_1 mask
   6251          */
   6252         data16 = 0;
   6253         if ( conf->inband_control.flags & 
   6254                         SOC_PORT_PHY_TIMESYNC_INBAND_CAP_SRC_PORT_CLK_ID) {
   6255             data16 |= PHY_BCM542XX_TOP_1588_CAP_SRC_PORT_CLK_ID;
   6256         } 
   6257         if ( conf->inband_control.flags &
   6258                         SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM) {
   6259             data16 |= PHY_BCM542XX_TOP_1588_MATCH_SRC_PORT_NUM;
   6260         } 
   6261         if ( conf->inband_control.flags &
   6262                         SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID) {
   6263             data16 |= PHY_BCM542XX_TOP_1588_MATCH_VLAN_ID;
   6264         }
   6265         mask16 = PHY_BCM542XX_TOP_1588_CAP_SRC_PORT_CLK_ID
   6266                | PHY_BCM542XX_TOP_1588_MATCH_SRC_PORT_NUM
   6267                | PHY_BCM542XX_TOP_1588_MATCH_VLAN_ID;
   6268 
   6269         /* P1588 MPLS label1 mask msb bit, RDB.0xA98, bit[15:13] */
   6270         phy_bcm542xx_direct_reg_modify( unit, pc,
   6271                 PHY_BCM542XX_TOP_1588_LABEL_N_MSB_MASK_REG_OFFSET(dev_port),
   6272                 data16, mask16 );
   6273 
   6274         /*
   6275          *  Timestamp capture enable for Rx & TX
   6276          */
   6277         /* P1588 TX SOP Timestamp Capture Enable, RDB.0xa21 */
   6278         phy_bcm542xx_direct_reg_modify( unit, pc,
   6279                         PHY_BCM542XX_TOP_1588_TX_TS_CAP_REG_OFFSET, 
   6280                         BIT(dev_port), BIT(dev_port) ); 
   6281         /* P1588 RX SOP Timestamp Capture Enable, RDB.0xa22 */
   6282         phy_bcm542xx_direct_reg_modify( unit, pc,
   6283                         PHY_BCM542XX_TOP_1588_RX_TS_CAP_REG_OFFSET, 
   6284                         BIT(dev_port), BIT(dev_port) ); 
   6285 
   6286         /* P1588 RX CF + Insertion Reg., RDB.0xAC0 */
   6287         phy_bcm542xx_direct_reg_modify( unit, pc,
   6288                         PHY_BCM542XX_TOP_1588_RX_CF_REG_OFFSET,
   6289                         PHY_BCM542XX_TOP_1588_RX_CF_UPD(dev_port)
   6290                       | PHY_BCM542XX_TOP_1588_RX_CS_UPD(dev_port),
   6291                         PHY_BCM542XX_TOP_1588_RX_CF_UPD(dev_port)
   6292                       | PHY_BCM542XX_TOP_1588_RX_CS_UPD(dev_port) );
   6293         /* P1588 TX CS Update Reg., RDB.0xAC1 */
   6294         phy_bcm542xx_direct_reg_modify( unit, pc,
   6295                         PHY_BCM542XX_TOP_1588_TX_CS_UPD_REG_OFFSET,
   6296                         PHY_BCM542XX_TOP_1588_TX_CS_UPD_MODE2(dev_port)
   6297                       | PHY_BCM542XX_TOP_1588_TX_CS_UPD_MODE3(dev_port),
   6298                         PHY_BCM542XX_TOP_1588_TX_CS_UPD_MODE2(dev_port)
   6299                       | PHY_BCM542XX_TOP_1588_TX_CS_UPD_MODE3(dev_port) );
   6300         /* P1588 P1588 TIMECODE Select Reg., RDB.0xAC3 */
   6301         phy_bcm542xx_direct_reg_modify( unit, pc,
   6302                         PHY_BCM542XX_TOP_1588_64b_TIMECODE_SEL_REG_OFFSET,
   6303                         PHY_BCM542XX_TOP_1588_64b_TIMECODE_SEL_RX_N(dev_port)
   6304                       | PHY_BCM542XX_TOP_1588_64b_TIMECODE_SEL_TX_N(dev_port),
   6305                         PHY_BCM542XX_TOP_1588_64b_TIMECODE_SEL_RX_N(dev_port)
   6306                       | PHY_BCM542XX_TOP_1588_64b_TIMECODE_SEL_TX_N(dev_port) );
   6307         /* P1588 P1588 DPLL Debug Select Reg., RDB.0xA5B */
   6308         phy_bcm542xx_direct_reg_modify( unit, pc,
   6309                         PHY_BCM542XX_TOP_1588_DPLL_DB_SEL_REG_OFFSET,
   6310                         PHY_BCM542XX_TOP_1588_DPLL_DB_SEL_RSVD,
   6311                         PHY_BCM542XX_TOP_1588_DPLL_DB_SEL_RSVD );
   6312     }/* TIMESYNC_VALID_PHY_1588_INBAND_CONTROL */
   6313 
   6314     /* Tx/Rx gphycore SOP or internal 1588 SOP: Select internal 1588 SOP (1) */
   6315     /* P1588 SOP Selection Register, RDB.0xAF8, TX[7:0] RX[15:8] */
   6316     phy_bcm542xx_direct_reg_modify( unit, pc,
   6317                         PHY_BCM542XX_TOP_1588_SOP_SEL_REG_OFFSET,
   6318                         PHY_BCM542XX_TOP_1588_SOP_SEL_TX_PORT_N(dev_port)
   6319                       | PHY_BCM542XX_TOP_1588_SOP_SEL_RX_PORT_N(dev_port),
   6320                         PHY_BCM542XX_TOP_1588_SOP_SEL_TX_PORT_N(dev_port)
   6321                       | PHY_BCM542XX_TOP_1588_SOP_SEL_RX_PORT_N(dev_port) );
   6322 
   6323     /***********************************************************************
   6324      * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   6325      * To access TOP level registers use phy_id of port0. Now restore back 
   6326      */
   6327     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   6328     
   6329     return SOC_E_NONE;
   6330 }
   6331 
   6332 /*
   6333  * Function:
   6334  *    phy_bcm542xx_timesync_config_get
   6335  * Purpose:
   6336  *
   6337  * Parameters:
   6338  *
   6339  * Returns:
   6340  */
   6341 int
   6342 phy_bcm542xx_timesync_config_get(int unit, soc_port_t port,
   6343                                  soc_port_phy_timesync_config_t *conf)
   6344 {
   6345     uint16 dev_port, tx_control_reg = 0, en_control_reg = 0; 
   6346     uint16 tx_capture_en_reg = 0, rx_capture_en_reg=0, rx_tx_control_reg;
   6347     uint16 nse_nco_6 = 0, nse_nco_2_2 = 0;
   6348     uint16 i, temp1, temp2, temp3, temp4, value, mpls_control_reg_rx; 
   6349     uint16 data16;
   6350 
   6351     soc_port_phy_timesync_global_mode_t  gmode
   6352                                       = SOC_PORT_PHY_TIMESYNC_MODE_FREE;
   6353     soc_port_phy_timesync_framesync_mode_t  framesync_mode
   6354                                       = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1;
   6355     soc_port_phy_timesync_syncout_mode_t  syncout_mode
   6356                                       = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE;
   6357     phy_ctrl_t *pc;
   6358 
   6359     if ( NULL == conf ) {
   6360         return SOC_E_PARAM;
   6361     }
   6362     
   6363     pc = EXT_PHY_SW_STATE(unit, port);
   6364 
   6365     /***********************************************************************
   6366      * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   6367      * To access TOP level registers use phy_id of port0. Override this ports 
   6368      */
   6369     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   6370     
   6371     /* Dev port numbers from 0-7 */
   6372     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   6373     
   6374     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   6375        of the device. For example to enable autogrEEEn on port0, 
   6376        rdb register for port 4 0x808 need to be used. 
   6377        Refer package configuration document.
   6378      */
   6379     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   6380         dev_port += 4;
   6381     }
   6382 
   6383     conf->flags = 0;
   6384 
   6385     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) {
   6386         /* SLICE ENABLE CONTROL register */
   6387         phy_bcm542xx_direct_reg_read(unit, pc,
   6388                          PHY_BCM542XX_TOP_1588_SLICE_EN_CTRL_REG_OFFSET, 
   6389                          &en_control_reg); 
   6390 
   6391         /* Tx & Rx (+8) */
   6392         if ( (en_control_reg & BIT(dev_port)) &&
   6393              (en_control_reg & BIT(dev_port + 8)) ) {
   6394             conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE;
   6395         }
   6396 
   6397         /* TxRx SOP TS CAPTURE ENABLE reg */
   6398         phy_bcm542xx_direct_reg_read(unit, pc,
   6399                          PHY_BCM542XX_TOP_1588_TX_TS_CAP_REG_OFFSET, 
   6400                          &tx_capture_en_reg);
   6401 
   6402         phy_bcm542xx_direct_reg_read(unit, pc,
   6403                          PHY_BCM542XX_TOP_1588_RX_TS_CAP_REG_OFFSET, 
   6404                          &rx_capture_en_reg); 
   6405 
   6406         if ( (tx_capture_en_reg & BIT(dev_port)) &&
   6407              (rx_capture_en_reg & BIT(dev_port)) ) {
   6408             conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE;
   6409         }
   6410 
   6411         /* P1588 NSE DPLL NCO Register 6, RDB.0xA7F */
   6412         /*                GMODE[15:14] FRAMESYNC_MODE[5:2] SYNC_OUT_MODE[1:0] */
   6413         phy_bcm542xx_direct_reg_read(unit, pc,
   6414                          PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET,
   6415                          &nse_nco_6);
   6416 
   6417         if ( nse_nco_6 & PHY_BCM542XX_TOP_1588_NSE_NCO_6_TS_CAP) {
   6418             conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE;
   6419         }
   6420 
   6421         /* RX TX CONTROL register */
   6422         phy_bcm542xx_direct_reg_read(unit, pc,
   6423                          PHY_BCM542XX_TOP_1588_RX_TX_CTL_REG_OFFSET,
   6424                          &rx_tx_control_reg);
   6425 
   6426         if ( rx_tx_control_reg & PHY_BCM542XX_TOP_1588_RX_TX_CTL_REG_RX_CRC_EN ) {
   6427             conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE;
   6428         }
   6429 
   6430         /* TX CONTROL register */
   6431         phy_bcm542xx_direct_reg_read(unit, pc,
   6432                          PHY_BCM542XX_TOP_1588_TX_CTL_REG_OFFSET,
   6433                          &tx_control_reg);
   6434                                           
   6435         if ( tx_control_reg & PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_AS_EN ) {
   6436             conf->flags |= SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE;
   6437         }
   6438 
   6439         if ( tx_control_reg & PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_L2_EN ) {
   6440             conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE;
   6441         }
   6442 
   6443         if ( tx_control_reg & PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_IPV4_UDP_EN ) {
   6444             conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE;
   6445         }
   6446 
   6447         if ( tx_control_reg & PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_IPV6_UDP_EN ) {
   6448             conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE;
   6449         }
   6450         phy_bcm542xx_direct_reg_read(unit, pc,
   6451                          PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_REG_OFFSET,
   6452                          &nse_nco_2_2);
   6453 
   6454         if ( !(nse_nco_2_2 & PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_FREQ_MDIO_SEL) ) {
   6455             conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT;
   6456         }
   6457     }
   6458 
   6459     /* P1588 NSE DPLL NCO Register 6, RDB.0xA7F */
   6460     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE ) {
   6461         /* P1588 NSE DPLL NCO Reg.6, bit[15:14] Global sync mode selection */
   6462         phy_bcm542xx_decode_gmode((nse_nco_6 >> 14), &gmode);
   6463         conf->gmode = gmode;
   6464     }
   6465 
   6466     /* framesync */
   6467     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE ) {
   6468         /* P1588 NSE DPLL NCO Reg.6, FRAMESYNC_MODE[5:2] */
   6469         phy_bcm542xx_decode_framesync_mode((nse_nco_6 >> 2), &framesync_mode);
   6470         conf->framesync.mode = framesync_mode;
   6471 
   6472         /* P1588 NSE DPLL NCO Register 7, RDB.0xa80-a81 */
   6473         phy_bcm542xx_direct_reg_read(unit, pc,
   6474                          PHY_BCM542XX_1588_NSE_DPLL_NCO_7_0_REG_OFFSET,
   6475                          &value);
   6476         conf->framesync.length_threshold = value;
   6477         phy_bcm542xx_direct_reg_read(unit, pc,
   6478                          PHY_BCM542XX_1588_NSE_DPLL_NCO_7_1_REG_OFFSET,
   6479                          &value);
   6480         conf->framesync.event_offset = value;
   6481     }
   6482 
   6483     /* Syncout */
   6484     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE ) {
   6485         /* P1588 NSE DPLL NCO Reg.6, SYNC_OUT_MODE[1:0] */
   6486         phy_bcm542xx_decode_sync_out_mode((nse_nco_6 ), &syncout_mode); 
   6487         conf->syncout.mode = syncout_mode;
   6488 
   6489         /* TOP_1588_NSE_NCO_3 - P1588 NSE DPLL NCO Register 3, RDB.0xa78-a7a */
   6490         phy_bcm542xx_direct_reg_read(unit, pc,
   6491                          PHY_BCM542XX_TOP_1588_NSE_NCO_3_0_REG_OFFSET,
   6492                          &temp1);
   6493         phy_bcm542xx_direct_reg_read(unit, pc,
   6494                          PHY_BCM542XX_TOP_1588_NSE_NCO_3_1_REG_OFFSET,
   6495                          &temp2);
   6496         phy_bcm542xx_direct_reg_read(unit, pc,
   6497                          PHY_BCM542XX_TOP_1588_NSE_NCO_3_2_REG_OFFSET,
   6498                          &temp3);
   6499         /* PULSE_TRAIN_LENGTH */
   6500         conf->syncout.pulse_1_length = ((temp3 & 0x7f) << 2)
   6501                                      | ((temp2 >> 14) & 0x3);
   6502         /* FRMSYNC_PULSE_LENGTH */
   6503         conf->syncout.pulse_2_length = (temp3 >> 7) & 0x1ff;
   6504         /* INTERVAL_LENGTH */
   6505         conf->syncout.interval =  ((temp2 & 0x3fff) << 16) | temp1;
   6506 
   6507         /* TOP_1588_NSE_NCO_5_0 - P1588 NSE DPLL NCO Register, RDB.0xa7c-a7e */
   6508         phy_bcm542xx_direct_reg_read(unit, pc,
   6509                          PHY_BCM542XX_TOP_1588_NSE_NCO_5_0_REG_OFFSET,
   6510                          &temp1);
   6511         phy_bcm542xx_direct_reg_read(unit, pc,
   6512                          PHY_BCM542XX_TOP_1588_NSE_NCO_5_1_REG_OFFSET,
   6513                          &temp2);
   6514         phy_bcm542xx_direct_reg_read(unit, pc,
   6515                          PHY_BCM542XX_TOP_1588_NSE_NCO_5_2_REG_OFFSET,
   6516                          &temp3);
   6517         /* SYNOUT_TS_REG (48 bits, but only [47:4] are useful)
   6518            time interval to trigger SYNC pulse                  */
   6519         COMPILER_64_SET( conf->syncout.syncout_ts, ((uint32)temp3),
   6520                          (((uint32)temp2 << 16) | ((uint32)temp1)) );
   6521     }
   6522 
   6523     /* VLAN Tags */
   6524     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID ) {
   6525 
   6526         phy_bcm542xx_direct_reg_read(unit, pc,
   6527                          PHY_BCM542XX_TOP_1588_VLAN_ITPID_REG_OFFSET, 
   6528                          &conf->itpid); 
   6529     }
   6530     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID ) {
   6531 
   6532         phy_bcm542xx_direct_reg_read(unit, pc,
   6533                          PHY_BCM542XX_TOP_1588_VLAN_OTPID_REG_OFFSET, 
   6534                          &conf->otpid); 
   6535     }
   6536     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2 ) {
   6537         phy_bcm542xx_direct_reg_read(unit, pc,
   6538                          PHY_BCM542XX_TOP_1588_OTHER_OTPID_REG_OFFSET,
   6539                          &conf->otpid2); 
   6540     }
   6541     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER ) {
   6542         phy_bcm542xx_direct_reg_read(unit, pc,
   6543                          PHY_BCM542XX_TOP_1588_NSE_NCO_4_REG_OFFSET,
   6544                          &conf->ts_divider); 
   6545     }
   6546     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY ) {
   6547         phy_bcm542xx_direct_reg_read(unit, pc,
   6548                          PHY_BCM542XX_TOP_1588_RX_PORTN_LINK_DELAY_LSB(dev_port),
   6549                          &temp1); 
   6550         phy_bcm542xx_direct_reg_read(unit, pc,
   6551                          PHY_BCM542XX_TOP_1588_RX_PORTN_LINK_DELAY_MSB(dev_port),
   6552                          &temp2);
   6553         conf->rx_link_delay = ((uint32)temp2 << 16) | temp1; 
   6554     }
   6555 
   6556     /* TIMECODE */
   6557     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE ) {
   6558         /* P1588 Original Time Code Register 0-4 (80 bits), RDB.0xa54-a58 */
   6559         phy_bcm542xx_direct_reg_read(unit, pc,
   6560                          PHY_BCM542XX_TOP_1588_TIME_CODE_0_REG_OFFSET, 
   6561                          &temp1);
   6562         phy_bcm542xx_direct_reg_read(unit, pc,
   6563                          PHY_BCM542XX_TOP_1588_TIME_CODE_1_REG_OFFSET, 
   6564                          &temp2);
   6565         conf->original_timecode.nanoseconds = ((uint32)temp2 << 16) | temp1;
   6566 
   6567         phy_bcm542xx_direct_reg_read(unit, pc,
   6568                          PHY_BCM542XX_TOP_1588_TIME_CODE_2_REG_OFFSET, 
   6569                          &temp1);
   6570         phy_bcm542xx_direct_reg_read(unit, pc,
   6571                          PHY_BCM542XX_TOP_1588_TIME_CODE_3_REG_OFFSET, 
   6572                          &temp2);
   6573         phy_bcm542xx_direct_reg_read(unit, pc,
   6574                          PHY_BCM542XX_TOP_1588_TIME_CODE_4_REG_OFFSET, 
   6575                          &temp3);
   6576         COMPILER_64_SET( conf->original_timecode.seconds, ((uint32)temp3),
   6577                          (((uint32)temp2 << 16) | ((uint32)temp1)) );
   6578     }
   6579 
   6580     /* TX TS OFFSET */
   6581     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET ) {
   6582         phy_bcm542xx_direct_reg_read(unit, pc,
   6583                          PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_LSB(dev_port), 
   6584                          &temp1);
   6585         phy_bcm542xx_direct_reg_read(unit, pc,
   6586                          PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_MSB(dev_port), 
   6587                          &temp2);
   6588         conf->tx_timestamp_offset = ((temp2 & 0xf) << 16) | temp1;
   6589     }   
   6590 
   6591     /* RX TS OFFSET */
   6592     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET ) {
   6593         phy_bcm542xx_direct_reg_read(unit, pc,
   6594                          PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_LSB(dev_port), 
   6595                          &temp1);
   6596         phy_bcm542xx_direct_reg_read(unit, pc,
   6597                          PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_MSB(dev_port), 
   6598                          &temp2);
   6599         conf->rx_timestamp_offset = ((temp2 & 0xf) << 16) | temp1;
   6600     }
   6601 
   6602     /* P1588 Port_n TX Event Message Mode1/2 Selection Reg., RDB.0xa11+(n) */
   6603     phy_bcm542xx_direct_reg_read(unit, pc,
   6604                          PHY_BCM542XX_TOP_1588_TX_MODE_PORT_N_OFFSET(dev_port),
   6605                          &value);
   6606     /* Tx Event Message Mode  for  Message 0-3 */
   6607     /*                           ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) */
   6608     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE ) {
   6609         phy_bcm542xx_decode_egress_message_mode(value, 0, &conf->tx_sync_mode);
   6610     }
   6611     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE ) {
   6612         phy_bcm542xx_decode_egress_message_mode(value, 2, &conf->tx_delay_request_mode);
   6613     }
   6614     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE ) {
   6615         phy_bcm542xx_decode_egress_message_mode(value, 4, &conf->tx_pdelay_request_mode);
   6616     }
   6617     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE ) {
   6618         phy_bcm542xx_decode_egress_message_mode(value, 6, &conf->tx_pdelay_response_mode);
   6619     }
   6620 
   6621     /* P1588 Port_n RX Event Message Mode1/2 Selection Reg., RDB.0xa19+(n) */
   6622     phy_bcm542xx_direct_reg_read(unit, pc,
   6623                          PHY_BCM542XX_TOP_1588_RX_MODE_PORT_N_OFFSET(dev_port),
   6624                          &value);
   6625     /* Rx Event Message Mode  for  Message 0-3 */
   6626     /*                           ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) */
   6627     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE ) {
   6628         phy_bcm542xx_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode);
   6629     }
   6630     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE ) {
   6631         phy_bcm542xx_decode_ingress_message_mode(value, 2, &conf->rx_delay_request_mode);
   6632     }
   6633     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE ) {
   6634         phy_bcm542xx_decode_ingress_message_mode(value, 4, &conf->rx_pdelay_request_mode);
   6635     }
   6636     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE ) {
   6637         phy_bcm542xx_decode_ingress_message_mode(value, 6, &conf->rx_pdelay_response_mode);
   6638     }
   6639 
   6640     /* DPLL initial reference phase */
   6641     /* P1588 NSE DPLL Register 2 ,  RDB.0xA67-0xA69  (48 bits) */
   6642     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) {
   6643         /*[15:0]*/
   6644         phy_bcm542xx_direct_reg_read(unit, pc,
   6645                          PHY_BCM542XX_TOP_1588_NSE_DPLL_2_0_REG_OFFSET,
   6646                          &temp1);   
   6647         /*[31:16]*/
   6648         phy_bcm542xx_direct_reg_read(unit, pc,
   6649                          PHY_BCM542XX_TOP_1588_NSE_DPLL_2_1_REG_OFFSET,
   6650                          &temp2);   
   6651         /*[47:32]*/    
   6652         phy_bcm542xx_direct_reg_read(unit, pc,
   6653                          PHY_BCM542XX_TOP_1588_NSE_DPLL_2_2_REG_OFFSET,
   6654                          &temp3);
   6655         COMPILER_64_SET( conf->phy_1588_dpll_ref_phase, ((uint32)temp3),
   6656                          (((uint32)temp2 << 16) | ((uint32)temp1)) );
   6657     }
   6658 
   6659     /* P1588 NSE DPLL Register 3 ,  RDB.0xA6A-0xA6B  (32 bits) */
   6660     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA ) {
   6661             /* Ref phase delta [15:0] */
   6662             phy_bcm542xx_direct_reg_read(unit, pc,
   6663                              PHY_BCM542XX_TOP_1588_NSE_DPLL_3_LSB_REG_OFFSET,
   6664                              &temp1);
   6665             /* Ref phase delta [31:16]  */
   6666             phy_bcm542xx_direct_reg_read(unit, pc,
   6667                              PHY_BCM542XX_TOP_1588_NSE_DPLL_3_MSB_REG_OFFSET,
   6668                              &temp2);
   6669             conf->phy_1588_dpll_ref_phase_delta = (temp2 << 16) | temp1;
   6670     }
   6671 
   6672     /* P1588 NSE DPLL Register 4/5/6 (K1/K2/K3) ,  RDB.0xA6C/0xA6D/0xA6E */
   6673     /* DPLL K1 */
   6674     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) {
   6675         phy_bcm542xx_direct_reg_read(unit, pc,
   6676                          PHY_BCM542XX_TOP_1588_NSE_DPLL_4_REG_OFFSET,
   6677                          &temp1);
   6678         conf->phy_1588_dpll_k1 = temp1 & 0xff;
   6679     }
   6680 
   6681     /* DPLL K2 */
   6682     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) {
   6683         phy_bcm542xx_direct_reg_read(unit, pc,
   6684                          PHY_BCM542XX_TOP_1588_NSE_DPLL_5_REG_OFFSET,
   6685                          &temp1);
   6686         conf->phy_1588_dpll_k2 = temp1 & 0xff;
   6687     }
   6688 
   6689     /* DPLL K3 */
   6690     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) {
   6691         phy_bcm542xx_direct_reg_read(unit, pc,
   6692                          PHY_BCM542XX_TOP_1588_NSE_DPLL_6_REG_OFFSET,
   6693                          &temp1);
   6694         conf->phy_1588_dpll_k3 = temp1 & 0xff;
   6695     }
   6696 
   6697     /* P1588 NSE DPLL Register 7 ,  RDB.0xA6F-0xA72  (64 bits) */
   6698     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER ) {
   6699         /* Initial loop filter[15:0] */
   6700         phy_bcm542xx_direct_reg_read(unit, pc,
   6701                          PHY_BCM542XX_TOP_1588_NSE_DPLL_7_0_REG_OFFSET,
   6702                          &temp1);
   6703         /* Initial loop filter[31:16]  */
   6704         phy_bcm542xx_direct_reg_read(unit, pc,
   6705                          PHY_BCM542XX_TOP_1588_NSE_DPLL_7_1_REG_OFFSET,
   6706                          &temp2);
   6707         /*  Initial loop filter[47:32] */
   6708         phy_bcm542xx_direct_reg_read(unit, pc,
   6709                          PHY_BCM542XX_TOP_1588_NSE_DPLL_7_2_REG_OFFSET,
   6710                          &temp3);
   6711         /* Initial loop filter[63:48]  */
   6712         phy_bcm542xx_direct_reg_read(unit, pc,
   6713                          PHY_BCM542XX_TOP_1588_NSE_DPLL_7_3_REG_OFFSET,
   6714                          &temp4);
   6715         COMPILER_64_SET( conf->phy_1588_dpll_loop_filter,
   6716                          (((uint32)temp4 << 16) | ((uint32)temp3)),
   6717                          (((uint32)temp2 << 16) | ((uint32)temp1)) );
   6718     }
   6719 
   6720     /* P1588 MPLS */
   6721     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) {
   6722         /* MPLS controls */
   6723 #if 0
   6724         phy_bcm542xx_direct_reg_read(unit, pc,
   6725                          PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET, 
   6726                          &mpls_control_reg_tx);
   6727 #endif
   6728         phy_bcm542xx_direct_reg_read(unit, pc,
   6729                          PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET, 
   6730                          &mpls_control_reg_rx);
   6731 
   6732         if ( (mpls_control_reg_rx & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN)
   6733             /*&& (mpls_control_reg_tx & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN)*/) {
   6734             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE;
   6735         }
   6736         if ( !(mpls_control_reg_rx & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS))
   6737             /*&& (mpls_control_reg_tx & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS)*/ {
   6738             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE;
   6739         }
   6740         if ( (mpls_control_reg_rx & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN)
   6741             /*&& (mpls_control_reg_tx & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN)*/) {
   6742             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE;
   6743         }
   6744         if ( (mpls_control_reg_rx & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_SP_LBL_EN)
   6745             /*&& (mpls_control_reg_tx & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_SP_LBL_EN)*/) {
   6746             conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE;
   6747         }
   6748 
   6749         for ( i = 0 ; i < conf->mpls_control.size; i++ ) {
   6750             phy_bcm542xx_direct_reg_read( unit, pc,
   6751                     PHY_BCM542XX_TOP_1588_LABEL_N_LSB_MASK_REG_OFFSET(i), 
   6752                     &temp1 );
   6753             conf->mpls_control.labels[i].mask = temp1;
   6754             phy_bcm542xx_direct_reg_read( unit, pc,
   6755                     PHY_BCM542XX_TOP_1588_LABEL_N_MSB_MASK_REG_OFFSET(i), 
   6756                     &temp1 );
   6757             conf->mpls_control.labels[i].mask |= (temp1 & 0xf) << 16;
   6758 
   6759             phy_bcm542xx_direct_reg_read( unit, pc,
   6760                     PHY_BCM542XX_TOP_1588_LABEL_N_LSB_VAL_REG_OFFSET(i), 
   6761                     &temp1 );
   6762             conf->mpls_control.labels[i].value = temp1;
   6763             phy_bcm542xx_direct_reg_read( unit, pc,
   6764                     PHY_BCM542XX_TOP_1588_LABEL_N_MSB_VAL_REG_OFFSET(i), 
   6765                     &temp1 );
   6766             conf->mpls_control.labels[i].value |= (temp1 & 0xf) << 16;
   6767         }
   6768     }
   6769 
   6770     /* P1588 direct Timer adjustment */
   6771     if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TIMER_ADJUSTMENT ) {
   6772         uint16  val16;
   6773         /* P1588 Timestamp Delta Register, RDB.0xAf7 */
   6774         phy_bcm542xx_direct_reg_read(unit, pc,
   6775                 PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_REG_OFFSET, &data16);
   6776 
   6777         /* Timestamp Delta Reg. bit[13:0] = Timer adjustment delta value */
   6778         val16 = data16 & PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MASK;
   6779         /* Timer adjustment delta is a 14-bit two's complement value */
   6780         if ( val16 & PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_SIGN ) {
   6781             /* sign extension if negative */
   6782             val16 |= PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_SIGN_EXT;
   6783         }
   6784         conf->timer_adjust.delta = (int) val16;
   6785 
   6786         if ( data16 & PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_48BIT ) {
   6787             conf->timer_adjust.mode |= SOC_PORT_PHY_TIMESYNC_TIMER_MODE_48BIT;
   6788         }
   6789         if ( data16 & PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_80BIT ) {
   6790             conf->timer_adjust.mode |= SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT;
   6791         }
   6792     }
   6793 
   6794     /* IEEE-1588 Gen-2 Inband operations */
   6795     if ( (conf->validity_mask &
   6796                 SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL) ) {
   6797         /* P1588 Inband Control Port_n Register, RDB.0xAEE~Af5 */
   6798         phy_bcm542xx_direct_reg_read(unit, pc,
   6799                 PHY_BCM542XX_TOP_1588_INBAND_CNTL_N_REG_OFFSET(dev_port),
   6800                 &data16);
   6801         conf->inband_control.resv0_id =         /* Rev0_ID[7:4] */
   6802                 (data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID)
   6803                  >> PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_SHIFT;
   6804 
   6805         if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_SYNC_EN ) {
   6806             conf->inband_control.flags |=
   6807                 SOC_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE;
   6808         }
   6809         if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_DELAY_REQ_EN ) {
   6810             conf->inband_control.flags |=
   6811                 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE;
   6812         }
   6813         if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_PDELAY_REQ_EN ) {
   6814             conf->inband_control.flags |=
   6815                 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE;
   6816         }
   6817         if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_PDELAY_RESP_EN ) {
   6818             conf->inband_control.flags |=
   6819                 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE;
   6820         }
   6821 
   6822         if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_CHECK ) {
   6823             conf->inband_control.flags |=
   6824                 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK;
   6825         }
   6826         if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_UPDATE ) {
   6827             conf->inband_control.flags |=
   6828                 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE;
   6829         }
   6830         if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_UPD_FOLLOW_UP ) {
   6831             conf->inband_control.flags |=
   6832                 SOC_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST;
   6833             conf->flags |=
   6834                 SOC_PORT_PHY_TIMESYNC_FOLLOW_UP_ASSIST_ENABLE;
   6835         }
   6836         if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_UPD_DELAY_RSP ) {
   6837             conf->inband_control.flags |=
   6838                 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST;
   6839             conf->flags |=
   6840                 SOC_PORT_PHY_TIMESYNC_DELAY_RESP_ASSIST_ENABLE;
   6841         }
   6842         if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_SEL ) {
   6843             conf->inband_control.timer_mode |=
   6844                       SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT;
   6845         } else {
   6846             conf->inband_control.timer_mode |=
   6847                       SOC_PORT_PHY_TIMESYNC_TIMER_MODE_48BIT;
   6848         }
   6849         if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_IP_ADDR_EN ) {
   6850             if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_IP_MAC_SEL ) {
   6851                 conf->inband_control.flags |=
   6852                       SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR;
   6853             } else {
   6854                 conf->inband_control.flags |=
   6855                       SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR;
   6856             }
   6857         }
   6858 
   6859         /* P1588 MPLS label1 mask msb bit, RDB.0xA98, bit[15:13] */
   6860         phy_bcm542xx_direct_reg_read(unit, pc,
   6861                 PHY_BCM542XX_TOP_1588_LABEL_N_MSB_MASK_REG_OFFSET(dev_port),
   6862                 &data16);
   6863         if ( data16 & PHY_BCM542XX_TOP_1588_CAP_SRC_PORT_CLK_ID ) {
   6864             conf->inband_control.flags |=
   6865                 SOC_PORT_PHY_TIMESYNC_INBAND_CAP_SRC_PORT_CLK_ID;
   6866         }
   6867         if ( data16 & PHY_BCM542XX_TOP_1588_MATCH_SRC_PORT_NUM ) {
   6868             conf->inband_control.flags |=
   6869                 PHY_BCM542XX_TOP_1588_MATCH_SRC_PORT_NUM;
   6870         }
   6871         if ( data16 & PHY_BCM542XX_TOP_1588_MATCH_VLAN_ID ) {
   6872             conf->inband_control.flags |=
   6873                 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID;
   6874         }
   6875     }/* SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL */
   6876 
   6877     /* TOP LEVEL REGISTER ACCESS -> RESTORE                                 *\
   6878     \* To access TOP level registers use phy_id of port0. Now restore back  */
   6879     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   6880 
   6881     return SOC_E_NONE;
   6882 }
   6883 
   6884 /*
   6885  * Function:
   6886  *    phy_bcm542xx_timesync_control_set
   6887  * Purpose:
   6888  *
   6889  * Parameters:
   6890  *
   6891  * Returns:
   6892  */
   6893 int
   6894 phy_bcm542xx_timesync_control_set(int unit, soc_port_t port,
   6895                                   soc_port_control_phy_timesync_t type,
   6896                                   uint64 value)
   6897 {
   6898     int          rv = SOC_E_NONE;
   6899     uint16       dev_port, temp1, temp2;
   6900     uint32       value32;
   6901     phy_ctrl_t  *pc;
   6902 
   6903     pc = EXT_PHY_SW_STATE(unit, port);
   6904 
   6905     /***********************************************************************
   6906      * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   6907      * To access TOP level registers use phy_id of port0. Override this ports 
   6908      */
   6909     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   6910     
   6911     /* Dev port numbers from 0-7 */
   6912     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   6913     
   6914     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   6915        of the device. For example to enable autogrEEEn on port0, 
   6916        rdb register for port 4 0x808 need to be used. 
   6917        Refer package configuration document.
   6918      */
   6919     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   6920         dev_port += 4;
   6921     }
   6922 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
   6923     PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc);   /* set RDB register access mode */
   6924 #endif
   6925 
   6926     switch ( type ) {
   6927     case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
   6928         /* TOP_1588_HEARTBEAT, Heartbeat (48 bits), RDB.0xa86-0xa88 */
   6929     case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
   6930         /* TOP_1588_TIME_STAMP, Tx Timestamp (48 bits), RDB.0xa89-0xa8b */
   6931         return SOC_E_FAIL;    /* read-only registers */
   6932 
   6933     case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC:
   6934         /* P1588 NSE DPLL NCO Register 6, RDB.0xA7F[5:2] FRAMESYNC_MODE */
   6935         SOC_IF_ERROR_BREAK(
   6936             phy_bcm542xx_rdb_reg_modify(unit, pc,
   6937                         PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET,
   6938                         (COMPILER_64_LO(value) & 0x0f) << 2, (0x0f << 2)), rv );
   6939         break;
   6940 
   6941     case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
   6942        /* TOP_1588_NSE_NCO_1, NSE_REG_NCO_FREQCNTR (32 bits), RDB.0xa73-0xa74 */
   6943         SOC_IF_ERROR_BREAK(
   6944             phy_bcm542xx_rdb_reg_write(unit, pc,    /* LSB 16 bits */
   6945                         PHY_BCM542XX_TOP_1588_NSE_NCO_1_0_REG_OFFSET,
   6946                         (uint16) (COMPILER_64_LO(value) & 0xffff)), rv );
   6947         SOC_IF_ERROR_BREAK(
   6948             phy_bcm542xx_rdb_reg_write(unit, pc,    /* MSB 16 bits */
   6949                         PHY_BCM542XX_TOP_1588_NSE_NCO_1_1_REG_OFFSET,
   6950                         (uint16) ((COMPILER_64_LO(value) >> 16) & 0xffff)), rv);
   6951         break;
   6952 
   6953     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
   6954         /* TOP_1588_NSE_NCO_2, Local Time (44 bits), RDB.0xa75-0xa77 */
   6955         SOC_IF_ERROR_BREAK(
   6956             phy_bcm542xx_rdb_reg_write(unit, pc,
   6957                         PHY_BCM542XX_TOP_1588_NSE_NCO_2_0_REG_OFFSET,
   6958                         (uint16) (COMPILER_64_LO(value) & 0xffff)), rv );
   6959         SOC_IF_ERROR_BREAK(
   6960             phy_bcm542xx_rdb_reg_write(unit, pc,
   6961                         PHY_BCM542XX_TOP_1588_NSE_NCO_2_1_REG_OFFSET,
   6962                         (uint16) ((COMPILER_64_LO(value) >> 16) & 0xffff)), rv);
   6963         SOC_IF_ERROR_BREAK(
   6964             phy_bcm542xx_rdb_reg_modify(unit, pc,
   6965                         PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_REG_OFFSET,
   6966                         (uint16) (COMPILER_64_HI(value) & 0xfff), 0xfff), rv );
   6967         break;
   6968 
   6969     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
   6970         temp1 = temp2 = 0;
   6971         value32 = COMPILER_64_LO(value);
   6972 
   6973         if ( value32 & SOC_PORT_PHY_TIMESYNC_TN_LOAD ) {
   6974            temp1 |= BIT(11);
   6975         }
   6976         if ( value32 & SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD ) {
   6977            temp2 |= BIT(11);
   6978         }
   6979         if ( value32 & SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD ) {
   6980            temp1 |= BIT(10);
   6981         }
   6982         if ( value32 & SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD ) {
   6983            temp2 |= BIT(10);
   6984         }
   6985         if ( value32 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD ) {
   6986            temp1 |= BIT(9);
   6987         }
   6988         if ( value32 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD ) {
   6989            temp2 |= BIT(9);
   6990         }
   6991         if ( value32 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD ) {
   6992            temp1 |= BIT(8);
   6993         }
   6994         if ( value32 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD ) {
   6995            temp2 |= BIT(8);
   6996         }
   6997         if ( value32 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD ) {
   6998            temp1 |= BIT(7);
   6999         }
   7000         if ( value32 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD ) {
   7001            temp2 |= BIT(7);
   7002         }
   7003         if ( value32 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD ) {
   7004            temp1 |= BIT(6);
   7005         }
   7006         if ( value32 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD ) {
   7007            temp2 |= BIT(6);
   7008         }
   7009         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD ) {
   7010            temp1 |= BIT(5);
   7011         }
   7012         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD ) {
   7013            temp2 |= BIT(5);
   7014         }
   7015         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD ) {
   7016            temp1 |= BIT(4);
   7017         }
   7018         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD ) {
   7019            temp2 |= BIT(4);
   7020         }
   7021         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD ) {
   7022            temp1 |= BIT(3);
   7023         }
   7024         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD ) {
   7025            temp2 |= BIT(3);
   7026         }
   7027         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD ) {
   7028            temp1 |= BIT(2);
   7029         }
   7030         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD ) {
   7031            temp2 |= BIT(2);
   7032         }
   7033         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD ) {
   7034            temp1 |= BIT(1);
   7035         }
   7036         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD ) {
   7037            temp2 |= BIT(1);
   7038         }
   7039         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD ) {
   7040            temp1 |= BIT(0);
   7041         }
   7042         if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD ) {
   7043            temp2 |= BIT(0);
   7044         }
   7045 
   7046         SOC_IF_ERROR_BREAK(
   7047             phy_bcm542xx_rdb_reg_write(unit, pc,
   7048                     PHY_BCM542XX_TOP_1588_SHD_LD_REG_OFFSET , temp1), rv );
   7049         SOC_IF_ERROR_BREAK(
   7050             phy_bcm542xx_rdb_reg_write(unit, pc,
   7051                     PHY_BCM542XX_TOP_1588_SHD_CTL_REG_OFFSET, temp2), rv );
   7052         break;
   7053 
   7054     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
   7055         /* disables the interrupt */
   7056         temp1 = 0;
   7057         value32 = COMPILER_64_LO(value);
   7058         if ( value32 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK) {
   7059            temp1 |= BIT((dev_port + 1));
   7060         }
   7061         if ( value32 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK) {
   7062            temp1 |= BIT(0);
   7063         }
   7064         SOC_IF_ERROR_BREAK(
   7065             phy_bcm542xx_rdb_reg_modify(unit, pc,
   7066                     PHY_BCM542XX_TOP_1588_INT_MASK_REG_OFFSET,
   7067                     temp1, BIT((dev_port + 1)) | BIT(0)), rv );
   7068         break;
   7069 
   7070     case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
   7071         value32 = COMPILER_64_LO(value);
   7072         SOC_IF_ERROR_BREAK(
   7073             phy_bcm542xx_rdb_reg_write(unit, pc,
   7074                     PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_LSB(dev_port),
   7075                     (uint16) (value32 & 0xffff)), rv );
   7076         SOC_IF_ERROR_BREAK(
   7077             phy_bcm542xx_rdb_reg_modify(unit, pc,
   7078                     PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_MSB(dev_port),
   7079                     (uint16) ((value32 >> 16) & 0xf ),
   7080                     PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_TX_MSB), rv );
   7081         break;
   7082 
   7083     case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
   7084         value32 = COMPILER_64_LO(value);
   7085         SOC_IF_ERROR_BREAK(
   7086             phy_bcm542xx_rdb_reg_write(unit, pc,
   7087                     PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_LSB(dev_port),
   7088                     (uint16) (value32 & 0xffff)), rv );
   7089         SOC_IF_ERROR_BREAK(
   7090             phy_bcm542xx_rdb_reg_modify(unit, pc,
   7091                     PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_MSB(dev_port),
   7092                     (uint16) ((value32 >> 16) & 0xf),
   7093                     PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_RX_MSB), rv );
   7094         break;
   7095        
   7096     default:
   7097         rv = SOC_E_UNAVAIL;
   7098         break;
   7099     } 
   7100 
   7101 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
   7102     PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */
   7103 #endif
   7104     /* NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE                          */
   7105     /* To access TOP level registers use phy_id of port0. Now restore back */
   7106     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   7107 
   7108     return (rv);
   7109 }
   7110 
   7111 /*
   7112  * Function:
   7113  *    phy_bcm542xx_timesync_control_get
   7114  * Purpose:
   7115  *
   7116  * Parameters:
   7117  *
   7118  * Returns:
   7119  */
   7120 int
   7121 phy_bcm542xx_timesync_control_get(int unit, soc_port_t port,
   7122                                   soc_port_control_phy_timesync_t type,
   7123                                   uint64 *value)
   7124 {
   7125     int          rv = SOC_E_NONE;
   7126     uint32       value32 = 0;
   7127     uint16       dev_port, value0, value1, value2;
   7128 
   7129     phy_ctrl_t  *pc;
   7130 
   7131     pc = EXT_PHY_SW_STATE(unit, port);
   7132 
   7133     /***********************************************************************
   7134      * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   7135      * To access TOP level registers use phy_id of port0. Override this ports 
   7136      */
   7137     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   7138 
   7139     /* Dev port numbers from 0-7 */
   7140     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   7141     
   7142     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   7143        of the device. For example to enable autogrEEEn on port0, 
   7144        rdb register for port 4 0x808 need to be used. 
   7145        Refer package configuration document.
   7146      */
   7147     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   7148         dev_port += 4;
   7149     }
   7150 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
   7151     PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc);   /* set RDB register access mode */
   7152 #endif
   7153 
   7154     switch ( type ) {
   7155     case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP:
   7156         /* P1588 Control/Debug Register, RDB.0xa8e[11:10] HB_CNTL */
   7157         SOC_IF_ERROR_BREAK(
   7158             phy_bcm542xx_rdb_reg_modify(unit, pc,
   7159                   PHY_BCM542XX_TOP_1588_CNTR_DBG_REG_OFFSET,  
   7160                   PHY_BCM542XX_TOP_1588_CNTR_DBG_HB_RD_START,
   7161                   PHY_BCM542XX_TOP_1588_CNTR_DBG_HB_CNTL), rv);
   7162         /* TOP_1588_HEARTBEAT, Heartbeat (48 bits), RDB.0xa86-0xa88 */
   7163         SOC_IF_ERROR_BREAK(
   7164             phy_bcm542xx_rdb_reg_read(unit, pc,
   7165                   PHY_BCM542XX_TOP_1588_HEARTBEAT_0_REG_OFFSET, &value0), rv);
   7166         SOC_IF_ERROR_BREAK(
   7167         phy_bcm542xx_rdb_reg_read(unit, pc,
   7168                   PHY_BCM542XX_TOP_1588_HEARTBEAT_1_REG_OFFSET, &value1), rv);
   7169         SOC_IF_ERROR_BREAK(
   7170             phy_bcm542xx_rdb_reg_read(unit, pc,
   7171                   PHY_BCM542XX_TOP_1588_HEARTBEAT_2_REG_OFFSET, &value2), rv);
   7172         /* P1588 Control/Debug Register, RDB.0xa8e[11:10] HB_CNTL */
   7173         SOC_IF_ERROR_BREAK(
   7174             phy_bcm542xx_rdb_reg_modify(unit, pc,
   7175                   PHY_BCM542XX_TOP_1588_CNTR_DBG_REG_OFFSET,  
   7176                   PHY_BCM542XX_TOP_1588_CNTR_DBG_HB_RD_END,
   7177                   PHY_BCM542XX_TOP_1588_CNTR_DBG_HB_CNTL), rv);
   7178         COMPILER_64_SET( (*value), ((uint32)value2),
   7179                          (((uint32)value1 << 16) | ((uint32)value0)) );
   7180         break;
   7181 
   7182     case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP:
   7183         /* P1588 Control/Debug Register, RDB.0xa8e[9:7] TS_SLICE_SEL */
   7184         SOC_IF_ERROR_BREAK(
   7185             phy_bcm542xx_rdb_reg_modify(unit, pc,
   7186                   PHY_BCM542XX_TOP_1588_CNTR_DBG_REG_OFFSET,  
   7187                   (dev_port << CNTR_DBG_TS_SLICE_SEL_SHIFT),
   7188                   PHY_BCM542XX_TOP_1588_CNTR_DBG_TS_SLICE_SEL), rv);
   7189         /* P1588 Timestamp READ START/END Register, RDB.0xa85 */
   7190         SOC_IF_ERROR_BREAK(
   7191             phy_bcm542xx_rdb_reg_write(unit, pc,
   7192                   PHY_BCM542XX_TOP_1588_TS_RD_START_END_REG_OFFSET,  
   7193                   PHY_BCM542XX_TOP_1588_TS_RD_START(dev_port)), rv);
   7194 
   7195         /* TOP_1588_TIME_STAMP, Tx Timestamp (48 bits), RDB.0xa89-0xa8b */
   7196         SOC_IF_ERROR_BREAK(
   7197             phy_bcm542xx_rdb_reg_read(unit, pc,
   7198                   PHY_BCM542XX_TOP_1588_TIMESTAMP_0_REG_OFFSET, &value0), rv);
   7199         SOC_IF_ERROR_BREAK(
   7200             phy_bcm542xx_rdb_reg_read(unit, pc,
   7201                   PHY_BCM542XX_TOP_1588_TIMESTAMP_1_REG_OFFSET, &value1), rv);
   7202         SOC_IF_ERROR_BREAK(
   7203             phy_bcm542xx_rdb_reg_read(unit, pc,
   7204                   PHY_BCM542XX_TOP_1588_TIMESTAMP_2_REG_OFFSET, &value2), rv);
   7205         SOC_IF_ERROR_BREAK(
   7206 
   7207         /* P1588 Timestamp READ START/END Register, RDB.0xa85 */
   7208         phy_bcm542xx_rdb_reg_write(unit, pc,
   7209                   PHY_BCM542XX_TOP_1588_TS_RD_START_END_REG_OFFSET,  
   7210                   PHY_BCM542XX_TOP_1588_TS_RD_END(dev_port)), rv);
   7211         SOC_IF_ERROR_BREAK(
   7212             phy_bcm542xx_rdb_reg_write(unit, pc,
   7213                   PHY_BCM542XX_TOP_1588_TS_RD_START_END_REG_OFFSET, 0), rv);
   7214 
   7215         COMPILER_64_SET( (*value), ((uint32)value2),
   7216                          (((uint32)value1 << 16) | ((uint32)value0)) );
   7217         break;
   7218 
   7219     case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC:
   7220         /* P1588 NSE DPLL NCO Register 6, RDB.0xA7F[5:2] FRAMESYNC_MODE */
   7221         SOC_IF_ERROR_BREAK(
   7222             phy_bcm542xx_rdb_reg_read(unit, pc,
   7223                   PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET, &value0), rv);
   7224         COMPILER_64_SET( (*value), 0, ((uint32) value0 >> 2) & 0x0f );
   7225         break;
   7226 
   7227     case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND:
   7228         /* TOP_1588_NSE_NCO_1, NSE_REG_NCO_FREQCNTR (32 bits), RDB.0xa73-0xa74 */
   7229         SOC_IF_ERROR_BREAK(
   7230             phy_bcm542xx_rdb_reg_read(unit, pc,
   7231                   PHY_BCM542XX_TOP_1588_NSE_NCO_1_0_REG_OFFSET, &value0), rv);
   7232         SOC_IF_ERROR_BREAK(
   7233             phy_bcm542xx_rdb_reg_read(unit, pc,
   7234                   PHY_BCM542XX_TOP_1588_NSE_NCO_1_1_REG_OFFSET, &value1), rv);
   7235         COMPILER_64_SET( (*value), ((uint32) 0),
   7236                          (((uint32)value1 << 16) | ((uint32)value0)) );
   7237         break;
   7238 
   7239     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME:
   7240         /* TOP_1588_NSE_NCO_2, Local Time (44 bits), RDB.0xa75-0xa77 */
   7241         SOC_IF_ERROR_BREAK(
   7242             phy_bcm542xx_rdb_reg_read(unit, pc,
   7243                   PHY_BCM542XX_TOP_1588_NSE_NCO_2_0_REG_OFFSET, &value0), rv);
   7244         SOC_IF_ERROR_BREAK(
   7245             phy_bcm542xx_rdb_reg_read(unit, pc,
   7246                   PHY_BCM542XX_TOP_1588_NSE_NCO_2_1_REG_OFFSET, &value1), rv);
   7247         SOC_IF_ERROR_BREAK(
   7248             phy_bcm542xx_rdb_reg_read(unit, pc,
   7249                   PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_REG_OFFSET, &value2), rv);
   7250         COMPILER_64_SET( (*value), (value2 & 0x0fff),          /* bit [43:32] */ 
   7251                          ((uint32)value1 << 16) | value0 );    /* bit [31:0]  */
   7252         COMPILER_64_SHL((*value), 4);
   7253         break;
   7254 
   7255     case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL:
   7256         SOC_IF_ERROR_BREAK(
   7257             phy_bcm542xx_rdb_reg_read(unit, pc,
   7258                   PHY_BCM542XX_TOP_1588_SHD_LD_REG_OFFSET , &value1), rv);
   7259         SOC_IF_ERROR_BREAK(
   7260             phy_bcm542xx_rdb_reg_read(unit, pc,
   7261                   PHY_BCM542XX_TOP_1588_SHD_CTL_REG_OFFSET, &value2), rv);
   7262 
   7263         if ( value1 & BIT(11) ) {
   7264             value32 |= SOC_PORT_PHY_TIMESYNC_TN_LOAD;
   7265         }
   7266         if ( value2 & BIT(11) ) {
   7267             value32 |= SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD;
   7268         }
   7269         if ( value1 & BIT(10) ) {
   7270             value32 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD;
   7271         }
   7272         if ( value2 & BIT(10) ) {
   7273             value32 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD;
   7274         }
   7275         if ( value1 & BIT(9) ) {
   7276             value32 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD;
   7277         }
   7278         if ( value2 & BIT(9) ) {
   7279             value32 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD;
   7280         }
   7281         if ( value1 & BIT(8) ) {
   7282             value32 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD;
   7283         }
   7284         if ( value1 & BIT(8) ) {
   7285             value32 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD;
   7286         }
   7287         if ( value1 & BIT(7) ) {
   7288             value32 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD;
   7289         }
   7290         if ( value1 & BIT(7) ) {
   7291             value32 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD;
   7292         }
   7293         if ( value1 & BIT(6) ) {
   7294             value32 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD;
   7295         }
   7296         if ( value2 & BIT(6) ) {
   7297             value32 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD;
   7298         }
   7299         if ( value1 & BIT(5) ) {
   7300             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD;
   7301         }
   7302         if ( value2 & BIT(5) ) {
   7303             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD;
   7304         }
   7305         if ( value1 & BIT(4) ) {
   7306             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD;
   7307         }
   7308         if ( value2 & BIT(4) ) {
   7309             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD;
   7310         }
   7311         if ( value1 & BIT(3) ) {
   7312             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD;
   7313         }
   7314         if ( value2 & BIT(3) ) {
   7315             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD;
   7316         }
   7317         if ( value1 & BIT(2) ) {
   7318             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD;
   7319         }
   7320         if ( value2 & BIT(2) ) {
   7321             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD;
   7322         }
   7323         if ( value1 & BIT(1) ) {
   7324             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD;
   7325         }
   7326         if ( value2 & BIT(1) ) {
   7327             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD;
   7328         }
   7329         if ( value1 & BIT(0) ) {
   7330             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD;
   7331         }
   7332         if ( value2 & BIT(0) ) {
   7333             value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD;
   7334         }
   7335 
   7336         COMPILER_64_SET((*value), (0), (value32));
   7337         break;
   7338  
   7339     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT:
   7340         /* This doesn't clear the interrupts. 
   7341            To clear read the timestamp.
   7342          */
   7343         SOC_IF_ERROR_BREAK(
   7344             phy_bcm542xx_rdb_reg_read(unit, pc,
   7345                     PHY_BCM542XX_TOP_1588_INT_STATUS_REG_OFFSET, &value1), rv);
   7346         if ( value1 & BIT((dev_port + 1)) ) {
   7347             value32 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT;
   7348         }
   7349         if ( value1 & BIT(0) ) {
   7350             value32 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT;
   7351         }
   7352         COMPILER_64_SET((*value), (uint32)((value1 >> 1) & 0xff), (value32));
   7353         break;
   7354 
   7355     case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK:
   7356         SOC_IF_ERROR_BREAK(
   7357             phy_bcm542xx_rdb_reg_read(unit, pc,
   7358                     PHY_BCM542XX_TOP_1588_INT_MASK_REG_OFFSET, &value1), rv);
   7359         if ( value1 & BIT((dev_port + 1)) ) {
   7360             value32 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK;
   7361         }
   7362         if ( value1 & BIT(0) ) {
   7363             value32 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK;
   7364         }
   7365         COMPILER_64_SET((*value), (0), (value32));
   7366         break;
   7367 
   7368     case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET:
   7369         SOC_IF_ERROR_BREAK(
   7370             phy_bcm542xx_rdb_reg_read(unit, pc,
   7371                     PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_LSB(dev_port), 
   7372                     &value1), rv);
   7373         SOC_IF_ERROR_BREAK(
   7374             phy_bcm542xx_rdb_reg_read(unit, pc,
   7375                     PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_MSB(dev_port), 
   7376                     &value2), rv);
   7377         COMPILER_64_SET((*value), 0, (((value2 & 0xf) << 16) | value1)); 
   7378         break;
   7379 
   7380     case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET:
   7381         SOC_IF_ERROR_BREAK(
   7382             phy_bcm542xx_rdb_reg_read(unit, pc,
   7383                     PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_LSB(dev_port), 
   7384                     &value1), rv);
   7385         SOC_IF_ERROR_BREAK(
   7386             phy_bcm542xx_rdb_reg_read(unit, pc,
   7387                     PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_MSB(dev_port), 
   7388                     &value2), rv);
   7389         COMPILER_64_SET((*value), 0, (((value2 & 0xf) << 16) | value1)); 
   7390         break; 
   7391 
   7392     default:
   7393         rv = SOC_E_UNAVAIL;
   7394     }
   7395 
   7396 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
   7397     PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */
   7398 #endif
   7399     /* NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE                             */
   7400     /* To access TOP level registers use phy_id of port0. Now restore back    */
   7401     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   7402     
   7403     return (rv);
   7404 }
   7405 
   7406 STATIC int
   7407 _phy_phy542xx_inband_timesync_get_msg_type(uint16 value,
   7408                               soc_port_phy_timesync_msg_t *msg_type) {
   7409     value = (value  >> PHY_BCM542XX_TOP_1588_TS_INFO_MSG_TYPE_SHIFT)
   7410         & PHY_BCM542XX_TOP_1588_TS_INFO_MSG_TYPE;
   7411     switch(value) {
   7412         case 0:
   7413             *msg_type = SOC_PORT_PHY_TIMESYNC_MSG_SYNC;
   7414             break;
   7415         case 1:
   7416             *msg_type = SOC_PORT_PHY_TIMESYNC_MSG_DELAY_REQ;
   7417             break;
   7418         case 2:
   7419             *msg_type = SOC_PORT_PHY_TIMESYNC_MSG_PDELAY_REQ;
   7420             break;
   7421         case 3:
   7422             *msg_type = SOC_PORT_PHY_TIMESYNC_MSG_PDELAY_RESP;
   7423             break;
   7424         default:
   7425             return SOC_E_UNAVAIL;
   7426     }
   7427     return SOC_E_NONE;
   7428 }
   7429 
   7430 STATIC int
   7431 _phy_phy542xx_inband_timesync_get_protocol(uint16 value,
   7432                               soc_port_phy_timesync_prot_t *protocol) {
   7433     value = (value  >> PHY_BCM542XX_TOP_1588_TS_INFO_DOMAIN_NUM_SHIFT)
   7434         & PHY_BCM542XX_TOP_1588_TS_INFO_DOMAIN_NUM;
   7435     switch(value) {
   7436         case 0:
   7437             *protocol = SOC_PORT_PHY_TIMESYNC_PROT_LAYER2;
   7438             break;
   7439         case 1:
   7440             *protocol = SOC_PORT_PHY_TIMESYNC_PROT_IPV4_UDP;
   7441             break;
   7442         case 2:
   7443             *protocol = SOC_PORT_PHY_TIMESYNC_PROT_IPV6_UDP;
   7444             break;
   7445         default:
   7446             return SOC_E_UNAVAIL;
   7447     }
   7448     return SOC_E_NONE;
   7449 }
   7450 
   7451 STATIC int
   7452 phy_bcm542xx_timesync_enhanced_capture_get(int unit, soc_port_t port, 
   7453                               soc_port_phy_timesync_enhanced_capture_t *value) {
   7454     uint16 dev_port, value0, value1, value2, value3;
   7455     phy_ctrl_t *pc;
   7456     uint16 data16 = 0;
   7457 
   7458     pc = EXT_PHY_SW_STATE(unit, port);
   7459 
   7460     /***********************************************************************
   7461      * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   7462      * To access TOP level registers use phy_id of port0. Override this ports 
   7463      */
   7464     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   7465 
   7466     /* Dev port numbers from 0-7 */
   7467     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   7468 
   7469     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   7470        of the device. For example to enable autogrEEEn on port0, 
   7471        rdb register for port 4 0x808 need to be used. 
   7472        Refer package configuration document.
   7473      */
   7474     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   7475         dev_port += 4;
   7476     }
   7477 
   7478     /* MSG_TYPE, PROTOCOL, DIRECTION */
   7479     SOC_IF_ERROR_RETURN(
   7480         phy_bcm542xx_direct_reg_modify(unit, pc,
   7481                     PHY_BCM542XX_TOP_1588_CNTR_DBG_REG_OFFSET,  
   7482                     (dev_port << CNTR_DBG_TS_SLICE_SEL_SHIFT),
   7483                     PHY_BCM542XX_TOP_1588_CNTR_DBG_TS_SLICE_SEL) );
   7484 
   7485     SOC_IF_ERROR_RETURN(
   7486         phy_bcm542xx_direct_reg_read(unit, pc,
   7487                     PHY_BCM542XX_TOP_1588_TS_INFO_1_REG_OFFSET, &value0) );
   7488     SOC_IF_ERROR_RETURN(
   7489         _phy_phy542xx_inband_timesync_get_msg_type(value0, &value->msg_type) );
   7490     SOC_IF_ERROR_RETURN(
   7491         _phy_phy542xx_inband_timesync_get_protocol(value0, &value->protocol) );
   7492 
   7493     value->direction = ( ((value0 >> PHY_BCM542XX_TOP_1588_TS_INFO_DIR_SHIFT)
   7494                            & PHY_BCM542XX_TOP_1588_TS_INFO_DIR) == 0 )
   7495                        ? SOC_PORT_PHY_TIMESYNC_DIR_EGRESS
   7496                        : SOC_PORT_PHY_TIMESYNC_DIR_INGRESS;
   7497     /* SEQ_ID */
   7498     SOC_IF_ERROR_RETURN(
   7499         phy_bcm542xx_direct_reg_read(unit, pc,
   7500                      PHY_BCM542XX_TOP_1588_TS_INFO_2_REG_OFFSET, &value0) );
   7501     value->seq_id = (value0 >> PHY_BCM542XX_TOP_1588_TS_INFO_SEQ_ID_SHIFT)
   7502                       & PHY_BCM542XX_TOP_1588_TS_INFO_SEQ_ID;
   7503 
   7504     /* DOMAIN */
   7505 
   7506     /* TIMESTAMP */
   7507 
   7508     /* SRC PORT ID selected? */
   7509     SOC_IF_ERROR_RETURN(
   7510         phy_bcm542xx_direct_reg_read(unit, pc,
   7511             PHY_BCM542XX_TOP_1588_LABEL_N_MSB_MASK_REG_OFFSET(dev_port),
   7512             &data16) );
   7513 
   7514     if ( data16 & PHY_BCM542XX_TOP_1588_CAP_SRC_PORT_CLK_ID ) {
   7515         SOC_IF_ERROR_RETURN(
   7516             phy_bcm542xx_direct_reg_read(unit, pc,
   7517                     PHY_BCM542XX_TOP_1588_TS_INFO_3_REG_OFFSET, &value0) );
   7518         value0 &= PHY_BCM542XX_TOP_1588_TS_INFO_SRC_PORT_CLK_ID_1;
   7519         SOC_IF_ERROR_RETURN(
   7520             phy_bcm542xx_direct_reg_read(unit, pc,
   7521                     PHY_BCM542XX_TOP_1588_TS_INFO_4_REG_OFFSET, &value1) );
   7522         value1 &= PHY_BCM542XX_TOP_1588_TS_INFO_SRC_PORT_CLK_ID_2;
   7523         SOC_IF_ERROR_RETURN(
   7524             phy_bcm542xx_direct_reg_read(unit, pc,
   7525                     PHY_BCM542XX_TOP_1588_TS_INFO_5_REG_OFFSET, &value2) );
   7526         value2 &= PHY_BCM542XX_TOP_1588_TS_INFO_SRC_PORT_CLK_ID_3;
   7527         SOC_IF_ERROR_RETURN(
   7528             phy_bcm542xx_direct_reg_read(unit, pc,
   7529                     PHY_BCM542XX_TOP_1588_TS_INFO_6_REG_OFFSET, &value3) );
   7530         value3 &= PHY_BCM542XX_TOP_1588_TS_INFO_SRC_PORT_CLK_ID_4;
   7531         COMPILER_64_SET( (value->source_port_identity), 
   7532                          (value3 << 16) | value2, 
   7533                          (value1 << 16) | value0 ); 
   7534     } else {
   7535         COMPILER_64_SET((value->source_port_identity), 0, 0); 
   7536     }
   7537 
   7538 
   7539     /* SRC PORT */
   7540     SOC_IF_ERROR_RETURN(
   7541         phy_bcm542xx_direct_reg_read(unit, pc,
   7542                     PHY_BCM542XX_TOP_1588_TS_INFO_7_REG_OFFSET, &value0) );
   7543     value->source_port &= PHY_BCM542XX_TOP_1588_TS_INFO_SRC_PORT_NUM;
   7544 
   7545     /* VLAN ID */
   7546     SOC_IF_ERROR_RETURN(
   7547         phy_bcm542xx_direct_reg_read(unit, pc,
   7548                     PHY_BCM542XX_TOP_1588_TS_INFO_8_REG_OFFSET, &value0) );
   7549     value->vlan_id &= PHY_BCM542XX_TOP_1588_TS_INFO_VLAN_ID;
   7550 
   7551    /***********************************************************************
   7552     * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   7553     * To access TOP level registers use phy_id of port0. Now restore back 
   7554     */
   7555     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   7556         
   7557     return SOC_E_NONE;
   7558 }
   7559 
   7560 
   7561 /*
   7562  * Function:
   7563  *      phy_54280_cable_diag_dispatch
   7564  * Purpose:
   7565  *      Run 54280 cable diagnostics
   7566  * Parameters:
   7567  *      unit - device number
   7568  *      port - port number
   7569  *      status - (OUT) cable diagnotic status structure
   7570  * Returns: 
   7571  *      SOC_E_XXX
   7572  */
   7573 STATIC int
   7574 phy_54280_cable_diag_dispatch(int unit, soc_port_t port,
   7575                               soc_port_cable_diag_t *status)
   7576 {
   7577     /* ECD_CTRL : break link */
   7578     uint16 ecd_ctrl = 0x1000;
   7579     phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port);
   7580 
   7581     /* ECD functions use legacy register addressing mode */
   7582     PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc);
   7583 
   7584     
   7585     SOC_IF_ERROR_RETURN(
   7586         phy_ecd_cable_diag_init_40nm(unit, port));
   7587 
   7588     SOC_IF_ERROR_RETURN(
   7589         phy_ecd_cable_diag_40nm(unit, port, status, ecd_ctrl));
   7590 
   7591     PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc);
   7592     return SOC_E_NONE;
   7593 }
   7594 
   7595 /*
   7596  * Function:
   7597  *    phy_bcm542xx_clock_enable_set
   7598  * Purpose:
   7599  *    SyncE primary/secondary recovery clodk
   7600  * Parameters:
   7601  *    bit_shift :  0 for primary, 4 for secondary
   7602  * Returns:
   7603  */
   7604 int
   7605 phy_bcm542xx_clock_enable_set(int unit, phy_ctrl_t *pc,
   7606                               int bit_shift, uint32 enable)
   7607 {
   7608     int     rv   = SOC_E_NONE;
   7609     uint16  data = 0;
   7610     int     dev_port;
   7611 
   7612     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   7613     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   7614        of the device. For example to enable autogrEEEn on port0, 
   7615        rdb register for port 4 0x808 need to be used. 
   7616        Refer package configuration document.
   7617      */
   7618     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   7619         dev_port += 4;
   7620     }
   7621 
   7622     /* act on the 1st port of this chip */
   7623     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   7624 
   7625     /* SyncE Recovery Clock Registe, RDB.0x83c                            *\
   7626     |*  bit[7]: disable secondary, bit[6:4] source of secondary clock     *|
   7627     \*  bit[3]: disable primary  , bit[2:0] source of primary   clock     */
   7628     data = (enable)
   7629            ? ((dev_port & PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK_SEL)
   7630                << bit_shift)
   7631            : ((bit_shift == 0) ? (PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK1_DIS)
   7632                                : (PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK2_DIS));
   7633     /* Set bit[14]: primary recovery clock, bit[13]: secondary recovery clock for BCM54292*/
   7634     if(enable && (PHY_IS_BCM54292(pc))) {
   7635             data |= ((bit_shift == 0) ? PHY_BCM542XX_SYNCE_RECOVERY_CLK1_EN
   7636                                       : PHY_BCM542XX_SYNCE_RECOVERY_CLK2_EN);
   7637     }
   7638  
   7639     /* write to SYNCE Recovery Clock Registe, RDB 0x83c */
   7640     if (PHY_IS_BCM54292(pc)) {
   7641         rv = phy_bcm542xx_direct_reg_modify( unit, pc,
   7642               PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_OFFSET, data,
   7643               ((PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK_MASK << bit_shift) |
   7644                ((bit_shift == 0) ? PHY_BCM542XX_SYNCE_RECOVERY_CLK1_EN : PHY_BCM542XX_SYNCE_RECOVERY_CLK2_EN)));
   7645     } else {
   7646         rv = phy_bcm542xx_direct_reg_modify( unit, pc,
   7647               PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_OFFSET, data,
   7648               (PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK_MASK << bit_shift));
   7649     }
   7650 
   7651     /* resume to the original phy id */
   7652     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   7653     return rv;
   7654 }
   7655 
   7656 /*
   7657  * Function:
   7658  *    phy_bcm542xx_clock_enable_get
   7659  * Purpose:
   7660  *    SyncE primary/secondary recovery clock
   7661  * Parameters:
   7662  *    bit_shift :  0 for primary, 4 for secondary
   7663  * Returns:
   7664  */
   7665 int
   7666 phy_bcm542xx_clock_enable_get(int unit, phy_ctrl_t *pc,
   7667                               int bit_shift, uint32 *value)
   7668 {
   7669     int     rv   = SOC_E_NONE;
   7670     uint16  data = 0;
   7671     int     dev_port;
   7672 
   7673     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   7674     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   7675        of the device. For example to enable autogrEEEn on port0, 
   7676        rdb register for port 4 0x808 need to be used. 
   7677        Refer package configuration document.
   7678      */
   7679     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   7680         dev_port += 4;
   7681     }
   7682 
   7683     /* act on the 1st port of this chip */
   7684     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   7685 
   7686     /* read from SYNCE Recovery Clock Registe, RDB 0x83c */
   7687     rv = phy_bcm542xx_direct_reg_read( unit, pc,
   7688                         PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_OFFSET, &data );
   7689 
   7690     /* resume to the original phy id */
   7691     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   7692 
   7693     /* SyncE Recovery Clock Registe, RDB.0x83c                            *\
   7694     |*  bit[7]: disable secondary, bit[6:4] source of secondary clock     *|
   7695     \*  bit[3]: disable primary  , bit[2:0] source of primary   clock     */
   7696     data >>= bit_shift;
   7697     *value = ( (data & PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK_DIS) ||
   7698               ((data & PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK_SEL) != dev_port) ) 
   7699              ? FALSE : TRUE;
   7700     return rv;
   7701 }
   7702 
   7703 /*
   7704  * Function:
   7705  *    phy_bcm542xx_clock_control_set
   7706  * Purpose:
   7707  * Parameters:
   7708  * Returns:
   7709  */
   7710 STATIC int
   7711 _phy_bcm542xx_clock_control_set(int unit, phy_ctrl_t *pc,
   7712                                 uint16 mask, uint32 value)
   7713 {
   7714     int  rv = SOC_E_NONE;
   7715 
   7716     /* act on the 1st port of this chip */
   7717     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   7718 
   7719     /* TOP_MISCREG_SYNCE - SYNCE Recovery Clock Registe, RDB.0x83c */
   7720     rv = phy_bcm542xx_direct_reg_modify(unit, pc,
   7721                         PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_OFFSET,
   7722                         ((value) ? mask : 0), mask );
   7723     /* resume to the original phy id */
   7724     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   7725     return rv;
   7726 }
   7727 
   7728 /*
   7729  * Function:
   7730  *    phy_bcm542xx_clock_control_get
   7731  * Purpose:
   7732  * Parameters:
   7733  * Returns:
   7734  */
   7735 STATIC int
   7736 _phy_bcm542xx_clock_control_get(int unit, phy_ctrl_t *pc,
   7737                                 uint16 mask, uint32 *value)
   7738 {
   7739     int     rv = SOC_E_NONE;
   7740     uint16  data;
   7741 
   7742     /* act on the 1st port of this chip */
   7743     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   7744 
   7745     /* TOP_MISCREG_SYNCE - SYNCE Recovery Clock Registe, RDB.0x83c */
   7746     rv = phy_bcm542xx_direct_reg_read( unit, pc,
   7747                          PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_OFFSET, &data );
   7748     *value = (data & mask) ? TRUE : FALSE;
   7749 
   7750     /* resume to the original phy id */
   7751     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   7752     return rv;
   7753 }
   7754 
   7755 /*
   7756  * Function:
   7757  *    phy_bcm542xx_power_mode_set
   7758  * Purpose:
   7759  * Parameters:
   7760  * Returns:
   7761  */
   7762 int
   7763 phy_bcm542xx_power_mode_set(int unit, phy_ctrl_t *pc, int mode)
   7764 {
   7765     if ( pc->power_mode == mode) {
   7766         return SOC_E_NONE;
   7767     }
   7768 
   7769     if (mode == SOC_PHY_CONTROL_POWER_LOW) {
   7770         /* enable dsp clock */
   7771         PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc,
   7772                             PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK, 
   7773                             PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK);
   7774 
   7775         if (1) { /* CHECK if the interface is SGMII? */
   7776             /* Select mode: SGMII->Copper */
   7777             phy_bcm542xx_direct_reg_modify(unit, pc,
   7778                             PHY_BCM542XX_MODE_CONTROL_REG_OFFSET, 
   7779                             PHY_BCM542XX_MODE_CONTROL_REG_MODE_SEL 
   7780                                 & MODE_SELECT_SGMII_2_COPPER, 
   7781                             PHY_BCM542XX_MODE_CONTROL_REG_MODE_SEL);
   7782 
   7783            /* Power down SGMII Interface  */ 
   7784             phy_bcm542xx_direct_reg_modify(unit, pc,
   7785                             PHY_BCM542XX_SGMII_CONTROL_REG_OFFSET, 
   7786                             PHY_BCM542XX_SGMII_CONTROL_REG_POWER_DOWN, 
   7787                             PHY_BCM542XX_SGMII_CONTROL_REG_POWER_DOWN);
   7788         }
   7789 
   7790         /* disable dsp clock */
   7791         PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc, 0x00,
   7792                             PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK);
   7793 
   7794     } else if (mode == SOC_PHY_CONTROL_POWER_FULL) {
   7795          /* enable dsp clock */
   7796          PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc,
   7797                             PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK, 
   7798                             PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK);
   7799 
   7800          if (1) { /* CHECK if the interface is SGMII? */
   7801             /* Select mode: SGMII->Copper */
   7802             phy_bcm542xx_direct_reg_modify(unit, pc,
   7803                             PHY_BCM542XX_MODE_CONTROL_REG_OFFSET, 
   7804                             PHY_BCM542XX_MODE_CONTROL_REG_MODE_SEL 
   7805                                & MODE_SELECT_SGMII_2_COPPER, 
   7806                             PHY_BCM542XX_MODE_CONTROL_REG_MODE_SEL);
   7807 
   7808            /* Normal operation mode - disable power down - SGMII Interface  */ 
   7809             phy_bcm542xx_direct_reg_modify(unit, pc,
   7810                             PHY_BCM542XX_SGMII_CONTROL_REG_OFFSET, 
   7811                             0x00, 
   7812                             PHY_BCM542XX_SGMII_CONTROL_REG_POWER_DOWN);
   7813         }
   7814 
   7815         /* disable dsp clock */
   7816         PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc, 0x00,
   7817                             PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK);
   7818 
   7819         /* disable the auto power mode */
   7820         phy_bcm542xx_direct_reg_modify( unit, pc,
   7821                             PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, 
   7822                             0x00, 
   7823                             PHY_BCM542XX_POWER_AUTO_DOWN_REG_APD_MODE);
   7824     } else if (mode == SOC_PHY_CONTROL_POWER_AUTO) {
   7825         phy_bcm542xx_direct_reg_modify( unit, pc,
   7826                             PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, 
   7827                             PHY_BCM542XX_POWER_AUTO_DOWN_REG_APD_MODE, 
   7828                             PHY_BCM542XX_POWER_AUTO_DOWN_REG_APD_MODE);
   7829     } else if (mode == SOC_PHY_CONTROL_POWER_AUTO_DISABLE) {
   7830         phy_bcm542xx_direct_reg_modify( unit, pc,
   7831                             PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, 
   7832                             0, 
   7833                             PHY_BCM542XX_POWER_AUTO_DOWN_REG_APD_MODE);
   7834     } else {
   7835         return SOC_E_UNAVAIL;
   7836     }
   7837 
   7838     pc->power_mode = mode;
   7839     return SOC_E_NONE;
   7840 }
   7841 
   7842 /*
   7843  * Function:
   7844  *    phy_bcm542xx_power_auto_wake_time_set
   7845  * Purpose:
   7846  * Parameters:
   7847  * Returns:
   7848  */
   7849 int
   7850 phy_bcm542xx_power_auto_wake_time_set(int unit, phy_ctrl_t *pc, int value)
   7851 {
   7852     value = (value <  PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_MAX)? value : PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_MAX;
   7853     /* at least one unit */
   7854     value = (value < PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_UNIT)? PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_UNIT : value;
   7855 
   7856     phy_bcm542xx_direct_reg_modify(unit, pc,
   7857              PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, 
   7858              PHY_BCM542XX_POWER_AUTO_DOWN_REG_WAKE_UP_TIMER_SEL 
   7859                & (value/PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_UNIT), 
   7860              PHY_BCM542XX_POWER_AUTO_DOWN_REG_WAKE_UP_TIMER_SEL);
   7861 
   7862     return SOC_E_NONE;
   7863 }
   7864 
   7865 /*
   7866  * Function:
   7867  *    phy_bcm542xx_power_auto_wake_time_get
   7868  * Purpose:
   7869  * Parameters:
   7870  * Returns:
   7871  */
   7872 int
   7873 phy_bcm542xx_power_auto_wake_time_get(int unit, phy_ctrl_t *pc, uint32 *value)
   7874 {
   7875     uint16 data;
   7876     phy_bcm542xx_direct_reg_read(unit, pc,
   7877             PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, &data);
   7878 
   7879     data &= PHY_BCM542XX_POWER_AUTO_DOWN_REG_WAKE_UP_TIMER_SEL;
   7880     *value = data * PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_UNIT;
   7881     return SOC_E_NONE;
   7882 }
   7883 
   7884 /*
   7885  * Function:
   7886  *    phy_bcm542xx_power_auto_sleep_time_set
   7887  * Purpose:
   7888  * Parameters:
   7889  * Returns:
   7890  */
   7891 int
   7892 phy_bcm542xx_power_auto_sleep_time_set(int unit, phy_ctrl_t *pc, int value)
   7893 {
   7894     /* sleep time configuration is either 2.7s or 5.4 s, default is 2.7s */
   7895     value = (value < PHY_BCM542XX_AUTO_PWRDWN_SLEEP_MAX)? 0x00 : PHY_BCM542XX_POWER_AUTO_DOWN_REG_WAKE_UP_TIMER_SEL;
   7896     phy_bcm542xx_direct_reg_modify( unit, pc,
   7897             PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, 
   7898             value, 
   7899             PHY_BCM542XX_POWER_AUTO_DOWN_REG_SLEEP_TIMER_SEL);
   7900 
   7901     return SOC_E_NONE;
   7902 }
   7903 
   7904 /*
   7905  * Function:
   7906  *    phy_bcm542xx_power_auto_sleep_time_get
   7907  * Purpose:
   7908  * Parameters:
   7909  * Returns:
   7910  */
   7911 int
   7912 phy_bcm542xx_power_auto_sleep_time_get(int unit, phy_ctrl_t *pc, uint32 *value)
   7913 {
   7914     uint16 data;
   7915     phy_bcm542xx_direct_reg_read(unit, pc,
   7916             PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, &data);
   7917    
   7918     *value = (data & PHY_BCM542XX_POWER_AUTO_DOWN_REG_SLEEP_TIMER_SEL)
   7919              ? PHY_BCM542XX_AUTO_PWRDWN_SLEEP_MAX
   7920              : PHY_BCM542XX_AUTO_PWRDWN_SLEEP_MIN;
   7921 
   7922     return SOC_E_NONE;
   7923 }
   7924 
   7925 /*
   7926  * Function:
   7927  *      phy_bcm542xx_eee_enable
   7928  * Purpose:
   7929  *      Enable or disable EEE (Native)
   7930  * Parameters:
   7931  *      unit   - StrataSwitch unit #.
   7932  *      port   - StrataSwitch port #.
   7933  *      mode   - 0:Native EEE  or  1:AutogrEEEn
   7934  *      enable - 1:Enable or 0:disable
   7935  * Returns:
   7936  *      SOC_E_NONE
   7937  */
   7938 int
   7939 phy_bcm542xx_eee_enable(int unit, soc_port_t port, int mode, int enable)
   7940 {
   7941     int                 dev_port;
   7942     phy_ctrl_t         *pc;
   7943 
   7944     if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   7945         return ( SOC_E_UNAVAIL );
   7946     }
   7947     pc = EXT_PHY_SW_STATE(unit, port);
   7948 
   7949     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);  /* Dev port numbers from 0-7 */
   7950 
   7951     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7  *\
   7952     |  of the device. For example to enable autogrEEEn on port0,         |
   7953     |  rdb register for port 4 0x808 need to be used.                    |
   7954     \* Refer package configuration document.                            */
   7955     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   7956         dev_port += 4;
   7957     }
   7958 
   7959     if ( enable ) {
   7960         soc_port_ability_t  abi = { 0 };
   7961         /* Enable EEE 
   7962          * 1. Enable EEE mode
   7963          * 2. Advertise EEE auto-negotiation capabilities
   7964          *    < Normal auto-negotiation properties >
   7965          *    < Enable optional variable/fixed latency modes >  if AutogrEEEn
   7966          * 3. Intiate auto-negotiation
   7967          * 4. Enable AutogrEEEn / Native EEE
   7968          */
   7969 
   7970         /* Enable EEE mode */
   7971         SOC_IF_ERROR_RETURN(         /* 7.0x803D[15:14] */
   7972                 PHY_MODIFY_BCM542XX_EEE_803Dr(unit, pc, 0xc000, 0xc000) );
   7973         /* Advertise EEE Auto Negotiation Capabilities */
   7974         SOC_IF_ERROR_RETURN( phy_bcm542xx_ability_advert_get(unit, port, &abi) );
   7975         abi.eee |= (SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX);
   7976         SOC_IF_ERROR_RETURN( phy_bcm542xx_ability_advert_set(unit, port, &abi) );
   7977         /* Initiate Auto Negotiation */
   7978         SOC_IF_ERROR_RETURN( phy_bcm542xx_autoneg_set(unit, port, TRUE) );
   7979 
   7980         if ( SOC_PHY_CONTROL_EEE_AUTO == mode ) {       /* AutogrEEEn mode */
   7981                 /***********************************************************************
   7982                  * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   7983                  * To access TOP level registers use phy_id of port0. Override this ports 
   7984                  */
   7985                 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   7986                 
   7987                 phy_bcm542xx_direct_reg_modify(unit, pc,
   7988                                     PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port),
   7989                                     PHY_BCM542XX_TOP_MISC_MII_BUFF_EN,
   7990                                     PHY_BCM542XX_TOP_MISC_MII_BUFF_EN);
   7991                 /***********************************************************************
   7992                  * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   7993                  * To access TOP level registers use phy_id of port0. Now restore back 
   7994                  */
   7995                 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   7996         }
   7997         /* 
   7998            Enable stat counters 
   7999            Clear BIT14 to get lower 16bits of the counters 
   8000         */
   8001         SOC_IF_ERROR_RETURN(
   8002                 PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc,
   8003                             PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_EN,
   8004                             PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_EN
   8005                           | PHY_BCM542XX_EEE_STAT_CTRL_SATURATE_MODE) );
   8006 
   8007     } else {  /* enable == 0 */
   8008         /* Disable EEE mode */
   8009         SOC_IF_ERROR_RETURN(         /* 7.0x803D[15:14] */
   8010                 PHY_MODIFY_BCM542XX_EEE_803Dr(unit, pc, 0x0000, 0xc000) );
   8011         phy_bcm542xx_autoneg_set(unit, port, 1);
   8012 
   8013         if ( SOC_PHY_CONTROL_EEE_AUTO == mode ) {       /* AutogrEEEn mode */
   8014                 /***********************************************************************
   8015                  * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   8016                  * To access TOP level registers use phy_id of port0. Override this ports 
   8017                  */
   8018                 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   8019                 
   8020                 phy_bcm542xx_direct_reg_modify(unit, pc,
   8021                                     PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port),
   8022                                     0x00,
   8023                                     PHY_BCM542XX_TOP_MISC_MII_BUFF_EN);
   8024                 /***********************************************************************
   8025                  * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   8026                  * To access TOP level registers use phy_id of port0. Now restore back 
   8027                  */
   8028                 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   8029         }
   8030         /* Reset stat counters */
   8031         SOC_IF_ERROR_RETURN(
   8032                 PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc,
   8033                             PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET,
   8034                             PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET) );
   8035         /* Disable stat counters */
   8036         SOC_IF_ERROR_RETURN(
   8037                 PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc, 0,
   8038                             PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET
   8039                           | PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_EN) );
   8040     }
   8041 
   8042     return SOC_E_NONE;
   8043 }
   8044 
   8045 STATIC int
   8046 _phy_bcm542xx_get_eee_control_status(int unit, phy_ctrl_t *pc, uint32 *value)
   8047 {
   8048     int     rv = SOC_E_NONE;
   8049     uint16  temp16 = 0;
   8050 
   8051     rv = PHY_READ_BCM542XX_EEE_803Dr(unit, pc,&temp16);    /* 7.803d */
   8052     *value = ((temp16 & 0xC000) == 0xC000) ? 1 : 0;
   8053     return rv;
   8054 }
   8055 
   8056 STATIC int
   8057 _phy_bcm542xx_get_auto_eee_control_status(int unit, soc_port_t port,
   8058                                           uint32 *value)
   8059 {
   8060     int          rv = SOC_E_NONE;
   8061     uint16       temp16 = 0;
   8062     int          dev_port;
   8063     phy_ctrl_t  *pc;
   8064 
   8065     pc = EXT_PHY_SW_STATE(unit, port);
   8066     /* Dev port numbers from 0-7 */
   8067     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   8068     
   8069     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   8070        of the device. For example to enable autogrEEEn on port0, 
   8071        rdb register for port 4 0x808 need to be used. 
   8072        Refer package configuration document.
   8073      */
   8074     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   8075         dev_port += 4;
   8076     }
   8077     
   8078     /***********************************************************************
   8079      * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   8080      * To access TOP level registers use phy_id of port0. Override this ports 
   8081      */
   8082     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   8083     /* TOP_MISCREG_MII_BUFFER_CNTL_0 Reg., RDB 0x800+2n */
   8084     rv = phy_bcm542xx_direct_reg_read(unit, pc,    /* bit[0] MII_BUFFER_ENABLE */
   8085                      PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port), 
   8086                      &temp16);
   8087 
   8088     /***********************************************************************
   8089      * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   8090      * To access TOP level registers use phy_id of port0. Now restore back 
   8091      */
   8092     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   8093 
   8094     *value = (temp16 & PHY_BCM542XX_TOP_MISC_MII_BUFF_EN)? 1: 0;
   8095     return rv;
   8096 }
   8097 
   8098 /*
   8099  * Function:
   8100  *    _phy_bcm542xx_eee_counter_get
   8101  * Purpose:
   8102  *    Get the 32-bit value of EEE Statistic counter/timer
   8103  *    CORE_ExpAA, ExpAB, ExpAC, ExpAD
   8104  * Parameters:
   8105  *                
   8106  * Returns:
   8107  */
   8108 STATIC int
   8109 _phy_bcm542xx_eee_counter_get(int unit, phy_ctrl_t *pc,
   8110                               uint16 reg_addr, uint32 *value32)
   8111 {
   8112     uint16  msb1, lsb1, msb2, lsb2;
   8113 
   8114 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
   8115     PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc);   /* set RDB register access mode */
   8116 #endif
   8117 
   8118     /* CORE_ExpAF - EEE Statistic counters ctrl/status, RDB 0x0af bit[14]     */
   8119     /* STATISTIC_UPPER_16BITS_SEL=1 to get the upper 16-bit of counters first */
   8120     SOC_IF_ERROR_RETURN(
   8121             phy_bcm542xx_rdb_reg_modify(unit, pc,
   8122                                 PHY_BCM542XX_EEE_STAT_CTRL_REG_OFFSET,
   8123                                 PHY_BCM542XX_EEE_STAT_CTRL_16U_BIT_SEL,
   8124                                 PHY_BCM542XX_EEE_STAT_CTRL_16U_BIT_SEL) );
   8125     /* CORE_ExpAA/AB/AC/AD: EEE Statistic timer/counter, TxRx duration & event*/
   8126     SOC_IF_ERROR_RETURN(
   8127             phy_bcm542xx_rdb_reg_read(unit, pc, reg_addr, &msb1) );    /* upper 16 bits */
   8128     SOC_IF_ERROR_RETURN(
   8129             phy_bcm542xx_rdb_reg_read(unit, pc, reg_addr, &lsb1) );    /* lower 16 bits */
   8130     if ( PHY_IS_BCM54210_220(pc) ) {
   8131         *value32 = (((uint32) msb1) << 16) | lsb1;
   8132     } else {
   8133         /* Workaround for old version of 5428x/29x/220/210   */
   8134         /* read the counter [CORE_ExpAA/AB/AC/AD] four times */
   8135         SOC_IF_ERROR_RETURN(
   8136             phy_bcm542xx_rdb_reg_read(unit, pc, reg_addr, &msb2) );
   8137         SOC_IF_ERROR_RETURN(
   8138             phy_bcm542xx_rdb_reg_read(unit, pc, reg_addr, &lsb2) );
   8139         /* form the 32-bit value by concatenating the upper & lower 16 bits   */
   8140         /*                see the 'NOTE' section of RDB Reg.0x0AF spec        */
   8141         /*                in BCM54220SE/5428x Programmer's Reference Guide    */
   8142         *value32 = ( lsb1 & BIT(15) ) ? (((uint32) msb1) << 16) | lsb1
   8143                                       : (((uint32) msb2) << 16) | lsb1;
   8144     }
   8145 
   8146 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING
   8147     PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */
   8148 #endif
   8149     return (SOC_E_NONE);
   8150 }
   8151 
   8152 /*
   8153  * Function:
   8154  *    phy_bcm542xx_eee_control_set
   8155  * Purpose:
   8156  *    Implements different 'setting' controls
   8157  *    for EEE
   8158  * Parameters:
   8159  *    phy_id    - PHY's device address
   8160  *    type      - type of control
   8161  *    value     - helps decide what needs to be
   8162  *                for the control type 'type'
   8163  * Returns:
   8164  */
   8165 int
   8166 phy_bcm542xx_eee_control_set(int unit, soc_port_t port, soc_phy_control_t type, uint32 value)
   8167 {
   8168     int          rv = SOC_E_NONE;
   8169     uint16       temp16 = 0;
   8170     int          dev_port;
   8171     phy_ctrl_t  *pc;
   8172 
   8173     if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   8174         return SOC_E_UNAVAIL;
   8175     }
   8176     pc = EXT_PHY_SW_STATE(unit, port);
   8177     /* Dev port numbers from 0-7 */
   8178     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   8179     
   8180     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   8181        of the device. For example to enable autogrEEEn on port0, 
   8182        rdb register for port 4 0x808 need to be used. 
   8183        Refer package configuration document.
   8184      */
   8185     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   8186         dev_port += 4;
   8187     }
   8188 
   8189     switch ( type ) {
   8190     case (SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD):
   8191         /***********************************************************************
   8192          * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE
   8193          * To access TOP level registers use phy_id of port0. Override this ports
   8194          */
   8195         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   8196         /* TOP_MISCREG_MII_BUFFER_CNTL_0 Reg., RDB 0x800+2n */
   8197         /*     bit[10:8] WAIT_IFG_LENGTH */
   8198         rv = phy_bcm542xx_direct_reg_modify(unit, pc,
   8199                          PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port),
   8200                          value << 8,
   8201                          PHY_BCM542XX_TOP_MISC_MII_BUFF_WAIT_IFG_LEN );
   8202         /***********************************************************************
   8203          * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   8204          * To access TOP level registers use phy_id of port0. Now restore back
   8205          */
   8206         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   8207         break;
   8208 
   8209     case (SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY):
   8210         /***********************************************************************
   8211          * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE
   8212          * To access TOP level registers use phy_id of port0. Override this ports
   8213          */
   8214         /* Fixed latency can have only 0 or 1 value  */
   8215         if ((value != FALSE) && (value != TRUE)) {
   8216             return SOC_E_PARAM;
   8217         }
   8218         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   8219         temp16 = (value == FALSE) ? PHY_BCM542XX_TOP_MISC_MII_BUFF_VAR_LAT_EN : 0;
   8220 
   8221         /* TOP_MISCREG_MII_BUFFER_CNTL_0 Reg., RDB 0x800+2n */
   8222         /*     bit[2] VARIABLE_LATENCY_EN */
   8223         rv = phy_bcm542xx_direct_reg_modify(unit, pc,
   8224                          PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port),
   8225                          temp16,
   8226                          PHY_BCM542XX_TOP_MISC_MII_BUFF_VAR_LAT_EN );
   8227         /***********************************************************************
   8228          * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   8229          * To access TOP level registers use phy_id of port0. Now restore back
   8230          */
   8231         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   8232 
   8233         /* Need to set MII buffer register as well : phy54682 ? */
   8234         break;
   8235 
   8236     case (SOC_PHY_CONTROL_EEE_STATISTICS_CLEAR):
   8237         if ( 1 == value ) {
   8238             /* Enable stat counters, Soft reset the counters */
   8239             SOC_IF_ERROR_RETURN(
   8240                  PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc,
   8241                          PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET
   8242                        | PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_EN,
   8243                          PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET
   8244                        | PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_EN) );
   8245             /*Clear the counter reset bit*/
   8246             SOC_IF_ERROR_RETURN(
   8247                  PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc, 0x0,
   8248                          PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET));
   8249         }
   8250         break;
   8251 
   8252     default:
   8253         break;
   8254     }  /* switch (type) */
   8255 
   8256     return rv;
   8257 }
   8258 
   8259 /*
   8260  * Function:
   8261  *    phy_bcm542xx_eee_control_get
   8262  * Purpose:
   8263  *    Implements different 'get' controls 
   8264  *    for EEE
   8265  * Parameters:
   8266  *    phy_id    - PHY's device address
   8267  *    type      - type of control
   8268  *    value     - gets the value for the 
   8269  *                control 'type
   8270  * Returns:
   8271  *    SOC_E_xxxx            
   8272  */
   8273 int
   8274 phy_bcm542xx_eee_control_get(int unit, soc_port_t port,
   8275                              soc_phy_control_t type, uint32 *value)
   8276 {
   8277     int          rv = SOC_E_NONE;
   8278     uint16       temp16 = 0;
   8279     int          dev_port;
   8280     phy_ctrl_t  *pc;
   8281 
   8282     if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   8283         return SOC_E_UNAVAIL;
   8284     }
   8285 
   8286     pc = EXT_PHY_SW_STATE(unit, port);
   8287     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);  /* Dev port numbers from 0-7 */
   8288     
   8289     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   8290        of the device. For example to enable autogrEEEn on port0, 
   8291        rdb register for port 4 0x808 need to be used. 
   8292        Refer package configuration document.
   8293      */
   8294     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   8295         dev_port += 4;
   8296     }
   8297 
   8298     switch ( type ) {
   8299     case (SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD):
   8300         /***********************************************************************
   8301          * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE
   8302          * To access TOP level registers use phy_id of port0. Override this ports
   8303          */
   8304         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   8305         /* TOP_MISCREG_MII_BUFFER_CNTL_0 Reg., RDB 0x800+2n */
   8306         /*     bit[10:8] WAIT_IFG_LENGTH */
   8307         rv = phy_bcm542xx_direct_reg_read(unit, pc,
   8308                          PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port),
   8309                          &temp16);
   8310         /***********************************************************************
   8311          * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   8312          * To access TOP level registers use phy_id of port0. Now restore back
   8313          */
   8314         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   8315 
   8316         *value = (temp16 & PHY_BCM542XX_TOP_MISC_MII_BUFF_WAIT_IFG_LEN) >> 8;
   8317         break;
   8318 
   8319     case (SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY):
   8320         /***********************************************************************
   8321          * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE
   8322          * To access TOP level registers use phy_id of port0. Override this ports
   8323          */
   8324         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   8325         /* TOP_MISCREG_MII_BUFFER_CNTL_0 Reg., RDB 0x800+2n */
   8326         /*     bit[2] VARIABLE_LATENCY_EN */
   8327         rv = phy_bcm542xx_direct_reg_read(unit, pc,
   8328                          PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port),
   8329                          &temp16);
   8330         /***********************************************************************
   8331          * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   8332          * To access TOP level registers use phy_id of port0. Now restore back
   8333          */
   8334         pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   8335 
   8336         *value = ((temp16 & PHY_BCM542XX_TOP_MISC_MII_BUFF_VAR_LAT_EN) == 0);
   8337         break;
   8338 
   8339     case SOC_PHY_CONTROL_EEE_TRANSMIT_EVENTS:
   8340         /* CORE_ExpAC - EEE Statistic loc lpi req 0_to_1 counter, RDB 0x0ac */
   8341         rv = _phy_bcm542xx_eee_counter_get(unit, pc,
   8342                          PHY_BCM542XX_EEE_STAT_TX_EVENTS_REG_OFFSET  , value);
   8343         break;
   8344     case SOC_PHY_CONTROL_EEE_TRANSMIT_DURATION:
   8345         /* CORE_ExpAA - EEE Statistic timer 12hours lpi, RDB 0x0aa */
   8346         rv = _phy_bcm542xx_eee_counter_get(unit, pc,
   8347                          PHY_BCM542XX_EEE_STAT_TX_DURATION_REG_OFFSET, value);
   8348         break;
   8349     case SOC_PHY_CONTROL_EEE_RECEIVE_EVENTS:
   8350         /* CORE_ExpAD - EEE Statistic rem lpi_req 0_to_1 counter, RDB 0x0ad */
   8351         rv = _phy_bcm542xx_eee_counter_get(unit, pc,
   8352                          PHY_BCM542XX_EEE_STAT_RX_EVENTS_REG_OFFSET  , value);
   8353         break;
   8354     case SOC_PHY_CONTROL_EEE_RECEIVE_DURATION:
   8355         /* CORE_ExpAB - EEE Statistic timer 12hours local, RDB 0x0ab */
   8356         rv = _phy_bcm542xx_eee_counter_get(unit, pc,
   8357                          PHY_BCM542XX_EEE_STAT_RX_DURATION_REG_OFFSET, value);
   8358         break;
   8359 
   8360     default:
   8361         break;
   8362     }  /* switch (type) */
   8363 
   8364     return rv;
   8365 }
   8366 
   8367 /*
   8368  * Function:
   8369  *      phy_bcm542xx_control_set
   8370  * Purpose:
   8371  *      Configure PHY device specific control fucntion.
   8372  * Parameters:
   8373  *      unit  - StrataSwitch unit #.
   8374  *      port  - StrataSwitch port #.
   8375  *      type  - Control to update
   8376  *      value - New setting for the control
   8377  * Returns:
   8378  *      SOC_E_NONE
   8379  */
   8380 STATIC int
   8381 phy_bcm542xx_control_set(int unit, soc_port_t port,
   8382                          soc_phy_control_t type, uint32 value)
   8383 {
   8384     int               rv   = SOC_E_NONE;
   8385     phy_ctrl_t       *pc;
   8386  
   8387     pc = EXT_PHY_SW_STATE(unit, port);
   8388 
   8389     PHY_CONTROL_TYPE_CHECK(type);
   8390 
   8391     switch ( type ) {
   8392     /* SyncE recovered clock controls */
   8393     case SOC_PHY_CONTROL_CLOCK_ENABLE:
   8394         rv = phy_bcm542xx_clock_enable_set(unit, pc,
   8395                           PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK1_SHIFT,
   8396                           value);
   8397         break;
   8398     case SOC_PHY_CONTROL_CLOCK_SECONDARY_ENABLE:
   8399         rv = phy_bcm542xx_clock_enable_set(unit, pc,
   8400                           PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK2_SHIFT,
   8401                           value);
   8402         break;
   8403     case SOC_PHY_CONTROL_CLOCK_MODE_AUTO:
   8404         rv = _phy_bcm542xx_clock_control_set(unit, pc,
   8405                           PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_AUTO_CLK_DIS,
   8406                           value);
   8407         break;
   8408     case SOC_PHY_CONTROL_CLOCK_AUTO_SECONDARY:
   8409         rv = _phy_bcm542xx_clock_control_set(unit, pc,
   8410                           PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_AUTO_SW_MODE,
   8411                           value);
   8412         break;
   8413     case SOC_PHY_CONTROL_CLOCK_SOURCE:
   8414     case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
   8415         return SOC_E_UNAVAIL;
   8416         break;
   8417 
   8418     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   8419         if (PHY_IS_BCM54240(pc)) {
   8420             if ( PHY_COPPER_MODE(unit, port) ) {
   8421                 SOC_IF_ERROR_RETURN(
   8422                     PHY_MODIFY_BCM542XX_MII_MISC_TESTr(unit, pc, (value) ? PHY_BCM542XX_MII_MISC_TEST_RMT_LB : 0,
   8423                                             PHY_BCM542XX_MII_MISC_TEST_RMT_LB) );
   8424                 SOC_IF_ERROR_RETURN
   8425                     (PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc, 1, PHY_BCM542XX_MII_CTRL_RST_AN));
   8426             } else {/* MEDIUM_FIBER */
   8427                 if(value) {
   8428                     SOC_IF_ERROR_RETURN(
   8429                         PHY_WRITE_BCM542XX_AUTO_DETECT_MEDIUMr(unit, pc, 0x7800) );
   8430                     SOC_IF_ERROR_RETURN(
   8431                         PHY_WRITE_BCM542XX_MODE_CTRLr(unit, pc, 0x7F06) );
   8432                     SOC_IF_ERROR_RETURN(                
   8433                         PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, 0x5140) );
   8434                 } else { /* Diable loopback */
   8435                     SOC_IF_ERROR_RETURN(
   8436                         PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, 0x1140) );
   8437                 }
   8438             }
   8439         } else {
   8440             return SOC_E_UNAVAIL;
   8441         }
   8442         break;
   8443 
   8444     /* power controls */
   8445     case SOC_PHY_CONTROL_POWER:
   8446         rv = phy_bcm542xx_power_mode_set(unit, pc, value);
   8447         break;
   8448     case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME:
   8449         phy_bcm542xx_power_auto_wake_time_set(unit, pc, value);
   8450         break;
   8451     case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME:
   8452         phy_bcm542xx_power_auto_sleep_time_set(unit, pc, value);
   8453         break;
   8454     /* port phy address setting */
   8455     case SOC_PHY_CONTROL_PORT_PRIMARY:
   8456         SOC_IF_ERROR_RETURN
   8457                 (soc_phyctrl_primary_set(unit, port, (soc_port_t)value));
   8458         break;
   8459     case SOC_PHY_CONTROL_PORT_OFFSET:
   8460         SOC_IF_ERROR_RETURN
   8461                 (soc_phyctrl_offset_set(unit, port, (int)value));
   8462         break;
   8463     case SOC_PHY_CONTROL_SUPER_ISOLATE:
   8464         SOC_IF_ERROR_RETURN
   8465                 (phy_bcm542xx_direct_reg_modify(unit, pc,
   8466                           PHY_BCM542XX_POWER_MII_CTRL_REG_OFFSET,
   8467                           (value) ? PHY_BCM542XX_POWER_MII_CTRL_SUPER_ISOLATE
   8468                                   : 0,
   8469                           PHY_BCM542XX_POWER_MII_CTRL_SUPER_ISOLATE) );
   8470         break;
   8471     case SOC_PHY_CONTROL_SOFT_RESET:
   8472         SOC_IF_ERROR_RETURN
   8473                 (phy_bcm542xx_direct_reg_modify(unit, pc,
   8474                           PHY_BCM542XX_SOFT_RESET_REG_OFFSET,
   8475                           (value) ? PHY_BCM542XX_SOFT_RESET_ISSUE_RESET : 0,
   8476                           PHY_BCM542XX_SOFT_RESET_ISSUE_RESET) );
   8477         PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc);
   8478         break;
   8479 
   8480     /* EEE settings */
   8481     case SOC_PHY_CONTROL_EEE:
   8482         if(value == 1 )
   8483         {
   8484             /*First Disable Auto EEE*/
   8485             SOC_IF_ERROR_RETURN
   8486                 (phy_bcm542xx_eee_enable(unit, port, SOC_PHY_CONTROL_EEE_AUTO, 0));
   8487         }
   8488         /*Enable/Disable Native EEE*/
   8489         SOC_IF_ERROR_RETURN
   8490                 (phy_bcm542xx_eee_enable(unit, port, type, value));
   8491         break;
   8492     case SOC_PHY_CONTROL_EEE_AUTO:
   8493         if(value == 1 )
   8494         {
   8495             /*First Disable Native  EEE*/
   8496             SOC_IF_ERROR_RETURN
   8497                 (phy_bcm542xx_eee_enable(unit, port, SOC_PHY_CONTROL_EEE, 0));
   8498         }
   8499         /*Enable/Disable Auto EEE*/
   8500         SOC_IF_ERROR_RETURN
   8501                 (phy_bcm542xx_eee_enable(unit, port, type, value));
   8502         break;
   8503     case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD:
   8504     case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY:
   8505     case SOC_PHY_CONTROL_EEE_STATISTICS_CLEAR:
   8506         SOC_IF_ERROR_RETURN
   8507                 (phy_bcm542xx_eee_control_set(unit, port, type, value));
   8508         break;       
   8509     case SOC_PHY_CONTROL_EEE_AUTO_BUFFER_LIMIT:
   8510         /* Buffer limit modification is not allowed */
   8511     case SOC_PHY_CONTROL_EEE_TRANSMIT_WAKE_TIME:
   8512     case SOC_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME:
   8513     case SOC_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME:
   8514     case SOC_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME:
   8515     case SOC_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME:
   8516     case SOC_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME:
   8517     case SOC_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME:
   8518         return SOC_E_UNAVAIL;
   8519 
   8520     default:  /* -- unrecognized PHY control commands -- */
   8521         return SOC_E_UNAVAIL;
   8522     } /* switch ( type ) */
   8523 
   8524     return rv;
   8525 }
   8526 
   8527 /*
   8528  * Function:
   8529  *      phy_bcm542xx_control_get
   8530  * Purpose:
   8531  *      Get current control settign of the PHY.                                
   8532  * Parameters:
   8533  *      unit  - StrataSwitch unit #.
   8534  *      port  - StrataSwitch port #.
   8535  *      type  - Control to update
   8536  *      value - (OUT)Current setting for the control
   8537  * Returns:
   8538  *      SOC_E_NONE
   8539  */
   8540 STATIC int 
   8541 phy_bcm542xx_control_get(int unit, soc_port_t port,
   8542                          soc_phy_control_t type, uint32 *value)
   8543 {
   8544     int          rv = SOC_E_NONE;
   8545     phy_ctrl_t  *pc;
   8546     soc_port_t   primary;
   8547     uint16       value16;
   8548 
   8549     pc = EXT_PHY_SW_STATE(unit, port);
   8550     
   8551     if ( NULL == value ) {
   8552         return SOC_E_PARAM;
   8553     }
   8554     
   8555     PHY_CONTROL_TYPE_CHECK(type);
   8556 
   8557     switch ( type ) {
   8558     /* power controls */
   8559     case SOC_PHY_CONTROL_POWER:
   8560         *value = pc->power_mode;
   8561         break;
   8562     case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME:
   8563         phy_bcm542xx_power_auto_sleep_time_get(unit, pc, value);
   8564         break;
   8565     case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME:
   8566         phy_bcm542xx_power_auto_wake_time_get(unit, pc, value);
   8567         break;
   8568     /* port phy address setting */
   8569     case SOC_PHY_CONTROL_PORT_PRIMARY:
   8570         SOC_IF_ERROR_RETURN
   8571             (soc_phyctrl_primary_get(unit, port, &primary));
   8572         *value = (uint32) primary;
   8573         break;
   8574     case SOC_PHY_CONTROL_PORT_OFFSET:
   8575         *value = (uint32) PHY_BCM542XX_DEV_PHY_SLICE(pc);
   8576         break;
   8577 
   8578     /* SyncE recovered clock controls */
   8579     case SOC_PHY_CONTROL_CLOCK_ENABLE:
   8580         rv = phy_bcm542xx_clock_enable_get(unit, pc,
   8581                           PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK1_SHIFT,
   8582                           value);
   8583         break;
   8584     case SOC_PHY_CONTROL_CLOCK_SECONDARY_ENABLE:
   8585         rv = phy_bcm542xx_clock_enable_get(unit, pc,
   8586                           PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK2_SHIFT,
   8587                           value);
   8588         break;
   8589     case SOC_PHY_CONTROL_CLOCK_MODE_AUTO:
   8590         rv = _phy_bcm542xx_clock_control_get(unit, pc,
   8591                     PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_AUTO_CLK_DIS, value);
   8592         break;
   8593     case SOC_PHY_CONTROL_CLOCK_AUTO_SECONDARY:
   8594         rv = _phy_bcm542xx_clock_control_get(unit, pc,
   8595                     PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_AUTO_SW_MODE, value);
   8596         break;
   8597     case SOC_PHY_CONTROL_CLOCK_SOURCE:
   8598         rv = _phy_bcm542xx_clock_control_get(unit, pc,
   8599                     PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_AUTO_SW_STS , value);
   8600         *value = (0 == *value) ? SOC_PORT_PHY_CLOCK_SOURCE_PRIMARY
   8601                                : SOC_PORT_PHY_CLOCK_SOURCE_SECONDARY;
   8602         break;
   8603     case SOC_PHY_CONTROL_SUPER_ISOLATE:
   8604         SOC_IF_ERROR_RETURN
   8605                 (phy_bcm542xx_direct_reg_read(unit, pc,
   8606                           PHY_BCM542XX_POWER_MII_CTRL_REG_OFFSET, &value16) );
   8607 
   8608         *value = ((value16) & PHY_BCM542XX_POWER_MII_CTRL_SUPER_ISOLATE)
   8609                  ? TRUE : FALSE;
   8610         break;
   8611 
   8612     /* EEE settings */
   8613     case SOC_PHY_CONTROL_EEE:
   8614         if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   8615             rv = SOC_E_UNAVAIL;
   8616             break;
   8617         }
   8618         rv = _phy_bcm542xx_get_eee_control_status(unit, pc, value);
   8619         break;
   8620     case SOC_PHY_CONTROL_EEE_AUTO:
   8621         if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   8622             rv = SOC_E_UNAVAIL;
   8623             break;
   8624         }
   8625         rv = _phy_bcm542xx_get_auto_eee_control_status(unit, port, value);
   8626         break;
   8627     case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY:
   8628     case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD:
   8629     case SOC_PHY_CONTROL_EEE_TRANSMIT_EVENTS:
   8630     case SOC_PHY_CONTROL_EEE_TRANSMIT_DURATION:
   8631     case SOC_PHY_CONTROL_EEE_RECEIVE_EVENTS:
   8632     case SOC_PHY_CONTROL_EEE_RECEIVE_DURATION:
   8633         rv = phy_bcm542xx_eee_control_get(unit, port, type, value);
   8634         break;
   8635 
   8636     default:  /* -- unrecognized PHY control commands -- */
   8637         return SOC_E_UNAVAIL;
   8638     }
   8639 
   8640     return rv;
   8641 }
   8642 
   8643 /*
   8644  * Function:
   8645  *      phy_bcm542xx_probe
   8646  * Purpose:
   8647  *      Complement the generic phy probe routine to identify this phy when its
   8648  *      phy id0 and id1 is same as some other phy's.
   8649  * Parameters:
   8650  *      unit - StrataSwitch unit #.
   8651  *      pc   - phy ctrl descriptor.
   8652  * Returns:
   8653  *      SOC_E_NONE, SOC_E_NOT_FOUND and SOC_E_<error>
   8654  */
   8655 STATIC int 
   8656 phy_bcm542xx_probe(int unit, phy_ctrl_t *pc) {
   8657     int  oui = 0, model = 0, rev = 0, rv = SOC_E_NONE;
   8658     soc_phy_info_t *pi = &SOC_PHY_INFO(unit, pc->port);
   8659 
   8660     if ( SOC_E_NONE != (rv = _phy_bcm542xx_model_rev_get(unit, pc,
   8661                                                    &oui, &model, &rev)) ) {
   8662         return SOC_E_FAIL;
   8663     }
   8664     pc->interface = SOC_PORT_IF_SGMII;  /* 54210/220/240/280/290/294/190/180/140 */
   8665 
   8666     /* determine the chip model */
   8667     switch ( model ) {
   8668 
   8669     case PHY_BCM54210_MODEL:
   8670     case PHY_BCM54220_MODEL:
   8671     case PHY_BCM54280_MODEL:
   8672         /*passthru*/
   8673     case PHY_BCM5428X_MODEL:
   8674         /*passthru*/
   8675     case PHY_BCM54240_MODEL:
   8676         break;
   8677 
   8678     case (PHY_BCM54282_MODEL | PHY_BCM54285_MODEL):
   8679         pi->phy_name = (rev & 0x8) ? "BCM54282" : "BCM54285";
   8680         pc->interface = SOC_PORT_IF_QSGMII;
   8681         break;
   8682 
   8683     case (PHY_BCM54290_MODEL | PHY_BCM54294_MODEL):
   8684         pi->phy_name = (rev & 0x8) ? "BCM54294" : "BCM54290";
   8685         break;
   8686 
   8687     case (PHY_BCM54292_MODEL | PHY_BCM54295_MODEL | PHY_BCM54296_MODEL):
   8688         if ( rev & 0x8 ) {
   8689             pi->phy_name = (0x8 & _phy_bcm542xx_hidden_rev_num_get(unit, pc))
   8690                          ? "BCM54296" : "BCM54295";
   8691         } else {
   8692             pi->phy_name = "BCM54292";
   8693         }
   8694         pc->interface = SOC_PORT_IF_QSGMII;
   8695         break;
   8696 
   8697     case (PHY_BCM54190_MODEL | PHY_BCM54194_MODEL):
   8698         pi->phy_name = (rev & 0x8) ? "BCM54194" : "BCM54190";
   8699         break;
   8700 
   8701     case (PHY_BCM54180_MODEL | PHY_BCM54140_MODEL):
   8702         pi->phy_name = (rev & 0x8) ? "BCM54140" : "BCM54180";
   8703         break;
   8704 
   8705     case (PHY_BCM54182_MODEL | PHY_BCM54185_MODEL):
   8706         if ( rev & 0x8 ) {
   8707             pi->phy_name = (0x8 & _phy_bcm542xx_hidden_rev_num_get(unit, pc))
   8708                          ? "BCM54186" : "BCM54185";
   8709         } else {
   8710             pi->phy_name = "BCM54182";
   8711         }
   8712         pc->interface = SOC_PORT_IF_QSGMII;
   8713         break;
   8714 
   8715     case (PHY_BCM54192_MODEL | PHY_BCM54195_MODEL):
   8716         if ( rev & 0x8 ) {
   8717             pi->phy_name = (0x8 & _phy_bcm542xx_hidden_rev_num_get(unit, pc))
   8718                          ? "BCM54196" : "BCM54195";
   8719         } else {
   8720             pi->phy_name = "BCM54192";
   8721         }
   8722         pc->interface = SOC_PORT_IF_QSGMII;
   8723         break;
   8724 
   8725     default :
   8726         return SOC_E_NOT_FOUND;
   8727     }
   8728 #ifdef INCLUDE_PLP_IMACSEC
   8729     pc->size = sizeof(PHY_BCM542XX_DEV_DESC_t) + sizeof(bcm_plp_base_t_sec_phy_access_t);
   8730 #else
   8731     pc->size = sizeof(PHY_BCM542XX_DEV_DESC_t);
   8732 #endif
   8733     return rv;
   8734 }
   8735 
   8736 /*
   8737  * Function:
   8738  *      phy_bcm542xx_link_up
   8739  * Purpose:
   8740  *      Link up handler
   8741  * Parameters:
   8742  *      unit  - StrataSwitch unit #.
   8743  *      port  - StrataSwitch port #.
   8744  * Returns:
   8745  *      SOC_E_NONE
   8746  */
   8747 STATIC int
   8748 phy_bcm542xx_link_up(int unit, soc_port_t port)
   8749 {
   8750     int speed = 0;
   8751 #ifdef INCLUDE_PLP_IMACSEC
   8752     phy_ctrl_t* pc;
   8753     pc = EXT_PHY_SW_STATE(unit, port);
   8754 #endif
   8755     SOC_IF_ERROR_RETURN
   8756         (phy_bcm542xx_speed_get(unit, port, &speed));
   8757 
   8758     /* Notify interface to internal PHY */
   8759     SOC_IF_ERROR_RETURN
   8760         (soc_phyctrl_notify(unit, port, phyEventInterface, IS_GMII_PORT(unit, port) ? SOC_PORT_IF_GMII : SOC_PORT_IF_SGMII));
   8761 
   8762     /* Situation observed with Saber devices XGXS16g1l+BCM54640E
   8763        Linkscan is not updating speed for internal phy xgxs16g1l. 
   8764        It was observed that when speed is set to 100M the int phy 
   8765        is still set to 1G and traffic does not flow through untill 
   8766        int phy speed is also update to 100M. This applies to other 
   8767        speeds as well. 
   8768        Explicitly send speed notify to int phy from ext phy.
   8769     */
   8770     SOC_IF_ERROR_RETURN
   8771         (soc_phyctrl_notify(unit, port, phyEventSpeed, speed));
   8772 #ifdef INCLUDE_PLP_IMACSEC
   8773     /* Check if MACSEC_SWITCH_SIDE_POLICY is DUPLEX_GATEWAY mode 
   8774      * Half duplex mode is supported only in 10 Mbps and 100 Mbps*/
   8775     if  (pc->macsec_enable) {
   8776         int duplex;
   8777         /* Duplex Gateway mode for supporting half-duplex-free switches:   *\
   8778         |* When line-side PHY lilnks up at half-duplex,                    *|
   8779         \* set half-duplex to line-side MAC, full-duplex to switch-side MAC*/
   8780 
   8781         /* get the duplex status from line side */
   8782         SOC_IF_ERROR_RETURN(
   8783             phy_bcm542xx_duplex_get(unit, port, &duplex) );
   8784         if ( pc->macsec_switch_fixed_speed  == speed  &&
   8785             pc->macsec_switch_fixed_duplex == duplex) {
   8786             return SOC_E_NONE;    /* speed/duplex unchanged */
   8787         }
   8788 
   8789         pc->macsec_switch_fixed_speed  = speed;
   8790         pc->macsec_switch_fixed_duplex = duplex;   /* Change the duplex mode to half duplex */
   8791         /* Config duplex Gateway parameters accordingly */
   8792         SOC_IF_ERROR_RETURN(
   8793                 phy_unimac_switch_side_set_params(unit,port,
   8794                               pc->macsec_mac_policy,
   8795                               speed, duplex, pc->macsec_switch_fixed_pause) );
   8796         /* under DUPLEX_GATEWAY mode, always Full-Duplex on system side */
   8797         SOC_IF_ERROR_RETURN
   8798             (soc_phyctrl_notify(unit, port, phyEventDuplex, TRUE));
   8799     }
   8800 #endif
   8801     return SOC_E_NONE;
   8802 }
   8803 
   8804 /*
   8805  * Function:
   8806  *    phy_bcm542xx_oam_config_set
   8807  * Purpose:
   8808  *
   8809  * Parameters:
   8810  *
   8811  * Returns:
   8812  */
   8813 int
   8814 phy_bcm542xx_oam_config_set(int unit, soc_port_t port, soc_port_config_phy_oam_t *conf) {
   8815     uint16  data = 0, mask = 0;
   8816     uint16 dm_tx_cntl_data = 0, dm_rx_cntl_data = 0;
   8817     phy_ctrl_t *pc;
   8818     soc_port_phy_timesync_config_t timesync_conf;
   8819     
   8820     sal_memset(&timesync_conf, 0, sizeof(soc_port_phy_timesync_config_t));
   8821 
   8822     if (NULL == conf) {
   8823         return SOC_E_PARAM;
   8824     }
   8825    
   8826     pc = EXT_PHY_SW_STATE(unit, port);
   8827 
   8828     /* 1. en_1588_softrst */ 
   8829     /* 2. en_RGMII_Timing_RGMII */
   8830     
   8831     /* Setup timesync 1588 */ 
   8832     timesync_conf.flags = SOC_PORT_PHY_TIMESYNC_ENABLE;
   8833     phy_bcm542xx_timesync_config_set(unit, port, &timesync_conf);
   8834     
   8835     /***********************************************************************
   8836      * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   8837      * To access TOP level registers use phy_id of port0. Override this ports 
   8838      */
   8839     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   8840   
   8841     /* TX: Delay measurement mode */
   8842     switch( conf->tx_dm_config.mode ) {
   8843         case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731:
   8844             dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_EN;
   8845             if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) {
   8846                 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_Y1731_TS_SEL;
   8847             }   
   8848             break;
   8849         case SOC_PORT_CONFIG_PHY_OAM_DM_BHH:
   8850             data = 0;
   8851             mask = 0;
   8852             if (!(conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE) ) {
   8853                 data |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS;
   8854             }    
   8855             if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) {
   8856                 data |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN;
   8857             }   
   8858             data |=  PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN;
   8859             mask =  PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN
   8860                     | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS
   8861                     | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN;
   8862             phy_bcm542xx_direct_reg_modify(unit, pc,
   8863                     PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET,
   8864                     data, mask);
   8865 
   8866             if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) {
   8867                 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL;
   8868             }   
   8869             break;
   8870         case SOC_PORT_CONFIG_PHY_OAM_DM_IETF:
   8871             data = 0;
   8872             mask = 0;
   8873             if (!(conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE) ) {
   8874                 data |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS;
   8875             }    
   8876             if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) {
   8877                 data |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN;
   8878             }   
   8879             data |=  PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN;
   8880             mask =  PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN
   8881                     | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS
   8882                     | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN;
   8883             phy_bcm542xx_direct_reg_modify(unit, pc,
   8884                     PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET,
   8885                     data, mask);
   8886 
   8887             dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_IETF_EN;
   8888             if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) {
   8889                 /* Same bit as for BHH */
   8890                 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL;
   8891             }   
   8892             break;
   8893         default:
   8894             if ( conf->tx_dm_config.mode == 0) {
   8895                 break;
   8896             }
   8897             /********************************************************
   8898              * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   8899              * To access TOP level registers use phy_id of port0. 
   8900                Now restore back 
   8901              */
   8902             pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   8903             return SOC_E_CONFIG;
   8904     }
   8905 
   8906     /* RX: Delay measurement mode */
   8907     switch(conf->rx_dm_config.mode) {
   8908         case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731:
   8909             dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_EN;
   8910             if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) {
   8911                 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_Y1731_TS_SEL;
   8912             }   
   8913             break;
   8914         case SOC_PORT_CONFIG_PHY_OAM_DM_BHH:
   8915             data = 0;
   8916             mask = 0;
   8917             if (!(conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE) ) {
   8918                 data |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS;
   8919             }    
   8920             if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) {
   8921                 data |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN;
   8922             }   
   8923             data |=  PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN;
   8924             mask =  PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN
   8925                     | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS
   8926                     | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN;
   8927             phy_bcm542xx_direct_reg_modify(unit, pc,
   8928                     PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET,
   8929                     data, mask);
   8930             
   8931             if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) {
   8932                 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_BHH_TS_SEL;
   8933             }   
   8934             break;
   8935         case SOC_PORT_CONFIG_PHY_OAM_DM_IETF:
   8936             data = 0;
   8937             mask = 0;
   8938             if (!(conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE) ) {
   8939                 data |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS;
   8940             }    
   8941             if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) {
   8942                 data |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN;
   8943             }   
   8944             data |=  PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN;
   8945             mask =  PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN
   8946                     | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS
   8947                     | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN;
   8948             phy_bcm542xx_direct_reg_modify(unit, pc,
   8949                     PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET,
   8950                     data, mask);
   8951 
   8952             dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_IETF_EN;
   8953             if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) {
   8954                 /* Same bit as for BHH */
   8955                 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_BHH_TS_SEL;
   8956             }   
   8957             break;
   8958         default:
   8959             if ( conf->rx_dm_config.mode == 0) {
   8960                 break;
   8961             }
   8962             /********************************************************
   8963              * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   8964              * To access TOP level registers use phy_id of port0. 
   8965                Now restore back 
   8966              */
   8967             pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   8968             return SOC_E_CONFIG;
   8969     }    
   8970 
   8971     /* Enable the 1588 counter includes the delay measurement packet */   
   8972    dm_tx_cntl_data |= (dm_tx_cntl_data)? PHY_BCM542XX_TOP_1588_DM_TX_CNTL_1588_CNT_EN : dm_tx_cntl_data;
   8973    dm_rx_cntl_data |= (dm_rx_cntl_data)? PHY_BCM542XX_TOP_1588_DM_TX_CNTL_1588_CNT_EN : dm_rx_cntl_data;
   8974 
   8975    if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE ) {
   8976        dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_MAC_EN;
   8977    }    
   8978    if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE ) {
   8979        dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_CW_EN;
   8980    }   
   8981    if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) {
   8982        dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_ENTROPY_EN;
   8983    }   
   8984 
   8985    if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE ) {
   8986        dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_MAC_EN;
   8987    }    
   8988    if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE ) {
   8989        dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_CW_EN;
   8990    }   
   8991    if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) {
   8992        dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_ENTROPY_EN;
   8993    }   
   8994 
   8995    mask = PHY_BCM542XX_TOP_1588_DM_TX_CNTL_EN 
   8996           | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_MAC_EN 
   8997           | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_CW_EN 
   8998           | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_ENTROPY_EN 
   8999           | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_Y1731_TS_SEL 
   9000           | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL  
   9001           | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_IETF_EN 
   9002           | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_1588_CNT_EN;
   9003 
   9004    phy_bcm542xx_direct_reg_modify(unit, pc,
   9005            PHY_BCM542XX_TOP_1588_DM_TX_CNTL_REG_OFFSET,
   9006            dm_tx_cntl_data, mask);
   9007    
   9008    mask = PHY_BCM542XX_TOP_1588_DM_RX_CNTL_EN 
   9009           | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_MAC_EN 
   9010           | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_CW_EN 
   9011           | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_ENTROPY_EN 
   9012           | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_Y1731_TS_SEL 
   9013           | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_BHH_TS_SEL  
   9014           | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_IETF_EN 
   9015           | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_1588_CNT_EN;
   9016    
   9017    phy_bcm542xx_direct_reg_modify(unit, pc,
   9018            PHY_BCM542XX_TOP_1588_DM_RX_CNTL_REG_OFFSET,
   9019            dm_rx_cntl_data, mask);
   9020 
   9021     /***********************************************************************
   9022      * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   9023      * To access TOP level registers use phy_id of port0. Now restore back 
   9024      */
   9025     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   9026 
   9027     /* Save the config */
   9028     sal_memcpy(PHY_BCM542XX_DEV_OAM_CONFIG_PTR(pc), conf, sizeof(soc_port_config_phy_oam_t));
   9029 
   9030     return SOC_E_NONE;
   9031 }
   9032 
   9033 /*
   9034  * Function:
   9035  *    phy_bcm542xx_oam_config_get
   9036  * Purpose:
   9037  *
   9038  * Parameters:
   9039  *
   9040  * Returns:
   9041  */
   9042 int
   9043 phy_bcm542xx_oam_config_get(int unit, soc_port_t port, soc_port_config_phy_oam_t *conf) {
   9044     uint16 dm_tx_cntl_data = 0, dm_rx_cntl_data = 0;
   9045     uint16 mpls_tx_cntl_data = 0, mpls_rx_cntl_data = 0;
   9046     phy_ctrl_t *pc;
   9047    
   9048     sal_memset(conf, 0, sizeof(soc_port_config_phy_oam_t));
   9049 
   9050     pc = EXT_PHY_SW_STATE(unit, port);
   9051 
   9052     /***********************************************************************
   9053      * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   9054      * To access TOP level registers use phy_id of port0. Override this ports 
   9055      */
   9056     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   9057    
   9058     /* Read config registers */ 
   9059     phy_bcm542xx_direct_reg_read(unit, pc,
   9060             PHY_BCM542XX_TOP_1588_DM_TX_CNTL_REG_OFFSET,
   9061             &dm_tx_cntl_data);
   9062     phy_bcm542xx_direct_reg_read(unit, pc,
   9063             PHY_BCM542XX_TOP_1588_DM_RX_CNTL_REG_OFFSET,
   9064             &dm_rx_cntl_data);
   9065     phy_bcm542xx_direct_reg_read(unit, pc,
   9066             PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET,
   9067             &mpls_tx_cntl_data);
   9068     phy_bcm542xx_direct_reg_read(unit, pc,
   9069             PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET,
   9070             &mpls_rx_cntl_data);
   9071 
   9072     /* Tx Config Mode */
   9073     if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_EN ) {
   9074         conf->tx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_Y1731;
   9075         if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_Y1731_TS_SEL) {
   9076             conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT;
   9077         }     
   9078     } else if ((dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_IETF_EN) 
   9079             && (mpls_tx_cntl_data & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN)){
   9080         conf->tx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_IETF;
   9081         if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL) {
   9082             conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT;
   9083         }     
   9084     } else if (mpls_tx_cntl_data & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN ) {
   9085         conf->tx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_BHH;
   9086         if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL) {
   9087             conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT;
   9088         }     
   9089     }
   9090 
   9091     /* Rx Config Mode */
   9092     if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_RX_CNTL_EN ) {
   9093         conf->rx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_Y1731;
   9094         if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_Y1731_TS_SEL) {
   9095             conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT;
   9096         }     
   9097     } else if ((dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_RX_CNTL_IETF_EN) 
   9098             && (mpls_rx_cntl_data & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN)){
   9099         conf->rx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_IETF;
   9100         if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL) {
   9101             conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT;
   9102         }     
   9103     } else if (mpls_rx_cntl_data & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN ) {
   9104         conf->rx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_BHH;
   9105         if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL) {
   9106             conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT;
   9107         }     
   9108     }
   9109     
   9110     /* Tx Config Flags */
   9111     if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_MAC_EN ) {
   9112         conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE;
   9113     }    
   9114     if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_CW_EN ) {
   9115         conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE; 
   9116     }     
   9117     if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_ENTROPY_EN ) {
   9118         conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE;
   9119     }     
   9120 
   9121     /* Rx Config Flags */
   9122     if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_RX_CNTL_MAC_EN ) {
   9123         conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE;
   9124     }    
   9125     if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_RX_CNTL_CW_EN ) {
   9126         conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE; 
   9127     }     
   9128     if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_RX_CNTL_ENTROPY_EN ) {
   9129         conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE;
   9130     }     
   9131 
   9132     /***********************************************************************
   9133      * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   9134      * To access TOP level registers use phy_id of port0. Now restore back 
   9135      */
   9136     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   9137     /* Save the config */
   9138     sal_memcpy(PHY_BCM542XX_DEV_OAM_CONFIG_PTR(pc), conf, sizeof(soc_port_config_phy_oam_t));
   9139     return SOC_E_NONE;
   9140 }
   9141 
   9142 /*
   9143  * Function:
   9144  *    phy_bcm542xx_oam_control_set
   9145  * Purpose:
   9146  *
   9147  * Parameters:
   9148  *
   9149  * Returns:
   9150  */
   9151 int
   9152 phy_bcm542xx_oam_control_set(int unit, soc_port_t port, soc_port_control_phy_oam_t type, uint64 value)
   9153 {
   9154     uint16  dev_port = 0;
   9155     phy_ctrl_t *pc = NULL;
   9156     soc_port_config_phy_oam_t *config = NULL;
   9157     soc_port_config_phy_oam_dm_mode_t tx_mode = 0;
   9158     soc_port_config_phy_oam_dm_mode_t rx_mode = 0;
   9159     uint32 tx_flags;
   9160 
   9161     pc = EXT_PHY_SW_STATE(unit, port);
   9162 
   9163     /* Dev port numbers from 0-7 */
   9164     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   9165     
   9166     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   9167        of the device. For example to enable autogrEEEn on port0, 
   9168        rdb register for port 4 0x808 need to be used. 
   9169        Refer package configuration document.
   9170      */
   9171     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   9172         dev_port += 4;
   9173     }
   9174     
   9175    
   9176     /* Config saved during config _set or read during config _get */ 
   9177     config = PHY_BCM542XX_DEV_OAM_CONFIG_PTR(pc); 
   9178     tx_mode = config->tx_dm_config.mode;
   9179     tx_flags = config->tx_dm_config.flags;
   9180     rx_mode = config->rx_dm_config.mode;
   9181     
   9182     /***********************************************************************
   9183      * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   9184      * To access TOP level registers use phy_id of port0. Override this ports 
   9185      */
   9186     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   9187 
   9188     switch(type) {
   9189         case SOC_PORT_CONTROL_PHY_OAM_DM_TX_ETHERTYPE:
   9190             switch(tx_mode) {
   9191                 case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731:
   9192                     if (tx_flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { /*NTP */
   9193                         phy_bcm542xx_direct_reg_write(unit, pc,
   9194                                 PHY_BCM542XX_TOP_1588_DM_ETHTYPE2_REG_OFFSET,
   9195                                 (COMPILER_64_LO(value) & 0xffff));
   9196                     } else { /*PTP */
   9197                         phy_bcm542xx_direct_reg_write(unit, pc,
   9198                                 PHY_BCM542XX_TOP_1588_DM_ETHTYPE1_REG_OFFSET,
   9199                                 (COMPILER_64_LO(value) & 0xffff));
   9200                     }
   9201                     break;
   9202                 case SOC_PORT_CONFIG_PHY_OAM_DM_BHH:
   9203                     if (tx_flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { /*NTP */
   9204                         phy_bcm542xx_direct_reg_write(unit, pc,
   9205                                 PHY_BCM542XX_TOP_1588_DM_ETHTYPE4_REG_OFFSET,
   9206                                 (COMPILER_64_LO(value) & 0xffff));
   9207                     } else { /*PTP */
   9208                         phy_bcm542xx_direct_reg_write(unit, pc,
   9209                                 PHY_BCM542XX_TOP_1588_DM_ETHTYPE3_REG_OFFSET,
   9210                                 (COMPILER_64_LO(value) & 0xffff));
   9211                     }
   9212                     break;
   9213                 case SOC_PORT_CONFIG_PHY_OAM_DM_IETF:
   9214                     phy_bcm542xx_direct_reg_write(unit, pc,
   9215                             PHY_BCM542XX_TOP_1588_DM_ETHTYPE9_REG_OFFSET,
   9216                             (COMPILER_64_LO(value) & 0xffff));
   9217                     break;
   9218                 default:
   9219                     /********************************************************
   9220                      * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   9221                      * To access TOP level registers use phy_id of port0. 
   9222                      Now restore back 
   9223                      */
   9224                     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   9225                     return SOC_E_CONFIG;    
   9226             }
   9227 
   9228             break;
   9229         case SOC_PORT_CONTROL_PHY_OAM_DM_RX_ETHERTYPE:
   9230             switch(rx_mode) {
   9231                 case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731:
   9232                     phy_bcm542xx_direct_reg_write(unit, pc,
   9233                             PHY_BCM542XX_TOP_1588_DM_ETHTYPE5_REG_OFFSET,
   9234                             (COMPILER_64_LO(value) & 0xffff));
   9235                     break;
   9236                 case SOC_PORT_CONFIG_PHY_OAM_DM_BHH:
   9237                     phy_bcm542xx_direct_reg_write(unit, pc,
   9238                             PHY_BCM542XX_TOP_1588_DM_ETHTYPE8_REG_OFFSET,
   9239                             (COMPILER_64_LO(value) & 0xffff));
   9240                     break;
   9241                 case SOC_PORT_CONFIG_PHY_OAM_DM_IETF:
   9242                     phy_bcm542xx_direct_reg_write(unit, pc,
   9243                             PHY_BCM542XX_TOP_1588_DM_ETHTYPE10_REG_OFFSET,
   9244                             (COMPILER_64_LO(value) & 0xffff));
   9245                     break;
   9246                 default:
   9247                     /********************************************************
   9248                      * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   9249                      * To access TOP level registers use phy_id of port0. 
   9250                      Now restore back 
   9251                      */
   9252                     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   9253                     return SOC_E_CONFIG;    
   9254             }
   9255             break;
   9256         case SOC_PORT_CONTROL_PHY_OAM_DM_TX_PORT_MAC_ADDRESS_INDEX:
   9257             phy_bcm542xx_direct_reg_write(unit, pc,
   9258                     PHY_BCM542XX_TOP_1588_DM_MAC_CTL_0_REG_OFFSET,
   9259                     (COMPILER_64_LO(value) & 0x0003) << (dev_port*2));
   9260             break;
   9261         case SOC_PORT_CONTROL_PHY_OAM_DM_RX_PORT_MAC_ADDRESS_INDEX:
   9262             phy_bcm542xx_direct_reg_write(unit, pc,
   9263                     PHY_BCM542XX_TOP_1588_DM_MAC_CTL_1_REG_OFFSET,
   9264                     (COMPILER_64_LO(value) & 0x0003) << (dev_port*2));
   9265             break;
   9266         case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_1:
   9267             phy_bcm542xx_direct_reg_write(unit, pc,
   9268                     PHY_BCM542XX_TOP_1588_DM_MAC_L1_0_REG_OFFSET,
   9269                     (COMPILER_64_LO(value) & 0xffff));
   9270             phy_bcm542xx_direct_reg_write(unit, pc,
   9271                     PHY_BCM542XX_TOP_1588_DM_MAC_L1_1_REG_OFFSET,
   9272                     (COMPILER_64_LO(value) >> 16) & 0xffff);
   9273             phy_bcm542xx_direct_reg_write(unit, pc,
   9274                     PHY_BCM542XX_TOP_1588_DM_MAC_L1_2_REG_OFFSET,
   9275                     (COMPILER_64_HI(value) & 0xffff));
   9276             break;
   9277         case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_2:
   9278             phy_bcm542xx_direct_reg_write(unit, pc,
   9279                     PHY_BCM542XX_TOP_1588_DM_MAC_L2_0_REG_OFFSET,
   9280                     (COMPILER_64_LO(value) & 0xffff));
   9281             phy_bcm542xx_direct_reg_write(unit, pc,
   9282                     PHY_BCM542XX_TOP_1588_DM_MAC_L2_1_REG_OFFSET,
   9283                     (COMPILER_64_LO(value) >> 16) & 0xffff);
   9284             phy_bcm542xx_direct_reg_write(unit, pc,
   9285                     PHY_BCM542XX_TOP_1588_DM_MAC_L2_2_REG_OFFSET,
   9286                     (COMPILER_64_HI(value) & 0xffff));
   9287             break;
   9288         case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_3:
   9289             phy_bcm542xx_direct_reg_write(unit, pc,
   9290                     PHY_BCM542XX_TOP_1588_DM_MAC_L3_0_REG_OFFSET,
   9291                     (COMPILER_64_LO(value) & 0xffff));
   9292             phy_bcm542xx_direct_reg_write(unit, pc,
   9293                     PHY_BCM542XX_TOP_1588_DM_MAC_L3_1_REG_OFFSET,
   9294                     (COMPILER_64_LO(value) >> 16) & 0xffff);
   9295             phy_bcm542xx_direct_reg_write(unit, pc,
   9296                     PHY_BCM542XX_TOP_1588_DM_MAC_L3_2_REG_OFFSET,
   9297                     (COMPILER_64_HI(value) & 0xffff));
   9298             break;
   9299         default:
   9300             /********************************************************
   9301              * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   9302              * To access TOP level registers use phy_id of port0. 
   9303                Now restore back 
   9304              */
   9305             pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   9306             return SOC_E_PARAM;
   9307     }     
   9308     
   9309 
   9310     /***********************************************************************
   9311      * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   9312      * To access TOP level registers use phy_id of port0. Now restore back 
   9313      */
   9314     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   9315                 
   9316     return SOC_E_NONE;
   9317 }
   9318 
   9319 /*
   9320  * Function:
   9321  *    phy_bcm542xx_oam_control_get
   9322  * Purpose:
   9323  *
   9324  * Parameters:
   9325  *
   9326  * Returns:
   9327  */
   9328 int
   9329 phy_bcm542xx_oam_control_get(int unit, soc_port_t port, soc_port_control_phy_oam_t type, uint64 *value) {
   9330     uint16  dev_port = 0;
   9331     phy_ctrl_t *pc = NULL;
   9332     soc_port_config_phy_oam_t *config = NULL;
   9333     uint16 value01 = 0, value02 = 0, value03 = 0;
   9334     soc_port_config_phy_oam_dm_mode_t tx_mode = 0, rx_mode = 0;
   9335     uint32 tx_flags;
   9336 
   9337     pc = EXT_PHY_SW_STATE(unit, port);
   9338 
   9339     /* Dev port numbers from 0-7 */
   9340     dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc);
   9341     
   9342     /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 
   9343        of the device. For example to enable autogrEEEn on port0, 
   9344        rdb register for port 4 0x808 need to be used. 
   9345        Refer package configuration document.
   9346      */
   9347     if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) {
   9348         dev_port += 4;
   9349     }
   9350 
   9351     /* Config saved during config _set */ 
   9352     config = PHY_BCM542XX_DEV_OAM_CONFIG_PTR(pc); 
   9353     tx_mode = config->tx_dm_config.mode;
   9354     tx_flags = config->tx_dm_config.flags;
   9355     rx_mode = config->rx_dm_config.mode;
   9356 
   9357     /***********************************************************************
   9358      * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE  
   9359      * To access TOP level registers use phy_id of port0. Override this ports 
   9360      */
   9361     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc);
   9362 
   9363     switch(type) {
   9364         case SOC_PORT_CONTROL_PHY_OAM_DM_TX_ETHERTYPE:
   9365             switch(tx_mode) {
   9366                 case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731:
   9367                     if (tx_flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { /*NTP */
   9368                         phy_bcm542xx_direct_reg_read(unit, pc,
   9369                                 PHY_BCM542XX_TOP_1588_DM_ETHTYPE2_REG_OFFSET,
   9370                                 &value01);
   9371                     } else { /*PTP */
   9372                         phy_bcm542xx_direct_reg_read(unit, pc,
   9373                                 PHY_BCM542XX_TOP_1588_DM_ETHTYPE1_REG_OFFSET,
   9374                                 &value01);
   9375                     }
   9376                     break;
   9377                 case SOC_PORT_CONFIG_PHY_OAM_DM_BHH:
   9378                     if (tx_flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { /*NTP */
   9379                         phy_bcm542xx_direct_reg_read(unit, pc,
   9380                                 PHY_BCM542XX_TOP_1588_DM_ETHTYPE4_REG_OFFSET,
   9381                                 &value01);
   9382                     } else { /*PTP */
   9383                         phy_bcm542xx_direct_reg_read(unit, pc,
   9384                                 PHY_BCM542XX_TOP_1588_DM_ETHTYPE3_REG_OFFSET,
   9385                                 &value01);
   9386                     }
   9387                     break;
   9388                 case SOC_PORT_CONFIG_PHY_OAM_DM_IETF:
   9389                     phy_bcm542xx_direct_reg_read(unit, pc,
   9390                             PHY_BCM542XX_TOP_1588_DM_ETHTYPE9_REG_OFFSET,
   9391                                 &value01);
   9392                     break;
   9393                 default:
   9394                     break;    
   9395             }
   9396  
   9397             COMPILER_64_SET((*value), 0,  (uint32)value01);
   9398 
   9399             break;
   9400         case SOC_PORT_CONTROL_PHY_OAM_DM_RX_ETHERTYPE:
   9401             switch(rx_mode) {
   9402                 case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731:
   9403                     phy_bcm542xx_direct_reg_read(unit, pc,
   9404                             PHY_BCM542XX_TOP_1588_DM_ETHTYPE5_REG_OFFSET,
   9405                                 &value01);
   9406                     break;
   9407                 case SOC_PORT_CONFIG_PHY_OAM_DM_BHH:
   9408                     phy_bcm542xx_direct_reg_read(unit, pc,
   9409                             PHY_BCM542XX_TOP_1588_DM_ETHTYPE8_REG_OFFSET,
   9410                                 &value01);
   9411                     break;
   9412                 case SOC_PORT_CONFIG_PHY_OAM_DM_IETF:
   9413                     phy_bcm542xx_direct_reg_read(unit, pc,
   9414                             PHY_BCM542XX_TOP_1588_DM_ETHTYPE10_REG_OFFSET,
   9415                                 &value01);
   9416                     break;
   9417                 default:
   9418                     break;    
   9419             }
   9420             COMPILER_64_SET((*value), 0, (uint32)value01);
   9421             break;
   9422         case SOC_PORT_CONTROL_PHY_OAM_DM_TX_PORT_MAC_ADDRESS_INDEX:
   9423             phy_bcm542xx_direct_reg_read(unit, pc,
   9424                     PHY_BCM542XX_TOP_1588_DM_MAC_CTL_0_REG_OFFSET,
   9425                     &value01);
   9426             COMPILER_64_SET((*value), 0, ((uint32)value01 >> (dev_port*2)) & 0x3);
   9427             break;
   9428         case SOC_PORT_CONTROL_PHY_OAM_DM_RX_PORT_MAC_ADDRESS_INDEX:
   9429             phy_bcm542xx_direct_reg_read(unit, pc,
   9430                     PHY_BCM542XX_TOP_1588_DM_MAC_CTL_1_REG_OFFSET,
   9431                     &value01);
   9432             COMPILER_64_SET((*value), 0, ((uint32)value01 >> (dev_port*2)) & 0x3);
   9433             break;
   9434         case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_1:
   9435             phy_bcm542xx_direct_reg_read(unit, pc,
   9436                     PHY_BCM542XX_TOP_1588_DM_MAC_L1_0_REG_OFFSET,
   9437                     &value01);
   9438             phy_bcm542xx_direct_reg_read(unit, pc,
   9439                     PHY_BCM542XX_TOP_1588_DM_MAC_L1_1_REG_OFFSET,
   9440                     &value02);
   9441             phy_bcm542xx_direct_reg_read(unit, pc,
   9442                     PHY_BCM542XX_TOP_1588_DM_MAC_L1_2_REG_OFFSET,
   9443                     &value03);
   9444             COMPILER_64_SET((*value), (uint32)value03, 
   9445                              ((uint32)value02 << 16) | ((uint32)value01));
   9446             break;
   9447         case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_2:
   9448             phy_bcm542xx_direct_reg_read(unit, pc,
   9449                     PHY_BCM542XX_TOP_1588_DM_MAC_L2_0_REG_OFFSET,
   9450                     &value01);
   9451             phy_bcm542xx_direct_reg_read(unit, pc,
   9452                     PHY_BCM542XX_TOP_1588_DM_MAC_L2_1_REG_OFFSET,
   9453                     &value02);
   9454             phy_bcm542xx_direct_reg_read(unit, pc,
   9455                     PHY_BCM542XX_TOP_1588_DM_MAC_L2_2_REG_OFFSET,
   9456                     &value03);
   9457             COMPILER_64_SET((*value), (uint32)value03, 
   9458                              ((uint32)value02 << 16) | ((uint32)value01));
   9459             break;
   9460         case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_3:
   9461             phy_bcm542xx_direct_reg_read(unit, pc,
   9462                     PHY_BCM542XX_TOP_1588_DM_MAC_L3_0_REG_OFFSET,
   9463                     &value01);
   9464             phy_bcm542xx_direct_reg_read(unit, pc,
   9465                     PHY_BCM542XX_TOP_1588_DM_MAC_L3_1_REG_OFFSET,
   9466                     &value02);
   9467             phy_bcm542xx_direct_reg_read(unit, pc,
   9468                     PHY_BCM542XX_TOP_1588_DM_MAC_L3_2_REG_OFFSET,
   9469                     &value03);
   9470             COMPILER_64_SET((*value), (uint32)value03, 
   9471                              ((uint32)value02 << 16) | ((uint32)value01));
   9472             break;
   9473         default:
   9474             /********************************************************
   9475              * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   9476              * To access TOP level registers use phy_id of port0. 
   9477                Now restore back 
   9478              */
   9479             pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   9480             return SOC_E_PARAM;
   9481     }
   9482     /***********************************************************************
   9483      * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE
   9484      * To access TOP level registers use phy_id of port0. Now restore back 
   9485      */
   9486     pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc);
   9487     
   9488     return SOC_E_NONE;
   9489 }
   9490 
   9491 #ifdef BROADCOM_DEBUG
   9492 
   9493 int
   9494 phy_bcm542xx_rdb_reg_set(int unit, soc_port_t port, int rdb, int value){
   9495     phy_ctrl_t *pc = NULL;
   9496     uint16 valuer;
   9497 
   9498     pc = EXT_PHY_SW_STATE(unit, port);
   9499 
   9500     phy_bcm542xx_direct_reg_write(unit, pc,(uint16)rdb, (uint16)(value & 0xffff));
   9501     phy_bcm542xx_direct_reg_read(unit, pc,(uint16)rdb, &valuer);
   9502 
   9503     LOG_INFO(BSL_LS_SOC_PHY,
   9504              (BSL_META_U(unit, "u=%d p=%d rdb=0x%04x value read back=0x%04x\n"),
   9505               unit, port, (uint16) rdb, valuer));
   9506     return SOC_E_NONE;
   9507 }
   9508 
   9509 int
   9510 phy_bcm542xx_rdb_reg_get(int unit, soc_port_t port, int rdb) {
   9511     phy_ctrl_t *pc = NULL;
   9512     uint16 value;
   9513 
   9514     pc = EXT_PHY_SW_STATE(unit, port);
   9515 
   9516     phy_bcm542xx_direct_reg_read(unit, pc,(uint16)rdb, &value);
   9517 
   9518     LOG_INFO(BSL_LS_SOC_PHY,
   9519              (BSL_META_U(unit,"u=%d p=%d rdb=0x%04x value=0x%04x\n"),
   9520               unit, port, (uint16)rdb, value));
   9521     return SOC_E_NONE;
   9522 }
   9523 
   9524 #endif
   9525 
   9526 /*
   9527  * Variable:    phy_542xxdrv_ge
   9528  * Purpose:     PHY driver for 542XX
   9529  */
   9530 phy_driver_t phy_542xxdrv_ge = {
   9531     "542XX Gigabit PHY Driver",
   9532     phy_bcm542xx_init,
   9533     phy_bcm542xx_reset,         /* phy_fe_ge_reset */
   9534     phy_bcm542xx_link_get,
   9535     phy_bcm542xx_enable_set,
   9536     phy_bcm542xx_enable_get,
   9537     phy_bcm542xx_duplex_set,
   9538     phy_bcm542xx_duplex_get,
   9539     phy_bcm542xx_speed_set,
   9540     phy_bcm542xx_speed_get,
   9541     phy_bcm542xx_master_set,
   9542     phy_bcm542xx_master_get,
   9543     phy_bcm542xx_autoneg_set,
   9544     phy_bcm542xx_autoneg_get,
   9545     NULL,                       /* pd_adv_local_set */
   9546     NULL,                       /* pd_adv_local_get */
   9547     NULL,                       /* pd_adv_remote_get */
   9548     phy_bcm542xx_lb_set,
   9549     phy_bcm542xx_lb_get,
   9550     phy_bcm542xx_interface_set,
   9551     phy_bcm542xx_interface_get,
   9552     NULL,                       /* pd_ability */
   9553     phy_bcm542xx_link_up,       /* pd_linkup */
   9554     NULL,                       /* pd_linkdn_evt */
   9555     phy_bcm542xx_mdix_set,
   9556     phy_bcm542xx_mdix_get,
   9557     phy_bcm542xx_mdix_status_get,
   9558     phy_bcm542xx_medium_config_set,
   9559     phy_bcm542xx_medium_config_get,
   9560     phy_bcm542xx_medium_status,
   9561     phy_54280_cable_diag_dispatch,
   9562     NULL,                       /* pd_link_change */
   9563     phy_bcm542xx_control_set,      
   9564     phy_bcm542xx_control_get,      
   9565     phy_ge_reg_read,
   9566     phy_ge_reg_write,
   9567     phy_ge_reg_modify,
   9568     NULL,                       /* pd_notify */
   9569     phy_bcm542xx_probe,         /* pd_probe */
   9570     phy_bcm542xx_ability_advert_set,  
   9571     phy_bcm542xx_ability_advert_get,  
   9572     phy_bcm542xx_ability_remote_get,  
   9573     phy_bcm542xx_ability_local_get,
   9574     NULL,                       /* pd_firmware_set */
   9575     phy_bcm542xx_timesync_config_set,
   9576     phy_bcm542xx_timesync_config_get,
   9577     phy_bcm542xx_timesync_control_set,
   9578     phy_bcm542xx_timesync_control_get,
   9579     NULL, /* pd_diag_ctrl */
   9580     NULL, /* pd_lane_control_set */
   9581     NULL, /* pd_lane_control_get */
   9582     NULL, /* pd_lane_reg_read */
   9583     NULL, /* pd_lane_reg_write */
   9584     phy_bcm542xx_oam_config_set,
   9585     phy_bcm542xx_oam_config_get,
   9586     phy_bcm542xx_oam_control_set,
   9587     phy_bcm542xx_oam_control_get,
   9588     phy_bcm542xx_timesync_enhanced_capture_get
   9589 };
   9590 
   9591 #else /* INCLUDE_PHY_542XX */
   9592 int _soc_phy_542xx_not_empty;
   9593 #endif /* INCLUDE_PHY_542XX */