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

phy543xx.c (91279B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  */
      7 
      8 /*
      9  * File:        phy54380.c
     10  * Purpose:     PHY driver for BCM54380 (MACSec)
     11  *
     12  * Supported BCM546X Family of PHY devices:
     13  *
     14  *      Device  Ports   Media                           MAC Interface
     15  *      54380   8       Copper(no Fiber)                SGMII
     16  *      54382   8       Copper(no Fiber)                2 QSGMII
     17  *      54340   4       Copper/Fiber                    4 SGMII
     18  *      54385   8       Copper/Fiber                    2 QSGMII
     19 
     20  * Workarounds:
     21  *
     22  *
     23  * Notes:
     24  */ 
     25 
     26 
     27 
     28 #include <sal/types.h>
     29 #include <sal/core/spl.h>
     30 #include <shared/bsl.h>
     31 #include <soc/drv.h>
     32 #include <soc/debug.h>
     33 #include <soc/error.h>
     34 #include <soc/phyreg.h>
     35 
     36 #include <soc/phy.h>
     37 #include <soc/phy/phyctrl.h>
     38 #include <soc/phy/drv.h>
     39 
     40 #include "phydefs.h"      /* Must include before other phy related includes */
     41 
     42 
     43 
     44 #ifdef INCLUDE_MACSEC
     45 #if defined(INCLUDE_PHY_54380)
     46 #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
     47 #include "phyident.h"
     48 #include "phyreg.h"
     49 #include "phyfege.h"
     50 #include "phy543xx.h"
     51 #include <soc/macsecphy.h>
     52 
     53 #define DISABLE_CLK125          0       /* Disable if unused to reduce */
     54                                         /*  EMI emissions */
     55 
     56 
     57 static bmacsec_error_t error_tbl[] = {
     58                                 SOC_E_NONE,
     59                                 SOC_E_INTERNAL,
     60                                 SOC_E_MEMORY,
     61                                 SOC_E_PARAM,
     62                                 SOC_E_EMPTY,
     63                                 SOC_E_FULL,
     64                                 SOC_E_NOT_FOUND,
     65                                 SOC_E_EXISTS,
     66                                 SOC_E_TIMEOUT,
     67                                 SOC_E_FAIL,
     68                                 SOC_E_DISABLED,
     69                                 SOC_E_BADID,
     70                                 SOC_E_RESOURCE,
     71                                 SOC_E_CONFIG,
     72                                 SOC_E_UNAVAIL,
     73                                 SOC_E_INIT,
     74                                 SOC_E_PORT,
     75                             };
     76 /*
     77  * Convert BMACSEC return codes to SOC return code.
     78  */
     79 #define SOC_ERROR(e)    error_tbl[(-e)]
     80 
     81 
     82 #define MACSEC_READ_PHY_REG(_unit, _pc, _mdio, _reg, _value)     \
     83             ((_pc->read)((_unit), (_mdio), (_reg), (_value)))
     84 #define MACSEC_WRITE_PHY_REG(_unit, _pc, _mdio, _reg, _value)     \
     85             ((_pc->write)((_unit), (_mdio), (_reg), (_value)))
     86 
     87 /*Copper*/
     88 #define ADVERT_ALL_COPPER_FLOW_CTRL   (_SHR_PA_PAUSE_TX | _SHR_PA_PAUSE_RX)
     89 #define ADVERT_ALL_COPPER_HD_SPEED    (_SHR_PA_SPEED_10MB |  _SHR_PA_SPEED_100MB | _SHR_PA_SPEED_1000MB) 
     90 #define ADVERT_ALL_COPPER_FD_SPEED    (_SHR_PA_SPEED_10MB |  _SHR_PA_SPEED_100MB | _SHR_PA_SPEED_1000MB)
     91 
     92 /*Fiber*/
     93 #define ADVERT_ALL_FIBER_FLOW_CTRL    (_SHR_PA_PAUSE_TX | _SHR_PA_PAUSE_RX)
     94 #define ADVERT_ALL_FIBER_FD_SPEED     (_SHR_PA_SPEED_100MB | _SHR_PA_SPEED_1000MB)
     95 
     96 
     97 #define SET_FLOW_CTRL_ABILITY(ability, p) ((ability)->pause |= p)
     98 #define SET_HD_SPEED_ABILITY(ability, s)  ((ability)->speed_half_duplex |= s)
     99 #define SET_FD_SPEED_ABILITY(ability, s)  ((ability)->speed_full_duplex |= s)
    100 
    101 #define ADVERT_ALL_COPPER(ability) {\
    102         SET_FLOW_CTRL_ABILITY(ability, ADVERT_ALL_COPPER_FLOW_CTRL);\
    103         SET_HD_SPEED_ABILITY(ability, ADVERT_ALL_COPPER_HD_SPEED);\
    104         SET_FD_SPEED_ABILITY(ability, ADVERT_ALL_COPPER_FD_SPEED);\
    105         }
    106 
    107 #define ADVERT_ALL_FIBER(ability) {\
    108         SET_FLOW_CTRL_ABILITY(ability, ADVERT_ALL_FIBER_FLOW_CTRL);\
    109         SET_FD_SPEED_ABILITY(ability, ADVERT_ALL_FIBER_FD_SPEED);\
    110         }
    111 
    112 #define PHY_IS_BCM54380(_pc) (PHY_MODEL_CHECK((_pc), \
    113                                   PHY_BCM54380_OUI, \
    114                                   PHY_BCM54380_MODEL))
    115   
    116 #define PHY_IS_BCM54382(_pc) (PHY_MODEL_CHECK((_pc), \
    117                                   PHY_BCM54382_OUI, \
    118                                   PHY_BCM54382_MODEL) \
    119                                   && (((_pc)->phy_rev & 0x8)))
    120   
    121 #define PHY_IS_BCM54340(_pc) (PHY_MODEL_CHECK((_pc), \
    122                                   PHY_BCM54340_OUI, \
    123                                   PHY_BCM54340_MODEL)) 
    124   
    125 #define PHY_IS_BCM54385(_pc) (PHY_MODEL_CHECK((_pc), \
    126                                   PHY_BCM54385_OUI, \
    127                                   PHY_BCM54385_MODEL) \
    128                                   && (!((_pc)->phy_rev & 0x8)))
    129   
    130 #define PHY_IS_BCM54385_B0(_pc) ((PHY_MODEL_CHECK((_pc), \
    131                                   PHY_BCM54385_OUI, \
    132                                   PHY_BCM54385_MODEL))\
    133                                   && ((_pc)->phy_rev  == 0x1))
    134 
    135 #define PHY_BCM54385_B0_REV (0x1)
    136 #define PHY_BCM54385_C0_REV (0x2)
    137 
    138 /* 
    139    Flag(s) to specify config options to mac 
    140    It should eventually be moved to mac_ctrl.h.
    141  */
    142 #define MAC_CTRL_FLAG_MACSEC_FIX_LATENCY_EN (1<<0)
    143 
    144 
    145 STATIC int _phy_54380_medium_change(int unit, soc_port_t port, 
    146                           int force_update, soc_port_medium_t force_medium);
    147 STATIC int phy_54380_duplex_set(int unit, soc_port_t port, int duplex);
    148 STATIC int phy_54380_speed_set(int unit, soc_port_t port, int speed);
    149 STATIC int phy_54380_master_set(int unit, soc_port_t port, int master);
    150 
    151 #if 0
    152 
    153 STATIC int phy_54380_adv_local_set(int unit, soc_port_t port,i
    154                                   /*soc_port_mode_t mode*/soc_port_ability_t ability);
    155 
    156 #endif
    157 
    158 STATIC int phy_54380_autoneg_get(int unit, soc_port_t port,
    159                      int *autoneg, int *autoneg_done);
    160 STATIC int phy_54380_autoneg_set(int unit, soc_port_t port, int autoneg);
    161 STATIC int phy_54380_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode);
    162 STATIC int phy_54380_speed_get(int unit, soc_port_t port, int *speed);
    163 STATIC int phy_54380_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability);
    164 extern int
    165 phy_ecd_cable_diag_init_40nm(int unit, soc_port_t port);
    166 extern int
    167 phy_ecd_cable_diag_40nm(int unit, soc_port_t port,
    168             soc_port_cable_diag_t *status, uint16 ecd_ctrl);
    169 
    170 extern int
    171 bmacsec_phy54380_macsec_enable(int phy_id, bmacsec_dev_addr_t bmacsec_addr, int macsec_enable);
    172 
    173 /***********************************************************************
    174  *
    175  * HELPER FUNCTIONS
    176  */
    177 /*
    178  * Function:
    179  *      _phy_54380_medium_check
    180  * Purpose:
    181  *      Determine if chip should operate in copper or fiber mode.
    182  * Parameters:
    183  *      unit - StrataSwitch unit #.
    184  *      port - StrataSwitch port #.
    185  *      medium - (OUT) SOC_PORT_MEDIUM_XXX
    186  * Returns:
    187  *      SOC_E_XXX
    188  */
    189 STATIC int
    190 _phy_54380_medium_check(int unit, soc_port_t port, int *medium)
    191 {
    192 
    193     phy_ctrl_t    *pc = EXT_PHY_SW_STATE(unit, port);
    194     bmacsec_dev_addr_t phy_dev_addr;
    195     bmacsec_phy_port_medium_t bmacsec_port_medium;
    196 
    197     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0);
    198     
    199     *medium = SOC_PORT_MEDIUM_COPPER;
    200 
    201     if (pc->automedium) {
    202     
    203         bmacsec_phy54380_medium_get(phy_dev_addr, 
    204                                    pc->fiber.preferred, 
    205                                    &bmacsec_port_medium); 
    206 
    207         if (bmacsec_port_medium == BMACSEC_PHY_MEDIUM_COPPER) {
    208             *medium = SOC_PORT_MEDIUM_COPPER;
    209         } else {
    210             *medium = SOC_PORT_MEDIUM_FIBER;
    211         }
    212     } else {
    213        *medium = pc->fiber.preferred ? SOC_PORT_MEDIUM_FIBER:
    214                   SOC_PORT_MEDIUM_COPPER; 
    215     }
    216 
    217     LOG_VERBOSE(BSL_LS_SOC_PHY,
    218                 (BSL_META_U(unit,
    219                             "_phy_54380_medium_check: "
    220                             "u=%d p=%d fiber_pref=%d fiber=%d\n"),
    221                  unit, port, pc->fiber.preferred,
    222                  (*medium == SOC_PORT_MEDIUM_FIBER) ? 1 : 0));
    223 
    224     return SOC_E_NONE;
    225 }
    226  
    227 
    228 /*
    229  * Function:
    230  *      phy_54380_medium_status
    231  * Purpose:
    232  *      Indicate the current active medium
    233  * Parameters:
    234  *      unit - StrataSwitch unit #.
    235  *      port - StrataSwitch port #.
    236  *      medium - (OUT) One of:
    237  *              SOC_PORT_MEDIUM_COPPER
    238  *              SOC_PORT_MEDIUM_FIBER
    239  * Returns:
    240  *      SOC_E_NONE
    241  */
    242 
    243 STATIC int
    244 phy_54380_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium)
    245 {
    246     if (PHY_COPPER_MODE(unit, port)) {
    247         *medium = SOC_PORT_MEDIUM_COPPER;
    248     } else {
    249         *medium = SOC_PORT_MEDIUM_FIBER;
    250     }
    251     return SOC_E_NONE;
    252 }
    253 
    254 
    255 /*
    256  * Function:
    257  *      _phy_54380_medium_config_update
    258  * Purpose:
    259  *      Update the PHY with config parameters
    260  * Parameters:
    261  *      unit - StrataSwitch unit #.
    262  *      port - StrataSwitch port #.
    263  *      cfg - Config structure.
    264  * Returns:
    265  *      SOC_E_XXX
    266  */
    267 
    268 STATIC int
    269 _phy_54380_medium_config_update(int unit, soc_port_t port,
    270                                 soc_phy_config_t *cfg)
    271 {
    272     SOC_IF_ERROR_RETURN
    273         (phy_54380_speed_set(unit, port, cfg->force_speed));
    274     SOC_IF_ERROR_RETURN
    275         (phy_54380_duplex_set(unit, port, cfg->force_duplex));
    276     SOC_IF_ERROR_RETURN
    277         (phy_54380_master_set(unit, port, cfg->master));
    278     SOC_IF_ERROR_RETURN
    279         (phy_54380_ability_advert_set(unit, port, &cfg->advert_ability));
    280     SOC_IF_ERROR_RETURN
    281         (phy_54380_autoneg_set(unit, port, cfg->autoneg_enable));
    282     SOC_IF_ERROR_RETURN
    283         (phy_54380_mdix_set(unit, port, cfg->mdix));
    284 
    285     return SOC_E_NONE;
    286 }
    287 
    288 
    289 /*
    290  * Function:
    291  *     phy_54380_pa_2_bmacsec_pa 
    292  * Purpose:
    293  *     Translate soc_port_ability to 
    294  *     bmacsec_port_ability
    295  * Parameters:
    296  *      soc_port_ability_t
    297  *      bmacsec_port_ability_t
    298  * Returns:
    299  */
    300 static void 
    301 phy_54380_pa_2_bmacsec_pa( soc_port_ability_t *ability, 
    302                     bmacsec_port_ability_t *bmacsec_ability)
    303 {
    304     if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) {
    305         bmacsec_ability->speed_full_duplex |= BMACSEC_PA_SPEED_1000MB;
    306     }
    307     if(ability->speed_full_duplex & SOC_PA_SPEED_100MB) {
    308         bmacsec_ability->speed_full_duplex |= BMACSEC_PA_SPEED_100MB;
    309     }
    310     if(ability->speed_full_duplex & SOC_PA_SPEED_10MB) {
    311         bmacsec_ability->speed_full_duplex |= BMACSEC_PA_SPEED_10MB;
    312     }
    313     if(ability->speed_half_duplex & SOC_PA_SPEED_1000MB) {
    314         bmacsec_ability->speed_half_duplex |= BMACSEC_PA_SPEED_1000MB;
    315     }
    316     if(ability->speed_half_duplex & SOC_PA_SPEED_100MB) {
    317         bmacsec_ability->speed_half_duplex |= BMACSEC_PA_SPEED_100MB;
    318     }
    319     if(ability->speed_half_duplex & SOC_PA_SPEED_10MB) {
    320         bmacsec_ability->speed_half_duplex |= BMACSEC_PA_SPEED_10MB;
    321     }
    322     if(ability->pause & SOC_PA_PAUSE_TX) {
    323         bmacsec_ability->pause |= BMACSEC_PA_PAUSE_TX;
    324     }
    325     if(ability->pause & SOC_PA_PAUSE_RX) {
    326         bmacsec_ability->pause |= BMACSEC_PA_PAUSE_RX;
    327     }
    328     if(ability->pause & SOC_PA_PAUSE_ASYMM) {
    329         bmacsec_ability->pause |= BMACSEC_PA_PAUSE_ASYMM;
    330     }
    331     if(ability->loopback & SOC_PA_LB_NONE) {
    332         bmacsec_ability->loopback |= BMACSEC_PA_LB_NONE;
    333     }
    334     if(ability->loopback & SOC_PA_LB_PHY) {
    335         bmacsec_ability->loopback |= BMACSEC_PA_LB_PHY;
    336     }
    337     if(ability->flags & SOC_PA_AUTONEG) {
    338         bmacsec_ability->flags |= BMACSEC_PA_AUTONEG;
    339     }
    340     if(ability->eee & SOC_PA_EEE_1GB_BASET) {
    341         bmacsec_ability->eee |= BMACSEC_PA_EEE_1GB_BASET;
    342     }
    343     if(ability->eee & SOC_PA_EEE_100MB_BASETX) {
    344         bmacsec_ability->eee |= BMACSEC_PA_EEE_100MB_BASETX;
    345     }
    346     return;
    347 }
    348 
    349 
    350 /*
    351  * Function:
    352  *     phy_54380_bmacsec_pa_2_pa 
    353  * Purpose:
    354  *     Translate bmacsecc_port_ability to 
    355  *     soc_port_ability
    356  * Parameters:
    357  *      bmacsec_port_ability_t
    358  *      soc_port_ability_t
    359  * Returns:
    360  */
    361 static void 
    362 phy_54380_bmacsec_pa_2_pa( bmacsec_port_ability_t *bmacsec_ability, 
    363                     soc_port_ability_t *ability)
    364 {
    365     if(bmacsec_ability->speed_full_duplex & BMACSEC_PA_SPEED_1000MB) {
    366         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
    367     }
    368     if(bmacsec_ability->speed_full_duplex & BMACSEC_PA_SPEED_100MB) {
    369         ability->speed_full_duplex |= SOC_PA_SPEED_100MB;
    370     }
    371     if(bmacsec_ability->speed_full_duplex & BMACSEC_PA_SPEED_10MB) {
    372         ability->speed_full_duplex |= SOC_PA_SPEED_10MB;
    373     }
    374     if(bmacsec_ability->speed_half_duplex & BMACSEC_PA_SPEED_1000MB) {
    375         ability->speed_half_duplex |= SOC_PA_SPEED_1000MB;
    376     }
    377     if(bmacsec_ability->speed_half_duplex & BMACSEC_PA_SPEED_100MB) {
    378         ability->speed_half_duplex |= SOC_PA_SPEED_100MB;
    379     }
    380     if(bmacsec_ability->speed_half_duplex & BMACSEC_PA_SPEED_10MB) {
    381         ability->speed_half_duplex |= SOC_PA_SPEED_10MB;
    382     }
    383     if(bmacsec_ability->pause & BMACSEC_PA_PAUSE_TX) {
    384         ability->pause |= SOC_PA_PAUSE_TX;
    385     }
    386     if(bmacsec_ability->pause & BMACSEC_PA_PAUSE_RX) {
    387         ability->pause |= SOC_PA_PAUSE_RX;
    388     }
    389     if(bmacsec_ability->pause & BMACSEC_PA_PAUSE_ASYMM) {
    390         ability->pause |= SOC_PA_PAUSE_ASYMM;
    391     }
    392     if(bmacsec_ability->loopback & BMACSEC_PA_LB_NONE) {
    393         ability->loopback |= SOC_PA_LB_NONE;
    394     }
    395     if(bmacsec_ability->loopback & BMACSEC_PA_LB_PHY) {
    396         ability->loopback |= SOC_PA_LB_PHY;
    397     }
    398     if(bmacsec_ability->flags & BMACSEC_PA_AUTONEG) {
    399         ability->flags |= SOC_PA_AUTONEG;
    400     }
    401      if(bmacsec_ability->eee & BMACSEC_PA_EEE_1GB_BASET) {
    402         ability->eee |= SOC_PA_EEE_1GB_BASET;
    403     }
    404     if(bmacsec_ability->eee & BMACSEC_PA_EEE_100MB_BASETX) {
    405         ability->eee |= SOC_PA_EEE_100MB_BASETX;
    406     }
    407     return;
    408 }
    409 
    410 /***********************************************************************
    411  *
    412  * PHY54380 DRIVER ROUTINES
    413  */
    414 
    415 
    416 
    417 
    418 
    419 /*
    420  * Function:
    421  *      phy_54380_medium_config_set
    422  * Purpose:
    423  *      Set the operating parameters that are automatically selected
    424  *      when medium switches type.
    425  * Parameters:
    426  *      unit - StrataSwitch unit #
    427  *      port - Port number
    428  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
    429  *      cfg - Operating parameters
    430  * Returns:
    431  *      SOC_E_XXX
    432  */
    433 STATIC int
    434 phy_54380_medium_config_set(int unit, soc_port_t port, 
    435                            soc_port_medium_t  medium,
    436                            soc_phy_config_t  *cfg)
    437 {
    438     phy_ctrl_t    *pc;
    439     soc_phy_config_t *active_medium;  /* Currently active medium */
    440     soc_phy_config_t *change_medium;  /* Requested medium */
    441     soc_phy_config_t *other_medium;   /* The other medium */
    442     int               medium_update;
    443     soc_port_ability_t advert_ability;
    444     sal_memset(&advert_ability, 0, sizeof(soc_port_ability_t));
    445 
    446     if (NULL == cfg) {
    447         return SOC_E_PARAM;
    448     }
    449 
    450     pc            = EXT_PHY_SW_STATE(unit, port);
    451     medium_update = FALSE;
    452 
    453    switch (medium) {
    454     case SOC_PORT_MEDIUM_COPPER:
    455         if (!pc->automedium && !PHY_COPPER_MODE(unit, port)) {
    456                 return SOC_E_UNAVAIL;
    457         }
    458         change_medium  = &pc->copper;
    459         other_medium   = &pc->fiber;
    460         ADVERT_ALL_COPPER(&advert_ability);
    461         break;
    462     case SOC_PORT_MEDIUM_FIBER:
    463         if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) {
    464             return SOC_E_UNAVAIL;
    465         }
    466         change_medium  = &pc->fiber;
    467         other_medium   = &pc->copper;
    468         ADVERT_ALL_FIBER(&advert_ability);
    469         break;
    470     default:
    471         return SOC_E_PARAM;
    472     }
    473 
    474     /*
    475      * Changes take effect immediately if the target medium is active or
    476      * the preferred medium changes.
    477      */
    478     if (change_medium->enable != cfg->enable) {
    479         medium_update = TRUE;
    480     }
    481     if (change_medium->preferred != cfg->preferred) {
    482         /* Make sure that only one medium is preferred */
    483         other_medium->preferred = !cfg->preferred;
    484         medium_update = TRUE;
    485     }
    486 
    487     sal_memcpy(change_medium, cfg, sizeof(*change_medium));
    488     change_medium->advert_ability.pause &= advert_ability.pause;
    489     change_medium->advert_ability.speed_half_duplex &= advert_ability.speed_half_duplex;
    490     change_medium->advert_ability.speed_full_duplex &= advert_ability.speed_full_duplex;
    491     change_medium->advert_ability.interface &= advert_ability.interface;
    492     change_medium->advert_ability.medium &= advert_ability.medium;
    493     change_medium->advert_ability.loopback &= advert_ability.loopback;
    494     change_medium->advert_ability.flags &= advert_ability.flags;
    495 
    496     if (medium_update) {
    497         /* The new configuration may cause medium change. Check
    498          * and update medium.
    499          */
    500         SOC_IF_ERROR_RETURN
    501             (_phy_54380_medium_change(unit, port, TRUE, medium));
    502     } else {
    503         active_medium = (PHY_COPPER_MODE(unit, port)) ?  
    504                             &pc->copper : &pc->fiber;
    505         if (active_medium == change_medium) {
    506             /* If the medium to update is active, update the configuration */
    507             SOC_IF_ERROR_RETURN
    508                 (_phy_54380_medium_config_update(unit, port, change_medium));
    509         }
    510     }
    511     return SOC_E_NONE;
    512 }
    513 
    514 
    515 /*
    516  * Function:
    517  *      phy_54380_medium_config_get
    518  * Purpose:
    519  *      Get the operating parameters that are automatically selected
    520  *      when medium switches type.
    521  * Parameters:
    522  *      unit - StrataSwitch unit #
    523  *      port - Port number
    524  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
    525  *      cfg - (OUT) Operating parameters
    526  * Returns:
    527  *      SOC_E_XXX
    528  */
    529 
    530 STATIC int
    531 phy_54380_medium_config_get(int unit, soc_port_t port, 
    532                            soc_port_medium_t medium,
    533                            soc_phy_config_t *cfg)
    534 {
    535     int            rv;
    536     phy_ctrl_t    *pc;
    537 
    538     pc = EXT_PHY_SW_STATE(unit, port);
    539     rv = SOC_E_NONE;
    540 
    541     switch (medium) {
    542     case SOC_PORT_MEDIUM_COPPER:
    543         if (pc->automedium || PHY_COPPER_MODE(unit, port)) {
    544             sal_memcpy(cfg, &pc->copper, sizeof (*cfg));
    545         } else {
    546             rv = SOC_E_UNAVAIL;
    547         }
    548         break;
    549     case SOC_PORT_MEDIUM_FIBER:
    550         if (pc->automedium || PHY_FIBER_MODE(unit, port)) {
    551             sal_memcpy(cfg, &pc->fiber, sizeof (*cfg));
    552         } else {
    553             rv = SOC_E_UNAVAIL;
    554         }
    555         break;
    556     default:
    557         rv = SOC_E_PARAM;
    558         break;
    559     }
    560 
    561     return rv;
    562 }
    563 
    564 /*
    565  * Function:
    566  *      _phy_54380_no_reset_setup
    567  * Purpose:
    568  *      Setup the operating parameters of the PHY without resetting PHY
    569  * Parameters:
    570  *      unit - StrataSwitch unit #
    571  *      port - Port number
    572  * Returns:
    573  *      SOC_E_XXX
    574  */
    575 
    576 STATIC int
    577 _phy_54380_no_reset_setup(int unit, soc_port_t port)
    578 {
    579     phy_ctrl_t    *pc;
    580     bmacsec_dev_addr_t phy_dev_addr;
    581     int rv = SOC_E_NONE;
    582 
    583     LOG_INFO(BSL_LS_SOC_PHY,
    584              (BSL_META_U(unit,
    585                          "_phy_54380_no_reset_setup: u=%d p=%d medium=%s\n"),
    586                          unit, port,
    587               PHY_COPPER_MODE(unit, port) ? "COPPER" : "FIBER"));
    588 
    589     pc      = EXT_PHY_SW_STATE(unit, port);
    590 
    591     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
    592     rv = bmacsec_phy54380_init(phy_dev_addr, pc->macsec_dev_addr, 
    593                                0,
    594                                pc->automedium,
    595                                pc->fiber.preferred,
    596                                pc->fiber_detect,
    597                                pc->macsec_enable,
    598                                pc->fiber.enable,
    599                                pc->copper.enable);  
    600 
    601     if (rv != BMACSEC_E_NONE) {
    602         return SOC_E_FAIL;
    603     }
    604     return SOC_E_NONE;
    605 }
    606 
    607 /*
    608  * Function:
    609  *      phy_54380_init
    610  * Purpose:
    611  *      Init function for 54380 PHY.
    612  * Parameters:
    613  *      unit - StrataSwitch unit #.
    614  *      port - StrataSwitch port #.
    615  * Returns:
    616  *      SOC_E_NONE
    617  */
    618 
    619 STATIC int
    620 phy_54380_init(int unit, soc_port_t port)
    621 {
    622     phy_ctrl_t *pc;
    623     int        fiber_capable = 0, rv;
    624     int        fiber_preferred;
    625     int        qsgmii_mdio;
    626     bmacsec_dev_addr_t macsec_dev_addr, qsgmii_dev_addr, phy_dev_addr, phy_base_addr;
    627     int         mmi_mdio_addr, port_index, macsec_enable, macsec_fixed_latency_en;
    628     uint32      mac_config_flag = 0, primary_offset;
    629 
    630     LOG_INFO(BSL_LS_SOC_PHY,
    631              (BSL_META_U(unit,
    632                          "phy_54xxx_init: u=%d p=%d\n"),
    633                          unit, port));
    634 
    635     /* Only SGMII interface to switch MAC is supported */ 
    636     if (IS_GMII_PORT(unit, port)) {
    637         return SOC_E_CONFIG; 
    638     }
    639 
    640     pc = EXT_PHY_SW_STATE(unit, port);
    641     pc->interface = SOC_PORT_IF_SGMII;
    642 
    643     mmi_mdio_addr = soc_property_port_get(unit, port, spn_MACSEC_DEV_ADDR, -1);
    644 
    645     if (mmi_mdio_addr == -1) {
    646         LOG_WARN(BSL_LS_SOC_PHY,
    647                  (BSL_META_U(unit,
    648                              "phy_54380_init: "
    649                              "MACSEC_DEV_ADDR property "
    650                              "not configured for u=%d p=%d\n"), unit, port));
    651         return SOC_E_CONFIG;
    652     }
    653     
    654     port_index = soc_property_port_get(unit, port, spn_MACSEC_PORT_INDEX, -1);
    655 
    656     if (port_index == -1) {
    657         LOG_WARN(BSL_LS_SOC_PHY,
    658                  (BSL_META_U(unit,
    659                              "phy_54380_init: "
    660                              "MACSEC_PORT_INDEX property not configured for "
    661                              "u=%d p=%d\n"), unit, port));
    662         return SOC_E_CONFIG;
    663     }
    664 
    665     /* EEE capable */ 
    666     if ( PHY_IS_BCM54380(pc) || PHY_IS_BCM54382(pc) ||
    667          PHY_IS_BCM54340(pc) || PHY_IS_BCM54385(pc) ) {
    668         PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_CAPABLE);
    669     }
    670 
    671     pc->macsec_dev_addr = mmi_mdio_addr;
    672     pc->macsec_dev_port = port_index;
    673     qsgmii_mdio = (pc->phy_id - pc->macsec_dev_port + 8);
    674 
    675     phy_dev_addr    = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
    676     macsec_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->macsec_dev_addr, 0);
    677     qsgmii_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, qsgmii_mdio, 0); 
    678     phy_base_addr   = SOC_MACSECPHY_MDIO_ADDR(unit, ((pc->phy_id) - port_index), 0); 
    679 
    680     macsec_enable = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0);
    681     pc->macsec_enable = macsec_enable;
    682     macsec_fixed_latency_en = soc_property_port_get(unit, port, spn_MACSEC_FIXED_LATENCY_ENABLE, -1);
    683 
    684     if(1 == macsec_fixed_latency_en) {
    685         mac_config_flag |= MAC_CTRL_FLAG_MACSEC_FIX_LATENCY_EN; 
    686     }
    687     rv = bmacsec_phy54380_phy_mac_addr_set(phy_dev_addr, macsec_dev_addr, 
    688                                    qsgmii_dev_addr, phy_base_addr,
    689                                    pc->macsec_dev_port, bmacsec_io_mmi1_quad,
    690                                    mac_config_flag); 
    691     if(rv != BMACSEC_E_NONE) {
    692         LOG_WARN(BSL_LS_SOC_PHY,
    693                  (BSL_META_U(unit,
    694                              "phy_54380_init: bmacsec_phy_mac_addr_set "
    695                              "returned error for u=%d p=%d\n"), unit, port));
    696         return SOC_E_FAIL;
    697     }
    698 
    699     /* fiber_capable? */
    700     if(PHY_IS_BCM54340(pc) || PHY_IS_BCM54385(pc)) {
    701         fiber_capable = 1;
    702     }
    703 
    704     /* Change it to copper prefer for default. */
    705     fiber_preferred =
    706         soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 0);
    707     pc->automedium =
    708         soc_property_port_get(unit, port, spn_PHY_AUTOMEDIUM, 0);
    709     pc->fiber_detect =
    710         soc_property_port_get(unit, port, spn_PHY_FIBER_DETECT, -4);
    711 
    712     LOG_INFO(BSL_LS_SOC_PHY,
    713              (BSL_META_U(unit,
    714                          "phy_54380_init: "
    715                          "u=%d p=%d type=54380%s automedium=%d fiber_pref=%d detect=%d\n"),
    716               unit, port, fiber_capable ? "S" : "",
    717               pc->automedium, fiber_preferred, pc->fiber_detect));
    718 
    719     if (fiber_capable == 0) { /* not fiber capable */
    720         fiber_preferred  = 0;
    721         pc->automedium   = 0;
    722         pc->fiber_detect = 0;
    723     }
    724 
    725     pc->copper.enable = TRUE;
    726     pc->copper.preferred = !fiber_preferred;
    727     pc->copper.autoneg_enable = TRUE;
    728     ADVERT_ALL_COPPER(&pc->copper.advert_ability);
    729     pc->copper.force_speed = 1000;
    730     pc->copper.force_duplex = TRUE;
    731     pc->copper.master = SOC_PORT_MS_AUTO;
    732     pc->copper.mdix = SOC_PORT_MDIX_AUTO;
    733 
    734     pc->fiber.enable = fiber_capable;
    735     pc->fiber.preferred = fiber_preferred;
    736     pc->fiber.autoneg_enable = fiber_capable;
    737     ADVERT_ALL_FIBER(&pc->fiber.advert_ability);
    738     pc->fiber.force_speed = 1000;
    739     pc->fiber.force_duplex = TRUE;
    740     pc->fiber.master = SOC_PORT_MS_NONE;
    741     pc->fiber.mdix = SOC_PORT_MDIX_NORMAL;
    742 
    743     /* Initially configure for the preferred medium. */
    744     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
    745     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
    746     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU);
    747     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
    748     if (pc->fiber.preferred) {
    749         PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
    750     } else {
    751         PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
    752     }
    753 
    754     /* Get Requested LED selectors (defaults are hardware defaults) */
    755     pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0);
    756     pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1);
    757     pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3);
    758     pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6);
    759     pc->ledctrl    = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8);
    760     pc->ledselect  = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0);
    761 
    762     /* default MACSEC MAC policy: MACSEC_SWITCH_FOLLOWS_LINE == 1 */
    763     pc->macsec_mac_policy = soc_property_port_get(unit, port,
    764                                           spn_MACSEC_SWITCH_SIDE_POLICY,
    765                                           BMACSEC_BCM54380_SWITCH_FOLLOWS_LINE);
    766     /* set Fixed policy if macsec_mac_policy == BMACSEC_SWITCH_FIXED == 0 */
    767     pc->macsec_switch_fixed = (pc->macsec_mac_policy ==
    768                                BMACSEC_BCM54380_SWITCH_FIXED) ? 1 : 0;
    769     /*
    770      * Some reasonable defaults
    771      */
    772     pc->macsec_switch_fixed_speed  = 1000;
    773     pc->macsec_switch_fixed_duplex = 1;
    774     pc->macsec_switch_fixed_pause  = 1;
    775     pc->macsec_pause_rx_fwd = 0;
    776     pc->macsec_pause_tx_fwd = 0;
    777     pc->macsec_line_ipg     = 0xc;
    778     pc->macsec_switch_ipg   = 0xc;
    779 
    780     /* Primary & Offset numbers from the config property */
    781     primary_offset = soc_property_port_get(unit, port, spn_PHY_PORT_PRIMARY_AND_OFFSET, 0x00);
    782     rv = soc_phyctrl_primary_set(unit, port, (primary_offset >>8) & 0xff);
    783     rv = soc_phyctrl_offset_set( unit, port,  primary_offset & 0xff);
    784 
    785     /* Init PHYS and MACs to defaults */
    786     rv = bmacsec_phy54380_init( phy_dev_addr, 
    787                                 macsec_dev_addr, 
    788                                 1,
    789                                 pc->automedium,
    790                                 fiber_preferred,
    791                                 pc->fiber_detect,
    792                                 pc->macsec_enable,
    793                                 pc->fiber.enable,
    794                                 pc->copper.enable); 
    795     
    796     if (rv != BMACSEC_E_NONE) {
    797         return SOC_E_FAIL;
    798     }
    799 
    800     /* Set LED Modes and Control */
    801     rv = bmacsec_phy54380_set_led_selectors(phy_dev_addr, pc->ledmode[0],
    802                                             pc->ledmode[1], pc->ledmode[2],
    803                                             pc->ledmode[3], pc->ledselect,
    804                                             pc->ledctrl);
    805     if (rv != BMACSEC_E_NONE) {
    806         return SOC_E_FAIL;
    807     }
    808 
    809     SOC_IF_ERROR_RETURN
    810         (_phy_54380_medium_config_update(unit, port,
    811                         PHY_COPPER_MODE(unit, port) ? &pc->copper
    812                                                     : &pc->fiber));
    813     if (pc->macsec_enable) {
    814         rv = soc_macsecphy_init(unit, port, pc,
    815                             BMACSEC_CORE_BCM5438X, bmacsec_io_mmi1_quad);
    816         if (!SOC_SUCCESS(rv)) {
    817             LOG_ERROR(BSL_LS_SOC_PHY,
    818                   (BSL_META_U(unit,
    819                               "soc_macsecphy_init: MACSEC init for"
    820                               " u=%d p=%d FAILED "), unit, port));
    821         } else {
    822             LOG_INFO(BSL_LS_SOC_PHY,
    823                  (BSL_META_U(unit,
    824                              "soc_macsecphy_init: MACSEC init for"
    825                              " u=%d p=%d SUCCESS "), unit, port));
    826         }
    827     }
    828     return SOC_E_NONE;
    829 }
    830 
    831 
    832 /*
    833  * Function:    
    834  *  phy_54380_reset
    835  * Purpose: 
    836  *  Reset PHY and wait for it to come out of reset.
    837  * Parameters:
    838  *  unit - StrataSwitch unit #.
    839  *  port - StrataSwitch port #. 
    840  * Returns: 
    841  *  SOC_E_XXX
    842      */
    843 
    844 STATIC int
    845 phy_54380_reset(int unit, soc_port_t port, void *user_arg)
    846 {
    847 
    848     int rv;
    849     phy_ctrl_t    *pc;
    850     bmacsec_dev_addr_t phy_dev_addr;
    851 
    852     pc = EXT_PHY_SW_STATE(unit, port);
    853 
    854     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
    855     rv = bmacsec_phy54380_reset(phy_dev_addr);
    856 
    857     return (SOC_ERROR(rv));
    858 }
    859 
    860 #define  MACSEC_REG_PORT_SHIFT      12
    861 #define  MACSEC_REG_PORT_MASK       (0xFU << MACSEC_REG_PORT_SHIFT)
    862 #define  UINT16_MASK                0xFFFF
    863 
    864 /*
    865  * Function:
    866  *      phy_54380_reg_read
    867  * Purpose:
    868  *      read a register.
    869  * Parameters:
    870  *      unit - StrataSwitch unit #.
    871  *      port - StrataSwitch port #.
    872  *      flags - register type.
    873  *      phy_reg_addr - register address.
    874  *      phy_data - data read from the register.
    875  * Returns:
    876  *      SOC_E_XXX
    877  */
    878 STATIC int
    879 phy_54380_reg_read(int unit, soc_port_t port, uint32 flags,
    880                    uint32 phy_reg_addr, uint32 *phy_data)
    881 {
    882     int  rv;
    883 
    884     if ( BMACSEC_PHY_REG_MACSEC & flags ) {    /* MACSEC registers */
    885         soc_port_t  offset;
    886         SOC_IF_ERROR_RETURN( soc_phyctrl_offset_get(unit, port, &offset) );
    887 
    888         phy_reg_addr &= ~(MACSEC_REG_PORT_MASK);
    889         phy_reg_addr |= (offset << MACSEC_REG_PORT_SHIFT);
    890         rv = bmacsec_phy54380_macsec_reg_read(port, flags, phy_reg_addr, phy_data);
    891 
    892     } else
    893     if ( BMACSEC_PHY_REG_DIRECT & flags ) {    /* RDB registers */
    894         uint16       data16 = 0;
    895         phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
    896 
    897         rv = bmacsec_phy54380_direct_reg_read(pc->phy_id,
    898                                 (uint16) (phy_reg_addr & UINT16_MASK), &data16);
    899         *phy_data = (uint32) data16;
    900 
    901     } else {    /* other registers */
    902         rv = phy_ge_reg_read(unit, port, flags, phy_reg_addr, phy_data);
    903     }
    904 
    905     return SOC_ERROR(rv);
    906 }
    907 
    908 /*
    909  * Function:
    910  *      phy_54380_reg_write
    911  * Purpose:
    912  *      write a register.
    913  * Parameters:
    914  *      unit - StrataSwitch unit #.
    915  *      port - StrataSwitch port #.
    916  *      flags - register type.
    917  *      phy_reg_addr - register address.
    918  *      phy_data - data to be written.
    919  * Returns:
    920  *      SOC_E_XXX
    921  */
    922 STATIC int
    923 phy_54380_reg_write(int unit, soc_port_t port, uint32 flags,
    924                     uint32 phy_reg_addr, uint32 phy_data)
    925 {
    926     int  rv;
    927 
    928     if ( BMACSEC_PHY_REG_MACSEC & flags ) {    /* MACSEC registers */
    929         soc_port_t  offset;
    930         SOC_IF_ERROR_RETURN( soc_phyctrl_offset_get(unit, port, &offset) );
    931 
    932         phy_reg_addr &= ~(MACSEC_REG_PORT_MASK);
    933         phy_reg_addr |= (offset << MACSEC_REG_PORT_SHIFT);
    934         rv = bmacsec_phy54380_macsec_reg_write(port, flags, phy_reg_addr, phy_data);
    935 
    936     } else
    937     if ( BMACSEC_PHY_REG_DIRECT & flags ) {    /* RDB registers */
    938         phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
    939         rv = bmacsec_phy54380_direct_reg_write(pc->phy_id,
    940                                       (uint16) (phy_reg_addr & UINT16_MASK),
    941                                       (uint16) (phy_data     & UINT16_MASK) );
    942 
    943     } else {    /* other registers */
    944         rv = phy_ge_reg_write(unit, port, flags, phy_reg_addr, phy_data);
    945     }
    946 
    947     return SOC_ERROR(rv);
    948 }
    949 
    950 /*
    951  * Function:
    952  *      phy_54380_reg_modify
    953  * Purpose:
    954  *      modify a register.
    955  * Parameters:
    956  *      unit - StrataSwitch unit #.
    957  *      port - StrataSwitch port #.
    958  *      flags - register type.
    959  *      phy_reg_addr - register address.
    960  *      phy_data - data to be modified.
    961  *      mask - register fields mask.
    962  * Returns:
    963  *      SOC_E_XXX
    964  */
    965 STATIC int
    966 phy_54380_reg_modify(int unit, soc_port_t port, uint32 flags,
    967                      uint32 phy_reg_addr, uint32 phy_data, uint32 mask)
    968 {
    969     int  rv;
    970 
    971     if ( BMACSEC_PHY_REG_MACSEC & flags ) {    /* MACSEC registers */
    972         soc_port_t  offset;
    973         SOC_IF_ERROR_RETURN( soc_phyctrl_offset_get(unit, port, &offset) );
    974 
    975         phy_reg_addr &= ~(MACSEC_REG_PORT_MASK);
    976         phy_reg_addr |= (offset << MACSEC_REG_PORT_SHIFT);
    977         rv = bmacsec_phy54380_macsec_reg_modify(port, flags, phy_reg_addr, phy_data, mask);
    978 
    979     } else
    980     if ( BMACSEC_PHY_REG_DIRECT & flags ) {    /* RDB registers */
    981         phy_ctrl_t  *pc = EXT_PHY_SW_STATE(unit, port);
    982         rv = bmacsec_phy54380_direct_reg_modify(pc->phy_id,
    983                                        (uint16) (phy_reg_addr & UINT16_MASK),
    984                                        (uint16) (phy_data     & UINT16_MASK),
    985                                        (uint16) mask );
    986 
    987     } else {    /* other registers */
    988         rv = phy_ge_reg_modify(unit, port, flags, phy_reg_addr, phy_data, mask);
    989     }
    990 
    991     return SOC_ERROR(rv);
    992 }
    993 
    994 /*
    995  * Function:
    996  *      phy_54380_enable_set
    997  * Purpose:
    998  *      Enable or disable the physical interface.
    999  * Parameters:
   1000  *      unit - StrataSwitch unit #.
   1001  *      port - StrataSwitch port #.
   1002  *      enable - Boolean, true = enable PHY, false = disable.
   1003  * Returns:
   1004  *      SOC_E_XXX
   1005  */
   1006 
   1007 STATIC int
   1008 phy_54380_enable_set(int unit, soc_port_t port, int enable)
   1009 {
   1010     phy_ctrl_t    *pc;
   1011     int rv = SOC_E_NONE;
   1012     bmacsec_dev_addr_t phy_dev_addr;
   1013     bmacsec_phy_port_mode_t port_mode = 0;
   1014 
   1015     pc     = EXT_PHY_SW_STATE(unit, port);
   1016 
   1017     if(PHY_COPPER_MODE(unit, port)) {
   1018         port_mode = BMACSEC_PHY_COPPER;
   1019     } else {
   1020         if(PHY_FIBER_MODE(unit, port)) {
   1021             port_mode = BMACSEC_PHY_FIBER;
   1022         }
   1023     }
   1024     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1025     rv = bmacsec_phy54380_enable_set(phy_dev_addr, pc->automedium,
   1026                                      port_mode, enable);
   1027     if(rv != BMACSEC_E_NONE) {
   1028         return SOC_E_FAIL;
   1029     }
   1030 
   1031     if (pc->automedium || PHY_FIBER_MODE(unit, port)) {
   1032         phy_ctrl_t  *int_pc;
   1033 
   1034         int_pc = INT_PHY_SW_STATE(unit, port);
   1035         if (NULL != int_pc) {
   1036             SOC_IF_ERROR_RETURN
   1037                 (PHY_ENABLE_SET(int_pc->pd, unit, port, enable));
   1038         }
   1039     
   1040         LOG_INFO(BSL_LS_SOC_PHY,
   1041                  (BSL_META_U(unit,
   1042                              "phy_54380_enable_set: "
   1043                              "Power %s fiber medium\n"), (enable) ? "up" : "down"));
   1044     }
   1045 
   1046     /* Update software state */
   1047     SOC_IF_ERROR_RETURN(phy_fe_ge_enable_set(unit, port, enable));
   1048     return SOC_E_NONE;
   1049 }
   1050 
   1051 /*
   1052  * Function:
   1053  *      phy_54380_enable_get
   1054  * Purpose:
   1055  *      Enable or disable the physical interface for a 54380 device.
   1056  * Parameters:
   1057  *      unit - StrataSwitch unit #.
   1058  *      port - StrataSwitch port #.
   1059  *      enable - (OUT) Boolean, true = enable PHY, false = disable.
   1060  * Returns:
   1061  *      SOC_E_XXX
   1062  */
   1063 
   1064 STATIC int
   1065 phy_54380_enable_get(int unit, soc_port_t port, int *enable)
   1066 {
   1067     return phy_fe_ge_enable_get(unit, port, enable);
   1068 }
   1069 
   1070 
   1071 /*
   1072  * Function:
   1073  *      _phy_54380_medium_change
   1074  * Purpose:
   1075  *      Change medium when media change detected or forced
   1076  * Parameters:
   1077  *      unit         - StrataSwitch unit #.
   1078  *      port         - StrataSwitch port #.
   1079  *      force_update - Force update
   1080  *      force_medium - Force update medium
   1081  * Returns:
   1082  *      SOC_E_XXX
   1083  */
   1084 STATIC int
   1085 _phy_54380_medium_change(int unit, soc_port_t port, int force_update,
   1086                          soc_port_medium_t force_medium)
   1087 {
   1088     phy_ctrl_t    *pc;
   1089     int            medium;
   1090 
   1091     pc = EXT_PHY_SW_STATE(unit, port);
   1092 
   1093     SOC_IF_ERROR_RETURN
   1094         (_phy_54380_medium_check(unit, port, &medium));
   1095 
   1096     if (medium == SOC_PORT_MEDIUM_COPPER) {
   1097         if (!PHY_COPPER_MODE(unit, port) || force_update) { /* Was fiber */ 
   1098             PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
   1099             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
   1100             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
   1101             PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE);
   1102             if ( PHY_IS_BCM54380(pc) || PHY_IS_BCM54382(pc) ||
   1103                  PHY_IS_BCM54340(pc) || PHY_IS_BCM54385(pc) ) {
   1104                 PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_CAPABLE);
   1105             }
   1106             SOC_IF_ERROR_RETURN
   1107                 (_phy_54380_no_reset_setup(unit, port));
   1108 
   1109             /* Do Not power up the interface if medium is disabled */
   1110             if (pc->copper.enable) {
   1111                 SOC_IF_ERROR_RETURN
   1112                     (_phy_54380_medium_config_update(unit, port, &pc->copper));
   1113             }
   1114             LOG_INFO(BSL_LS_SOC_PHY,
   1115                      (BSL_META_U(unit,
   1116                                  "_phy_54380_link_auto_detect: u=%d p=%d [F->C]\n"),
   1117                       unit, port));
   1118         }
   1119     } else {        /* Fiber */
   1120         if (PHY_COPPER_MODE(unit, port) || force_update) { /* Was copper */
   1121             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
   1122             PHY_FLAGS_CLR(unit, port, PHY_FLAGS_EEE_CAPABLE); /* no EEE for fiber */
   1123             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
   1124             PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE);
   1125 
   1126             SOC_IF_ERROR_RETURN
   1127                 (_phy_54380_no_reset_setup(unit, port));
   1128 
   1129             if (pc->fiber.enable) {
   1130                 SOC_IF_ERROR_RETURN
   1131                     (_phy_54380_medium_config_update(unit, port, &pc->fiber));
   1132             }
   1133             LOG_INFO(BSL_LS_SOC_PHY,
   1134                      (BSL_META_U(unit,
   1135                                  "_phy_54380_link_auto_detect: u=%d p=%d [C->F]\n"),
   1136                       unit, port));
   1137         }
   1138     }
   1139 
   1140     return SOC_E_NONE;
   1141 }
   1142 
   1143 /*
   1144  * Function:
   1145  *      phy_54380_link_get
   1146  * Purpose:
   1147  *      Determine the current link up/down status for a 54380 device.
   1148  * Parameters:
   1149  *      unit - StrataSwitch unit #.
   1150  *      port - StrataSwitch port #.
   1151  *      link - (OUT) Boolean, true indicates link established.
   1152  * Returns:
   1153  *      SOC_E_XXX
   1154  * Notes:
   1155  *      If using automedium, also switches the mode.
   1156  */
   1157 STATIC int
   1158 phy_54380_link_get(int unit, soc_port_t port, int *link)
   1159 {
   1160     phy_ctrl_t    *pc;
   1161     uint16         data; 
   1162     int rv = SOC_E_NONE;
   1163     bmacsec_phy_port_mode_t port_mode = 0;
   1164     bmacsec_dev_addr_t phy_dev_addr;
   1165     int bmacsec_link;
   1166 
   1167 
   1168     pc    = EXT_PHY_SW_STATE(unit, port);
   1169     *link = FALSE;      /* Default return */
   1170 
   1171     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1172         return SOC_E_NONE;
   1173     }
   1174 
   1175     if (!pc->fiber.enable && !pc->copper.enable) {
   1176         return SOC_E_NONE;
   1177     }
   1178 
   1179     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_MEDIUM_CHANGE);
   1180     if (pc->automedium) {
   1181         /* Check for medium change and update HW/SW accordingly. */
   1182         SOC_IF_ERROR_RETURN
   1183             (_phy_54380_medium_change(unit, port, FALSE, 0));
   1184     }
   1185 
   1186     if(PHY_COPPER_MODE(unit, port)) {
   1187         port_mode = BMACSEC_PHY_COPPER;
   1188     } else {
   1189         if(PHY_FIBER_MODE(unit, port)) {
   1190             port_mode = BMACSEC_PHY_FIBER;
   1191         }
   1192     }
   1193     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1194     rv = bmacsec_phy_54380_link_get(phy_dev_addr, port_mode, &bmacsec_link);
   1195     if (!BMACSEC_E_SUCCESS(rv)) {
   1196         return SOC_E_FAIL;
   1197     }
   1198     if (bmacsec_link == 1) {
   1199         *link = TRUE;
   1200     } else {
   1201         *link = FALSE;
   1202     }
   1203     /* If preferred medium is up, disable the other medium 
   1204      * to prevent false link. */
   1205     if (pc->automedium) {
   1206         if (pc->copper.preferred) {
   1207             if (pc->fiber.enable) {
   1208                 /* Power down Serdes if Copper mode is up */
   1209                 data = (*link && PHY_COPPER_MODE(unit, port)) ? 0 : 1;
   1210             } else {
   1211                 data = 0;
   1212 
   1213             }
   1214             port_mode = BMACSEC_PHY_FIBER;
   1215             (void)bmacsec_phy54380_enable_set(phy_dev_addr, pc->automedium,
   1216                                                  port_mode, data);
   1217         } else {  /* pc->fiber.preferred */
   1218             if (pc->copper.enable) {
   1219                 data = (*link && PHY_FIBER_MODE(unit, port)) ? 0 : 1;
   1220             } else {
   1221                 data = 0;
   1222             }
   1223             port_mode = BMACSEC_PHY_COPPER;
   1224             (void)bmacsec_phy54380_enable_set(phy_dev_addr, pc->automedium,
   1225                                              port_mode, data);
   1226         }
   1227     }
   1228     LOG_VERBOSE(BSL_LS_SOC_PHY,
   1229                 (BSL_META_U(unit,
   1230                             "phy_54380_link_get: u=%d p=%d mode=%s%s link=%d\n"),
   1231                  unit, port,
   1232                  PHY_COPPER_MODE(unit, port) ? "C" : "F",
   1233                  PHY_FIBER_100FX_MODE(unit, port)? "(100FX)" : "",
   1234                  *link));
   1235 
   1236     return SOC_E_NONE;
   1237 }
   1238 
   1239 
   1240 /*
   1241  * Function:
   1242  *      phy_54380_duplex_set
   1243  * Purpose:
   1244  *      Set the current duplex mode (forced).
   1245  * Parameters:
   1246  *      unit - StrataSwitch unit #.
   1247  *      port - StrataSwitch port #.
   1248  *      duplex - Boolean, true indicates full duplex, false indicates half.
   1249  * Returns:
   1250  *      SOC_E_NONE
   1251  *      SOC_E_UNAVAIL - Half duplex requested, and not supported.
   1252  * Notes:
   1253  *      The duplex is set only for the ACTIVE medium.
   1254  *      No synchronization performed at this level.
   1255  *      Autonegotiation is not manipulated.
   1256  */
   1257 
   1258 STATIC int
   1259 phy_54380_duplex_set(int unit, soc_port_t port, int duplex)
   1260 {
   1261     int                          rv=SOC_E_NONE;
   1262     phy_ctrl_t                   *pc;
   1263     bmacsec_phy_port_mode_t port_mode = 0;
   1264     bmacsec_dev_addr_t phy_dev_addr;
   1265     bmacsec_phy_duplex_t bmacsec_duplex;
   1266 
   1267     pc = EXT_PHY_SW_STATE(unit, port);
   1268     rv = SOC_E_NONE;
   1269 
   1270     if(PHY_COPPER_MODE(unit, port)) {
   1271         port_mode = BMACSEC_PHY_COPPER;
   1272     } else {
   1273         if(PHY_FIBER_MODE(unit, port)) {
   1274             port_mode = BMACSEC_PHY_FIBER;
   1275             if (duplex == 0) {
   1276                 return SOC_E_UNAVAIL;
   1277             }
   1278         }
   1279     }
   1280     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1281     if (duplex) {
   1282         bmacsec_duplex = BMACSEC_FULL_DUPLEX;
   1283     } else {
   1284         bmacsec_duplex = BMACSEC_HALF_DUPLEX;
   1285     }
   1286     rv = bmacsec_phy54380_duplex_set(phy_dev_addr, port_mode, 
   1287                                      bmacsec_duplex);
   1288 
   1289     if(BMACSEC_E_SUCCESS(rv)) {
   1290         if(PHY_FIBER_MODE(unit, port)) {
   1291             pc->fiber.force_duplex = duplex;
   1292         } else {
   1293             pc->copper.force_duplex = duplex;
   1294         }
   1295     }
   1296 
   1297     LOG_INFO(BSL_LS_SOC_PHY,
   1298              (BSL_META_U(unit,
   1299                          "phy_54380_duplex_set: u=%d p=%d d=%d rv=%d\n"),
   1300               unit, port, duplex, rv));
   1301     return (SOC_ERROR(rv));
   1302 }
   1303 
   1304 /*
   1305  * Function:
   1306  *      phy_54380_duplex_get
   1307  * Purpose:
   1308  *      Get the current operating duplex mode. If autoneg is enabled,
   1309  *      then operating mode is returned, otherwise forced mode is returned.
   1310  * Parameters:
   1311  *      unit - StrataSwitch unit #.
   1312  *      port - StrataSwitch port #.
   1313  *      duplex - (OUT) Boolean, true indicates full duplex, false
   1314  *              indicates half.
   1315  * Returns:
   1316  *      SOC_E_NONE
   1317  * Notes:
   1318  *      The duplex is retrieved for the ACTIVE medium.
   1319  *      No synchronization performed at this level. Autonegotiation is
   1320  *      not manipulated.
   1321  */
   1322 
   1323 STATIC int
   1324 phy_54380_duplex_get(int unit, soc_port_t port, int *duplex)
   1325 {
   1326 
   1327     int rv = SOC_E_NONE;
   1328     bmacsec_phy_port_mode_t port_mode = 0;
   1329     phy_ctrl_t             *pc;
   1330     bmacsec_dev_addr_t      phy_dev_addr;
   1331     bmacsec_phy_duplex_t    bmacsec_duplex;
   1332 
   1333     pc = EXT_PHY_SW_STATE(unit, port);
   1334 
   1335     if ( PHY_COPPER_MODE(unit, port) ) {
   1336         port_mode = BMACSEC_PHY_COPPER;
   1337     } else
   1338     if ( PHY_FIBER_MODE(unit, port) ) {
   1339         port_mode = BMACSEC_PHY_FIBER;
   1340         *duplex = TRUE;
   1341         return SOC_E_NONE;
   1342     }
   1343 
   1344     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1345     rv = bmacsec_phy54380_duplex_get(phy_dev_addr, port_mode, 
   1346                                      &bmacsec_duplex);
   1347     if (rv != BMACSEC_E_NONE) {
   1348         return SOC_E_FAIL;
   1349     }
   1350 
   1351     *duplex = (bmacsec_duplex == BMACSEC_FULL_DUPLEX) ? TRUE : FALSE;
   1352     return SOC_E_NONE;
   1353 }
   1354 
   1355 /*
   1356  * Function:
   1357  *      phy_54380_speed_set
   1358  * Purpose:
   1359  *      Set the current operating speed (forced).
   1360  * Parameters:
   1361  *      unit - StrataSwitch unit #.
   1362  *      port - StrataSwitch port #.
   1363  *      speed - Requested speed, only 1000 supported.
   1364  * Returns:
   1365  *      SOC_E_XXX
   1366  * Notes:
   1367  *      The speed is set only for the ACTIVE medium.
   1368  */
   1369 
   1370 STATIC int
   1371 phy_54380_speed_set(int unit, soc_port_t port, int speed)
   1372 {
   1373     int            rv = SOC_E_NONE; 
   1374     phy_ctrl_t    *pc;
   1375     bmacsec_dev_addr_t phy_dev_addr;
   1376     bmacsec_phy_port_mode_t port_mode = 0;
   1377 
   1378     pc = EXT_PHY_SW_STATE(unit, port);
   1379 
   1380     if(PHY_COPPER_MODE(unit, port)) {
   1381         port_mode = BMACSEC_PHY_COPPER;
   1382     } else {
   1383         if(PHY_FIBER_MODE(unit, port)) {
   1384             port_mode = BMACSEC_PHY_FIBER;
   1385             if (speed == 10) {
   1386                 return SOC_E_UNAVAIL;
   1387             }
   1388         }
   1389     }
   1390     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0);
   1391     rv = bmacsec_phy54380_speed_set(phy_dev_addr, port_mode, speed);
   1392 
   1393     if(BMACSEC_E_SUCCESS(rv)) {
   1394         if(PHY_COPPER_MODE(unit, port)) {
   1395             pc->copper.force_speed = speed;
   1396         } else {
   1397             if(PHY_FIBER_MODE(unit, port)) {
   1398                 if (speed == 100) {
   1399                         PHY_FLAGS_SET(unit, port, PHY_FLAGS_100FX);
   1400                         pc->fiber.autoneg_enable = FALSE;
   1401                         phy_54380_autoneg_set(unit, port, 0);
   1402                 }
   1403 
   1404                 if (speed == 1000) {
   1405                         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
   1406                         pc->fiber.force_duplex = TRUE;
   1407                         phy_54380_autoneg_set(unit, port,
   1408                                               pc->fiber.autoneg_enable);
   1409                 }
   1410                 pc->fiber.force_speed = speed;
   1411             }
   1412         }
   1413     }
   1414     LOG_INFO(BSL_LS_SOC_PHY,
   1415              (BSL_META_U(unit,
   1416                          "phy_54380_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"),
   1417               unit, port, speed, PHY_FIBER_MODE(unit, port), rv));
   1418     return SOC_ERROR(rv);
   1419 }
   1420 
   1421 /*
   1422  * Function:
   1423  *      phy_54380_speed_get
   1424  * Purpose:
   1425  *      Get the current operating speed for a 54380 device.
   1426  * Parameters:
   1427  *      unit - StrataSwitch unit #.
   1428  *      port - StrataSwitch port #.
   1429  *      duplex - (OUT) Boolean, true indicates full duplex, false
   1430  *              indicates half.
   1431  * Returns:
   1432  *      SOC_E_NONE
   1433  * Notes:
   1434  *      The speed is retrieved for the ACTIVE medium.
   1435  */
   1436 
   1437 STATIC int
   1438 phy_54380_speed_get(int unit, soc_port_t port, int *speed)
   1439 {
   1440     int rv = SOC_E_NONE;
   1441     bmacsec_phy_port_mode_t port_mode = 0;
   1442     bmacsec_dev_addr_t phy_dev_addr;
   1443     phy_ctrl_t    *pc;
   1444 
   1445     pc = EXT_PHY_SW_STATE(unit, port);
   1446 
   1447     if(PHY_COPPER_MODE(unit, port)) {
   1448         port_mode = BMACSEC_PHY_COPPER;
   1449     } else {
   1450         if(PHY_FIBER_MODE(unit, port)) {
   1451             port_mode = BMACSEC_PHY_FIBER;
   1452         }
   1453     }
   1454     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0);
   1455     rv = bmacsec_phy54380_speed_get(phy_dev_addr, port_mode, speed);
   1456 
   1457     if(!BMACSEC_E_SUCCESS(rv)) {
   1458         LOG_WARN(BSL_LS_SOC_PHY,
   1459                  (BSL_META_U(unit,
   1460                              "phy_54380_speed_get: u=%d p=%d invalid speed\n"),
   1461                   unit, port));
   1462     } else {
   1463         LOG_INFO(BSL_LS_SOC_PHY,
   1464                  (BSL_META_U(unit,
   1465                              "phy_54380_speed_get: u=%d p=%d speed=%d"),
   1466                   unit, port, *speed));
   1467     }
   1468 
   1469     return SOC_ERROR(rv);
   1470 }
   1471 
   1472 /*
   1473  * Function:
   1474  *      phy_54380_master_set
   1475  * Purpose:
   1476  *      Set the current master mode
   1477  * Parameters:
   1478  *      unit - StrataSwitch unit #.
   1479  *      port - StrataSwitch port #.
   1480  *      master - SOC_PORT_MS_*
   1481  * Returns:
   1482  *      SOC_E_XXX
   1483  * Notes:
   1484  *      The master mode is set only for the ACTIVE medium.
   1485  */
   1486 STATIC int
   1487 phy_54380_master_set(int unit, soc_port_t port, int master)
   1488 {
   1489     int                  rv = SOC_E_NONE;
   1490     phy_ctrl_t    *pc;
   1491     bmacsec_phy_port_mode_t port_mode = 0;
   1492     bmacsec_dev_addr_t phy_dev_addr;
   1493 
   1494     pc = EXT_PHY_SW_STATE(unit, port);
   1495     rv = SOC_E_NONE;
   1496 
   1497     if(PHY_COPPER_MODE(unit, port)) {
   1498         port_mode = BMACSEC_PHY_COPPER;
   1499     } else {
   1500         if(PHY_FIBER_MODE(unit, port)) {
   1501             port_mode = BMACSEC_PHY_FIBER;
   1502         }
   1503     }
   1504     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1505     rv = bmacsec_phy54380_master_set(phy_dev_addr, port_mode, master);
   1506     if(BMACSEC_E_SUCCESS(rv)) {
   1507         pc->copper.master = master;
   1508     }
   1509 
   1510     LOG_INFO(BSL_LS_SOC_PHY,
   1511              (BSL_META_U(unit,
   1512                          "phy_54380_master_set: u=%d p=%d master=%d fiber=%d rv=%d\n"),
   1513               unit, port, master, PHY_FIBER_MODE(unit, port), rv));
   1514     return SOC_ERROR(rv);
   1515 }
   1516 
   1517 /*
   1518  * Function:
   1519  *      phy_54380_master_get
   1520  * Purpose:
   1521  *      Get the current master mode for a 54380 device.
   1522  * Parameters:
   1523  *      unit - StrataSwitch unit #.
   1524  *      port - StrataSwitch port #.
   1525  *      master - (OUT) SOC_PORT_MS_*
   1526  * Returns:
   1527  *      SOC_E_NONE
   1528  * Notes:
   1529  *      The master mode is retrieved for the ACTIVE medium.
   1530  */
   1531 
   1532 STATIC int
   1533 phy_54380_master_get(int unit, soc_port_t port, int *master)
   1534 {
   1535     int        rv;
   1536     phy_ctrl_t *pc;
   1537     bmacsec_phy_port_mode_t port_mode = 0;
   1538     bmacsec_dev_addr_t phy_dev_addr;
   1539 
   1540     pc = EXT_PHY_SW_STATE(unit, port);
   1541     rv = SOC_E_NONE;
   1542 
   1543     if(PHY_COPPER_MODE(unit, port)) {
   1544         port_mode = BMACSEC_PHY_COPPER;
   1545     } else {
   1546         if(PHY_FIBER_MODE(unit, port)) {
   1547             port_mode = BMACSEC_PHY_FIBER;
   1548             *master = SOC_PORT_MS_NONE;
   1549             return SOC_E_NONE;
   1550         }
   1551     }
   1552     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1553     rv = bmacsec_phy54380_master_get(phy_dev_addr, port_mode, master);
   1554 
   1555     return SOC_ERROR(rv);
   1556 }
   1557 
   1558 /*
   1559  * Function:
   1560  *      phy_54380_autoneg_set
   1561  * Purpose:
   1562  *      Enable or disable auto-negotiation on the specified port.
   1563  * Parameters:
   1564  *      unit - StrataSwitch unit #.
   1565  *      port - StrataSwitch port #.
   1566  *      autoneg - Boolean, if true, auto-negotiation is enabled
   1567  *              (and/or restarted). If false, autonegotiation is disabled.
   1568  * Returns:
   1569  *      SOC_E_XXX
   1570  * Notes:
   1571  *      The autoneg mode is set only for the ACTIVE medium.
   1572  */
   1573 
   1574 STATIC int
   1575 phy_54380_autoneg_set(int unit, soc_port_t port, int autoneg)
   1576 {
   1577     int                 rv = SOC_E_NONE;
   1578     phy_ctrl_t   *pc;
   1579     bmacsec_port_ability_t *autoneg_advert = 0;
   1580     bmacsec_phy_port_mode_t port_mode = 0;
   1581     bmacsec_dev_addr_t phy_dev_addr;
   1582 
   1583 
   1584     pc = EXT_PHY_SW_STATE(unit, port);
   1585     rv = SOC_E_NONE;
   1586 
   1587     if(PHY_COPPER_MODE(unit, port)) {
   1588         port_mode = BMACSEC_PHY_COPPER;
   1589         autoneg_advert = (bmacsec_port_ability_t *)&pc->copper.advert_ability;
   1590     } else {
   1591         if(PHY_FIBER_MODE(unit, port)) {
   1592             port_mode = BMACSEC_PHY_FIBER;
   1593             autoneg_advert = (bmacsec_port_ability_t *)&pc->fiber.advert_ability;
   1594         }
   1595     }
   1596     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1597     rv = bmacsec_phy54380_an_set(phy_dev_addr, port_mode,
   1598                                  autoneg, autoneg_advert);
   1599     if(BMACSEC_E_SUCCESS(rv)) {
   1600         if(PHY_COPPER_MODE(unit, port)) {
   1601             pc->copper.autoneg_enable = autoneg ? TRUE : FALSE;
   1602         } else {
   1603             if(PHY_FIBER_MODE(unit, port)) {
   1604                 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE;
   1605             }
   1606         }
   1607     }
   1608 
   1609     LOG_INFO(BSL_LS_SOC_PHY,
   1610              (BSL_META_U(unit,
   1611                          "phy_54380_autoneg_set: u=%d p=%d autoneg=%d rv=%d\n"),
   1612               unit, port, autoneg, rv));
   1613     return SOC_ERROR(rv);
   1614 }
   1615 
   1616 /*
   1617  * Function:
   1618  *      phy_54380_autoneg_get
   1619  * Purpose:
   1620  *      Get the current auto-negotiation status (enabled/busy).
   1621  * Parameters:
   1622  *      unit - StrataSwitch unit #.
   1623  *      port - StrataSwitch port #.
   1624  *      autoneg - (OUT) if true, auto-negotiation is enabled.
   1625  *      autoneg_done - (OUT) if true, auto-negotiation is complete. This
   1626  *              value is undefined if autoneg == FALSE.
   1627  * Returns:
   1628  *      SOC_E_XXX
   1629  * Notes:
   1630  *      The autoneg mode is retrieved for the ACTIVE medium.
   1631  */
   1632 
   1633 STATIC int
   1634 phy_54380_autoneg_get(int unit, soc_port_t port,
   1635                      int *autoneg, int *autoneg_done)
   1636 {
   1637     int           rv;
   1638     phy_ctrl_t   *pc;
   1639     bmacsec_phy_port_mode_t port_mode = 0;
   1640     bmacsec_dev_addr_t phy_dev_addr;
   1641 
   1642     pc = EXT_PHY_SW_STATE(unit, port);
   1643 
   1644     rv            = SOC_E_NONE;
   1645     *autoneg      = FALSE;
   1646     *autoneg_done = FALSE;
   1647 
   1648     if(PHY_COPPER_MODE(unit, port)) {
   1649         port_mode = BMACSEC_PHY_COPPER;
   1650     } else {
   1651         if(PHY_FIBER_MODE(unit, port)) {
   1652             port_mode = BMACSEC_PHY_FIBER;
   1653         }
   1654     }
   1655     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1656     rv = bmacsec_phy54380_an_get(phy_dev_addr, port_mode, autoneg,
   1657                                  autoneg_done);
   1658 
   1659     return SOC_ERROR(rv);
   1660 }
   1661 
   1662 /*
   1663  * Function:
   1664  *      phy_54380_ability_advert_set
   1665  * Purpose:
   1666  *      Set the current advertisement for auto-negotiation.
   1667  * Parameters:
   1668  *      unit - StrataSwitch unit #.
   1669  *      port - StrataSwitch port #.
   1670  *      mode - Port mode mask indicating supported options/speeds.
   1671  * Returns:
   1672  *      SOC_E_XXX
   1673  * Notes:
   1674  *      The advertisement is set only for the ACTIVE medium.
   1675  *      No synchronization performed at this level.
   1676  */
   1677 STATIC int
   1678 phy_54380_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability)
   1679 {
   1680     int rv = SOC_E_NONE;
   1681     phy_ctrl_t    *pc;
   1682     bmacsec_phy_port_mode_t port_mode = 0;
   1683     bmacsec_port_ability_t bmacsec_ability ;
   1684     bmacsec_dev_addr_t phy_dev_addr;
   1685 
   1686     pc = EXT_PHY_SW_STATE(unit, port);
   1687     rv = SOC_E_NONE;
   1688 
   1689 
   1690     if(PHY_COPPER_MODE(unit, port)) {
   1691         port_mode = BMACSEC_PHY_COPPER;
   1692     } else {
   1693         if(PHY_FIBER_MODE(unit, port)) {
   1694             port_mode = BMACSEC_PHY_FIBER;
   1695         }
   1696     }
   1697     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0);
   1698     
   1699     
   1700     sal_memset(&bmacsec_ability, 0,  sizeof(bmacsec_port_ability_t)); 
   1701     phy_54380_pa_2_bmacsec_pa(ability, &bmacsec_ability);
   1702 
   1703     rv = bmacsec_phy54380_ability_advert_set(phy_dev_addr, port_mode, &bmacsec_ability);
   1704     if(BMACSEC_E_SUCCESS(rv)) {
   1705         if(PHY_COPPER_MODE(unit, port)) {
   1706             pc->copper.advert_ability = *ability;
   1707         } else {
   1708             if(PHY_FIBER_MODE(unit, port)) {
   1709                 pc->fiber.advert_ability = *ability;
   1710         } else {
   1711             }
   1712         }
   1713     }
   1714 
   1715     LOG_INFO(BSL_LS_SOC_PHY,
   1716              (BSL_META_U(unit,
   1717                          "phy_54380_adv_local_set: u=%d p=%d ability_hd_speed=0x%x, ability_fd_speed=0x%x, ability_pause=0x%x,  rv=%d\n"),
   1718               unit, port, ability->speed_half_duplex, ability->speed_full_duplex, ability->pause, rv));
   1719     return (SOC_ERROR(rv));
   1720 }
   1721 
   1722 /*
   1723  * Function:
   1724  *      phy_54380_adv_local_get
   1725  * Purpose:
   1726  *      Get the current advertisement for auto-negotiation.
   1727  * Parameters:
   1728  *      unit - StrataSwitch unit #.
   1729  *      port - StrataSwitch port #.
   1730  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1731  * Returns:
   1732  *      SOC_E_XXX
   1733  * Notes:
   1734  *      The advertisement is retrieved for the ACTIVE medium.
   1735  *      No synchronization performed at this level.
   1736  */
   1737 
   1738 STATIC int
   1739 phy_54380_ability_advert_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1740 {
   1741 
   1742     int rv = SOC_E_NONE;
   1743     bmacsec_port_ability_t bmacsec_ability;
   1744     bmacsec_phy_port_mode_t port_mode = BMACSEC_PHY_COPPER;
   1745     phy_ctrl_t   *pc;
   1746     bmacsec_dev_addr_t phy_dev_addr;
   1747 
   1748     if (NULL == ability) {
   1749         return SOC_E_PARAM;
   1750     }
   1751     sal_memset(ability, 0,  sizeof(soc_port_ability_t)); /* zero initialize */
   1752     
   1753     pc = EXT_PHY_SW_STATE(unit, port);
   1754     rv = SOC_E_NONE;
   1755 
   1756     if(PHY_COPPER_MODE(unit, port)) {
   1757         port_mode = BMACSEC_PHY_COPPER;
   1758     } else {
   1759         if(PHY_FIBER_MODE(unit, port)) {
   1760             port_mode = BMACSEC_PHY_FIBER;
   1761         }
   1762     }
   1763 
   1764     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0);
   1765     
   1766     rv = bmacsec_phy54380_ability_advert_get(phy_dev_addr, port_mode, 
   1767                                         &bmacsec_ability);
   1768     
   1769     phy_54380_bmacsec_pa_2_pa( &bmacsec_ability, ability);
   1770     
   1771     LOG_INFO(BSL_LS_SOC_PHY,
   1772              (BSL_META_U(unit,
   1773                          "phy_54380_adv_local_get: u=%d p=%d ability_hd_speed=0x%x, ability_fd_speed=0x%x, ability_pause=0x%x,  rv=%d\n"),
   1774               unit, port, ability->speed_half_duplex, ability->speed_full_duplex, ability->pause, rv));
   1775 
   1776     return  (SOC_ERROR(rv));
   1777 
   1778 }
   1779 
   1780 /*
   1781  * Function:
   1782  *      phy_54380_ability_remote_get
   1783  * Purpose:
   1784  *      Get partners current advertisement for auto-negotiation.
   1785  * Parameters:
   1786  *      unit - StrataSwitch unit #.
   1787  *      port - StrataSwitch port #.
   1788  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1789  * Returns:
   1790  *      SOC_E_XXX
   1791  * Notes:
   1792  *      The remote advertisement is retrieved for the ACTIVE medium.
   1793  *      No synchronization performed at this level. If Autonegotiation is
   1794  *      disabled or in progress, this routine will return an error.
   1795  */
   1796 
   1797 STATIC int
   1798 phy_54380_ability_remote_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1799 {
   1800     int rv, eee_enable = FALSE;
   1801     phy_ctrl_t    *pc;
   1802     bmacsec_phy_port_mode_t port_mode = BMACSEC_PHY_COPPER;
   1803     bmacsec_port_ability_t bmacsec_ability;
   1804     bmacsec_dev_addr_t phy_dev_addr;
   1805 
   1806     if (NULL == ability) {
   1807         return SOC_E_PARAM;
   1808     }
   1809 
   1810     sal_memset(ability, 0, sizeof(soc_port_ability_t)); /*zero init*/
   1811 
   1812     pc = EXT_PHY_SW_STATE(unit, port);
   1813     rv = SOC_E_NONE;
   1814 
   1815     if(PHY_COPPER_MODE(unit, port)) {
   1816         port_mode = BMACSEC_PHY_COPPER;
   1817     } else {
   1818         if(PHY_FIBER_MODE(unit, port)) {
   1819             port_mode = BMACSEC_PHY_FIBER;
   1820         }
   1821     }
   1822     
   1823     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   1824         eee_enable = TRUE;
   1825     }
   1826 
   1827     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1828     rv = bmacsec_phy54380_ability_remote_get(phy_dev_addr, port_mode, 
   1829                                          &bmacsec_ability, eee_enable);
   1830 
   1831     phy_54380_bmacsec_pa_2_pa( &bmacsec_ability, ability);
   1832 
   1833     LOG_INFO(BSL_LS_SOC_PHY,
   1834              (BSL_META_U(unit,
   1835                          "phy_54380_adv_remote_get: u=%d p=%d ability_hd_speed=0x%x ability_fd_speed=0x%x ability_pause=0x%x rv=%d\n"), unit, port, ability->speed_half_duplex, ability->speed_full_duplex, ability->pause, rv));
   1836 
   1837     return  (SOC_ERROR(rv));
   1838 }
   1839 
   1840 /*
   1841  * Function:
   1842  *      phy_54380_lb_set
   1843  * Purpose:
   1844  *      Set the local PHY loopback mode.
   1845  * Parameters:
   1846  *      unit - StrataSwitch unit #.
   1847  *      port - StrataSwitch port #.
   1848  *      loopback - Boolean: true = enable loopback, false = disable.
   1849  * Returns:
   1850  *      SOC_E_XXX
   1851  * Notes:
   1852  *      The loopback mode is set only for the ACTIVE medium.
   1853  *      No synchronization performed at this level.
   1854  */
   1855 
   1856 STATIC int
   1857 phy_54380_lb_set(int unit, soc_port_t port, int enable)
   1858 {
   1859     int           rv = SOC_E_NONE;
   1860     phy_ctrl_t    *pc;
   1861     bmacsec_phy_port_mode_t port_mode = BMACSEC_PHY_COPPER;
   1862     bmacsec_dev_addr_t phy_dev_addr;
   1863 
   1864     pc = EXT_PHY_SW_STATE(unit, port);
   1865     rv = SOC_E_NONE;
   1866 
   1867     if(PHY_COPPER_MODE(unit, port)) {
   1868         port_mode = BMACSEC_PHY_COPPER;
   1869     } else {
   1870         if(PHY_FIBER_MODE(unit, port)) {
   1871             port_mode = BMACSEC_PHY_FIBER;
   1872         }
   1873     }
   1874     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1875     rv = bmacsec_phy54380_loopback_set(phy_dev_addr, port_mode, enable);
   1876 
   1877     LOG_INFO(BSL_LS_SOC_PHY,
   1878              (BSL_META_U(unit,
   1879                          "phy_54380_lb_set: u=%d p=%d en=%d rv=%d\n"), 
   1880               unit, port, enable, rv));
   1881     return SOC_ERROR(rv); 
   1882 }
   1883 
   1884 /*
   1885  * Function:
   1886  *      phy_54380_lb_get
   1887  * Purpose:
   1888  *      Get the local PHY loopback mode.
   1889  * Parameters:
   1890  *      unit - StrataSwitch unit #.
   1891  *      port - StrataSwitch port #.
   1892  *      loopback - (OUT) Boolean: true = enable loopback, false = disable.
   1893  * Returns:
   1894  *      SOC_E_XXX
   1895  * Notes:
   1896  *      The loopback mode is retrieved for the ACTIVE medium.
   1897  */
   1898 
   1899 STATIC int
   1900 phy_54380_lb_get(int unit, soc_port_t port, int *enable)
   1901 {
   1902     int                  rv;
   1903     phy_ctrl_t    *pc;
   1904     bmacsec_phy_port_mode_t port_mode = BMACSEC_PHY_COPPER;
   1905     bmacsec_dev_addr_t phy_dev_addr;
   1906 
   1907     pc = EXT_PHY_SW_STATE(unit, port);
   1908     rv = SOC_E_NONE;
   1909 
   1910     if(PHY_COPPER_MODE(unit, port)) {
   1911         port_mode = BMACSEC_PHY_COPPER;
   1912     } else {
   1913         if(PHY_FIBER_MODE(unit, port)) {
   1914             port_mode = BMACSEC_PHY_FIBER;
   1915         }
   1916     }
   1917     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   1918     rv = bmacsec_phy54380_loopback_get(phy_dev_addr, port_mode, enable);
   1919 
   1920     return SOC_ERROR(rv); 
   1921 }
   1922 
   1923 /*
   1924  * Function:
   1925  *      phy_54380_interface_set
   1926  * Purpose:
   1927  *      Set the current operating mode of the PHY.
   1928  * Parameters:
   1929  *      unit - StrataSwitch unit #.
   1930  *      port - StrataSwitch port #.
   1931  *      pif - one of SOC_PORT_IF_*
   1932  * Returns:
   1933  *      SOC_E_NONE - success
   1934  *      SOC_E_UNAVAIL - unsupported interface
   1935  */
   1936 
   1937 STATIC int
   1938 phy_54380_interface_set(int unit, soc_port_t port, soc_port_if_t pif)
   1939 {
   1940     COMPILER_REFERENCE(unit);
   1941     COMPILER_REFERENCE(port);
   1942 
   1943     switch (pif) {
   1944     case SOC_PORT_IF_SGMII:
   1945     case SOC_PORT_IF_GMII:
   1946         return SOC_E_NONE;
   1947     default:
   1948         return SOC_E_UNAVAIL;
   1949     }
   1950 }
   1951 
   1952 /*
   1953  * Function:
   1954  *      phy_54380_interface_get
   1955  * Purpose:
   1956  *      Get the current operating mode of the PHY.
   1957  * Parameters:
   1958  *      unit - StrataSwitch unit #.
   1959  *      port - StrataSwitch port #.
   1960  *      pif - (OUT) one of SOC_PORT_IF_*
   1961  * Returns:
   1962  *      SOC_E_NONE
   1963  */
   1964 
   1965 STATIC int
   1966 phy_54380_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   1967 {
   1968     COMPILER_REFERENCE(unit);
   1969     COMPILER_REFERENCE(port);
   1970 
   1971     *pif = SOC_PORT_IF_SGMII;
   1972 
   1973     return SOC_E_NONE;
   1974 }
   1975 
   1976 /*
   1977  * Function:
   1978  *      phy_54380_ability_local_get
   1979  * Purpose:
   1980  *      Get the abilities of the local gigabit PHY.
   1981  * Parameters:
   1982  *      unit - StrataSwitch unit #.
   1983  *      port - StrataSwitch port #.
   1984  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1985  * Returns:
   1986  *      SOC_E_NONE
   1987  * Notes:
   1988  *      The ability is retrieved only for the ACTIVE medium.
   1989  */
   1990 
   1991 STATIC int
   1992 phy_54380_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1993 {
   1994     int         rv;
   1995     phy_ctrl_t *pc;
   1996     bmacsec_phy_port_mode_t port_mode = BMACSEC_PHY_COPPER;
   1997     bmacsec_dev_addr_t phy_dev_addr;
   1998     bmacsec_port_ability_t bmacsec_ability;
   1999 
   2000     rv = SOC_E_NONE;
   2001 
   2002     if (NULL == ability) {
   2003         return SOC_E_PARAM;
   2004     }
   2005 
   2006     sal_memset(ability, 0,  sizeof(soc_port_ability_t)); /* zero initialize */
   2007 
   2008     sal_memset(&bmacsec_ability, 0,  sizeof(bmacsec_port_ability_t)); /* zero initialize */
   2009     
   2010     if(PHY_COPPER_MODE(unit, port)) {
   2011         port_mode = BMACSEC_PHY_COPPER;
   2012         ability->medium = SOC_PA_MEDIUM_COPPER;
   2013     } else {
   2014         if(PHY_FIBER_MODE(unit, port)) {
   2015             port_mode = BMACSEC_PHY_FIBER;
   2016             ability->medium = SOC_PA_MEDIUM_FIBER;
   2017         }
   2018     }
   2019 
   2020     ability->interface = SOC_PA_INTF_SGMII;
   2021     
   2022     pc = EXT_PHY_SW_STATE(unit, port);
   2023 
   2024     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0);
   2025     
   2026     rv = bmacsec_phy54380_ability_get(phy_dev_addr, port_mode, &bmacsec_ability);
   2027     if (rv != BMACSEC_E_NONE) {
   2028         return SOC_E_FAIL;
   2029     }
   2030 
   2031     if(bmacsec_ability.speed_full_duplex & BMACSEC_PA_SPEED_1000MB) {
   2032         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   2033     }
   2034     if(bmacsec_ability.speed_full_duplex & BMACSEC_PA_SPEED_100MB) {
   2035         ability->speed_full_duplex |= SOC_PA_SPEED_100MB;
   2036     }
   2037     if(bmacsec_ability.speed_full_duplex & BMACSEC_PA_SPEED_10MB) {
   2038         ability->speed_full_duplex |= SOC_PA_SPEED_10MB;
   2039     }
   2040     if(bmacsec_ability.speed_half_duplex & BMACSEC_PA_SPEED_1000MB) {
   2041         ability->speed_half_duplex |= SOC_PA_SPEED_1000MB;
   2042     }
   2043     if(bmacsec_ability.speed_half_duplex & BMACSEC_PA_SPEED_100MB) {
   2044         ability->speed_half_duplex |= SOC_PA_SPEED_100MB;
   2045     }
   2046     if(bmacsec_ability.speed_half_duplex & BMACSEC_PA_SPEED_10MB) {
   2047         ability->speed_half_duplex |= SOC_PA_SPEED_10MB;
   2048     }
   2049     if(bmacsec_ability.pause & BMACSEC_PA_PAUSE_TX) {
   2050         ability->pause |= SOC_PA_PAUSE_TX;
   2051     }
   2052     if(bmacsec_ability.pause & BMACSEC_PA_PAUSE_RX) {
   2053         ability->pause |= SOC_PA_PAUSE_RX;
   2054     }
   2055     if(bmacsec_ability.pause & BMACSEC_PA_PAUSE_ASYMM) {
   2056         ability->pause |= SOC_PA_PAUSE_ASYMM;
   2057     }
   2058     if(bmacsec_ability.loopback & BMACSEC_PA_LB_NONE) {
   2059         ability->loopback |= SOC_PA_LB_NONE;
   2060     }
   2061     if(bmacsec_ability.loopback & BMACSEC_PA_LB_PHY) {
   2062         ability->loopback |= SOC_PA_LB_PHY;
   2063     }
   2064     if(bmacsec_ability.flags & BMACSEC_PA_AUTONEG) {
   2065         ability->flags |= SOC_PA_AUTONEG;
   2066     }
   2067     if(bmacsec_ability.eee & BMACSEC_PA_EEE_1GB_BASET) {
   2068         ability->eee |= SOC_PA_EEE_1GB_BASET;
   2069     }
   2070     if(bmacsec_ability.eee & BMACSEC_PA_EEE_100MB_BASETX) {
   2071         ability->eee |= SOC_PA_EEE_100MB_BASETX;
   2072     }
   2073  
   2074     if (pc->automedium) {
   2075         ability->flags     |= SOC_PA_COMBO;
   2076     }
   2077 
   2078 
   2079     LOG_INFO(BSL_LS_SOC_PHY,
   2080              (BSL_META_U(unit,
   2081                          "phy_54380_ability_local_get: u=%d p=%d ability_hd_speed=0x%x, ability_fd_speed=0x%x, ability_pause=0x%x,  rv=%d\n"),
   2082               unit, port, ability->speed_half_duplex, ability->speed_full_duplex, ability->pause, rv));
   2083     return SOC_E_NONE;
   2084 }
   2085 
   2086 /*
   2087  * Function:
   2088  *      phy_54380_mdix_set
   2089  * Description:
   2090  *      Set the Auto-MDIX mode of a port/PHY
   2091  * Parameters:
   2092  *      unit - Device number
   2093  *      port - Port number
   2094  *      mode - One of:
   2095  *              SOC_PORT_MDIX_AUTO
   2096  *                      Enable auto-MDIX when autonegotiation is enabled
   2097  *              SOC_PORT_MDIX_FORCE_AUTO
   2098  *                      Enable auto-MDIX always
   2099  *              SOC_PORT_MDIX_NORMAL
   2100  *                      Disable auto-MDIX
   2101  *              SOC_PORT_MDIX_XOVER
   2102  *                      Disable auto-MDIX, and swap cable pairs
   2103  * Return Value:
   2104  *      SOC_E_XXX
   2105  */
   2106 STATIC int
   2107 phy_54380_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode)
   2108 {
   2109 
   2110     int         rv = SOC_E_NONE;
   2111     phy_ctrl_t  *pc;
   2112     bmacsec_phy_port_mode_t port_mode = BMACSEC_PHY_COPPER;
   2113     bmacsec_dev_addr_t phy_dev_addr;
   2114     bmacsec_port_mdix_t bmacsec_mode;
   2115 
   2116     pc = EXT_PHY_SW_STATE(unit, port);
   2117 
   2118     if(PHY_COPPER_MODE(unit, port)) {
   2119         port_mode = BMACSEC_PHY_COPPER;
   2120     } else {
   2121         if(PHY_FIBER_MODE(unit, port)) {
   2122             port_mode = BMACSEC_PHY_FIBER;
   2123             if (mode != SOC_PORT_MDIX_NORMAL) {
   2124                 return SOC_E_UNAVAIL;
   2125             }
   2126         }
   2127     }
   2128     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   2129     switch(mode) {
   2130     case SOC_PORT_MDIX_AUTO:
   2131         bmacsec_mode = BMACSEC_PORT_MDIX_AUTO;
   2132         break;
   2133     case SOC_PORT_MDIX_FORCE_AUTO:
   2134         bmacsec_mode = BMACSEC_PORT_MDIX_FORCE_AUTO;
   2135         break;
   2136     case SOC_PORT_MDIX_NORMAL:
   2137         bmacsec_mode = BMACSEC_PORT_MDIX_NORMAL;
   2138         break;
   2139     case SOC_PORT_MDIX_XOVER:
   2140         bmacsec_mode = BMACSEC_PORT_MDIX_XOVER;
   2141         break;
   2142     default :
   2143         return SOC_E_CONFIG;
   2144     }
   2145 
   2146     rv = bmacsec_phy54380_mdix_set(phy_dev_addr, port_mode, bmacsec_mode);
   2147 
   2148     if(BMACSEC_E_SUCCESS(rv)) {
   2149         if(PHY_COPPER_MODE(unit, port)) {
   2150             pc->copper.mdix = mode;
   2151         }
   2152     }
   2153     return SOC_ERROR(rv);
   2154 }        
   2155 
   2156 /*
   2157  * Function:
   2158  *      phy_54380_mdix_get
   2159  * Description:
   2160  *      Get the Auto-MDIX mode of a port/PHY
   2161  * Parameters:
   2162  *      unit - Device number
   2163  *      port - Port number
   2164  *      mode - (Out) One of:
   2165  *              SOC_PORT_MDIX_AUTO
   2166  *                      Enable auto-MDIX when autonegotiation is enabled
   2167  *              SOC_PORT_MDIX_FORCE_AUTO
   2168  *                      Enable auto-MDIX always
   2169  *              SOC_PORT_MDIX_NORMAL
   2170  *                      Disable auto-MDIX
   2171  *              SOC_PORT_MDIX_XOVER
   2172  *                      Disable auto-MDIX, and swap cable pairs
   2173  * Return Value:
   2174  *      SOC_E_XXX
   2175  */
   2176 STATIC int
   2177 phy_54380_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode)
   2178 {
   2179     phy_ctrl_t    *pc;
   2180     int            speed;
   2181 
   2182     if (mode == NULL) {
   2183         return SOC_E_PARAM;
   2184     }
   2185 
   2186     pc = EXT_PHY_SW_STATE(unit, port);
   2187 
   2188     if (PHY_COPPER_MODE(unit, port)) {
   2189         SOC_IF_ERROR_RETURN(phy_54380_speed_get(unit, port, &speed));
   2190         if (speed == 1000) {
   2191            *mode = SOC_PORT_MDIX_AUTO;
   2192         } else {
   2193             *mode = pc->copper.mdix;
   2194         }
   2195     } else {
   2196         *mode = SOC_PORT_MDIX_NORMAL;
   2197     }
   2198 
   2199     return SOC_E_NONE;
   2200 }    
   2201 
   2202 /*
   2203  * Function:
   2204  *      phy_54380_mdix_status_get
   2205  * Description:
   2206  *      Get the current MDIX status on a port/PHY
   2207  * Parameters:
   2208  *      unit    - Device number
   2209  *      port    - Port number
   2210  *      status  - (OUT) One of:
   2211  *              SOC_PORT_MDIX_STATUS_NORMAL
   2212  *                      Straight connection
   2213  *              SOC_PORT_MDIX_STATUS_XOVER
   2214  *                      Crossover has been performed
   2215  * Return Value:
   2216  *      SOC_E_XXX
   2217  */
   2218 STATIC int
   2219 phy_54380_mdix_status_get(int unit, soc_port_t port, 
   2220                          soc_port_mdix_status_t *status)
   2221 {
   2222     int         rv;
   2223     phy_ctrl_t    *pc;
   2224 
   2225     bmacsec_phy_port_mode_t port_mode = BMACSEC_PHY_COPPER;
   2226     bmacsec_dev_addr_t phy_dev_addr;
   2227     bmacsec_port_mdix_status_t mdix_status;
   2228 
   2229     if (status == NULL) {
   2230         return SOC_E_PARAM;
   2231     }
   2232 
   2233     pc = EXT_PHY_SW_STATE(unit, port);
   2234 
   2235     if(PHY_COPPER_MODE(unit, port)) {
   2236         port_mode = BMACSEC_PHY_COPPER;
   2237     } else {
   2238         if(PHY_FIBER_MODE(unit, port)) {
   2239             port_mode = BMACSEC_PHY_FIBER;
   2240         }
   2241     }
   2242 
   2243     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   2244     rv = bmacsec_phy54380_mdix_status_get(phy_dev_addr, port_mode, 
   2245                                           &mdix_status);
   2246     if(BMACSEC_E_SUCCESS(rv)) {
   2247         if(mdix_status == BMACSEC_PORT_MDIX_STATUS_NORMAL) {
   2248             *status = SOC_PORT_MDIX_STATUS_NORMAL;
   2249         }
   2250         if(mdix_status == BMACSEC_PORT_MDIX_STATUS_XOVER) {
   2251             *status = SOC_PORT_MDIX_STATUS_XOVER;
   2252         }
   2253         return SOC_E_NONE;
   2254     }
   2255 
   2256     return SOC_ERROR(rv);
   2257 }    
   2258 
   2259 
   2260 
   2261 /*
   2262  * Function:
   2263  *      phy_54380_timesync_config_set
   2264  * Description:
   2265  *      
   2266  * Parameters:
   2267  *
   2268  * Return Value:
   2269  *      SOC_E_XXX
   2270  */
   2271 
   2272 int
   2273 phy_54380_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *timesync_config)
   2274 {
   2275     int                          rv;
   2276     phy_ctrl_t                   *pc;
   2277     bmacsec_dev_addr_t phy_dev_addr;
   2278 
   2279     pc = EXT_PHY_SW_STATE(unit, port);
   2280     rv = SOC_E_NONE;
   2281     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   2282 
   2283     rv = bmacsec_phy54380_timesync_config_set(phy_dev_addr, (bmacsec_port_phy_timesync_config_t *)timesync_config);
   2284     return (SOC_ERROR(rv));
   2285 
   2286 }
   2287 
   2288 
   2289 /*
   2290  * Function:
   2291  *     phy_54380_timesync_config_get 
   2292  * Description:
   2293  *     
   2294  * Parameters:
   2295  *
   2296  * Return Value:
   2297  *      SOC_E_XXX
   2298  */
   2299 
   2300 int
   2301 phy_54380_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *timesync_config)
   2302 {
   2303     int                          rv;
   2304     phy_ctrl_t                   *pc;
   2305     bmacsec_dev_addr_t phy_dev_addr;
   2306 
   2307     pc = EXT_PHY_SW_STATE(unit, port);
   2308     rv = SOC_E_NONE;
   2309     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   2310  
   2311     rv = bmacsec_phy54380_timesync_config_get(phy_dev_addr, (bmacsec_port_phy_timesync_config_t *)timesync_config);
   2312     return (SOC_ERROR(rv));
   2313 
   2314 }
   2315 
   2316 
   2317 /*
   2318  * Function:
   2319  *      phy_54380_timesync_control_set
   2320  * Description:
   2321  *      
   2322  * Parameters:
   2323  *
   2324  * Return Value:
   2325  *      SOC_E_XXX
   2326  */
   2327 
   2328 int
   2329 phy_54380_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t control_type, uint64 value)
   2330 {
   2331     int                          rv;
   2332     phy_ctrl_t                   *pc;
   2333     bmacsec_dev_addr_t phy_dev_addr;
   2334     buint64_t btemp64;
   2335 
   2336     COMPILER_64_SET(btemp64, COMPILER_64_HI(value), COMPILER_64_LO(value)); 
   2337 
   2338     pc = EXT_PHY_SW_STATE(unit, port);
   2339     rv = SOC_E_NONE;
   2340     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   2341  
   2342     rv = bmacsec_phy54380_timesync_control_set(phy_dev_addr,
   2343                 (bmacsec_port_phy_control_timesync_t) control_type, btemp64);
   2344     return (SOC_ERROR(rv));
   2345 
   2346 }
   2347 
   2348 
   2349 
   2350 /*
   2351  * Function:
   2352  *      phy_54380_timesync_control_get
   2353  * Description:
   2354  *      
   2355  * Parameters:
   2356  *
   2357  * Return Value:
   2358  *      SOC_E_XXX
   2359  */
   2360 int
   2361 phy_54380_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t control_type, uint64 *value)
   2362 {
   2363     int                          rv;
   2364     phy_ctrl_t                   *pc;
   2365     bmacsec_dev_addr_t phy_dev_addr;
   2366     buint64_t btemp64;
   2367 
   2368     COMPILER_64_ZERO(btemp64);
   2369     pc = EXT_PHY_SW_STATE(unit, port);
   2370     rv = SOC_E_NONE;
   2371     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   2372  
   2373     rv = bmacsec_phy54380_timesync_control_get(phy_dev_addr,
   2374                 (bmacsec_port_phy_control_timesync_t) control_type, &btemp64);
   2375   
   2376     COMPILER_64_SET(*value, COMPILER_64_HI(btemp64), COMPILER_64_LO(btemp64));
   2377 
   2378     return (SOC_ERROR(rv));
   2379 
   2380 }
   2381 
   2382 /*
   2383  * Function:
   2384  *      phy_54380_cable_diag_dispatch
   2385  * Purpose:
   2386  *      Run 54380 cable diagnostics
   2387  * Parameters:
   2388  *      unit - device number
   2389  *      port - port number
   2390  *      status - (OUT) cable diagnotic status structure
   2391  * Returns:     
   2392  *      SOC_E_XXX
   2393  */
   2394 STATIC int
   2395 phy_54380_cable_diag_dispatch(int unit, soc_port_t port,
   2396             soc_port_cable_diag_t *status)
   2397 {
   2398     /*ECD_CTRL :break link */
   2399     uint16 ecd_ctrl = 0x1000;
   2400     
   2401     
   2402     SOC_IF_ERROR_RETURN(
   2403         phy_ecd_cable_diag_init_40nm(unit, port));
   2404 
   2405     SOC_IF_ERROR_RETURN(
   2406         phy_ecd_cable_diag_40nm(unit, port, status, ecd_ctrl));
   2407     return SOC_E_NONE;
   2408 }
   2409 
   2410 
   2411 /*
   2412  * Function:
   2413  *      phy_54380_control_set
   2414  * Purpose:
   2415  *      Configure PHY device specific control fucntion.
   2416  * Parameters:
   2417  *      unit  - StrataSwitch unit #.
   2418  *      port  - StrataSwitch port #.
   2419  *      type  - Control to update
   2420  *      value - New setting for the control
   2421  * Returns:    
   2422  *      SOC_E_NONE
   2423  */
   2424 STATIC int
   2425 phy_54380_control_set(int unit, soc_port_t port,
   2426                       soc_phy_control_t type, uint32 value)
   2427 {
   2428     int rv, offset;
   2429     phy_ctrl_t    *pc;
   2430     bmacsec_phy_port_mode_t port_mode = BMACSEC_PHY_COPPER;
   2431     bmacsec_dev_addr_t phy_dev_addr;
   2432     soc_phy_config_t phy_config;
   2433 
   2434     pc = EXT_PHY_SW_STATE(unit, port);
   2435 
   2436     if(PHY_COPPER_MODE(unit, port)) {
   2437         port_mode = BMACSEC_PHY_COPPER;
   2438     } else {
   2439         if(PHY_FIBER_MODE(unit, port)) {
   2440             port_mode = BMACSEC_PHY_FIBER;
   2441         } else {
   2442             return SOC_E_NONE;
   2443         }
   2444     }
   2445     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   2446 
   2447     rv = BMACSEC_E_NONE;
   2448 
   2449     /* PHY Control types APIs*/
   2450     switch ( type ) {
   2451 #if 0
   2452     case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED:
   2453         pc->macsec_switch_fixed = value;
   2454         if ( value ) {
   2455             rv = bmacsec_phy54380_switch_side_set_params(phy_dev_addr, 
   2456                             BMACSEC_BCM54380_SWITCH_FIXED, 
   2457                             pc->macsec_switch_fixed_speed,
   2458                             pc->macsec_switch_fixed_duplex,
   2459                             pc->macsec_switch_fixed_pause);
   2460         } else { /* Switch side follows line side */
   2461             rv = bmacsec_phy54380_switch_side_set_params(phy_dev_addr, 
   2462                             BMACSEC_BCM54380_SWITCH_FOLLOWS_LINE, 
   2463                             -1, -1, -1);
   2464         }
   2465         break;
   2466 #endif
   2467     /* CLOCK CONTROLS  */
   2468     case SOC_PHY_CONTROL_CLOCK_ENABLE:
   2469         SOC_IF_ERROR_RETURN
   2470             (soc_phyctrl_offset_get(unit, port, &offset));
   2471         bmacsec_phy54380_clock_enable_set(phy_dev_addr, offset, value);
   2472         break;
   2473 
   2474     case SOC_PHY_CONTROL_CLOCK_SECONDARY_ENABLE:
   2475         SOC_IF_ERROR_RETURN
   2476             (soc_phyctrl_offset_get(unit, port, &offset));
   2477         bmacsec_phy54380_clock_secondary_enable_set(phy_dev_addr, offset, value);
   2478         break;
   2479 
   2480     case SOC_PHY_CONTROL_CLOCK_FREQUENCY:
   2481         return SOC_E_UNAVAIL;
   2482         break;
   2483 
   2484     case SOC_PHY_CONTROL_POWER:
   2485         rv = bmacsec_phy54380_power_mode_set(phy_dev_addr, value);
   2486         break;
   2487 
   2488     case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME:
   2489         bmacsec_phy54380_power_auto_wake_time_set(phy_dev_addr, value);
   2490         break;
   2491 
   2492     case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME:
   2493         bmacsec_phy54380_power_auto_sleep_time_set(phy_dev_addr, value);
   2494         break;
   2495 
   2496     case SOC_PHY_CONTROL_PORT_PRIMARY:
   2497         SOC_IF_ERROR_RETURN
   2498             (soc_phyctrl_primary_set(unit, port, (soc_port_t)value));
   2499         break;
   2500 
   2501     case SOC_PHY_CONTROL_PORT_OFFSET:
   2502         SOC_IF_ERROR_RETURN
   2503             (soc_phyctrl_offset_set(unit, port, (int)value));
   2504         break;
   2505 
   2506     case SOC_PHY_CONTROL_EEE:
   2507         phy_config = pc->copper;
   2508         if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   2509             rv = SOC_E_UNAVAIL;
   2510             break;
   2511         }
   2512         if ( PHY_FIBER_MODE(unit, port) ) {
   2513             phy_config = pc->fiber;
   2514             /* PHY does not support EEE in fiber mode */
   2515             rv = SOC_E_UNAVAIL;
   2516             break;
   2517         }
   2518         /* enable/disable EEE */
   2519         rv = bmacsec_phy_54380_eee_enable(phy_dev_addr, port_mode,
   2520                           (bmacsec_port_ability_t*) &phy_config.advert_ability,
   2521                           (value) ? 1 : 0 );
   2522         break;
   2523 
   2524     case SOC_PHY_CONTROL_EEE_AUTO:
   2525         if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) {
   2526             rv = SOC_E_UNAVAIL;
   2527             break;
   2528         }
   2529         if ( PHY_FIBER_MODE(unit, port) ) {
   2530             phy_config = pc->fiber;
   2531             /* PHY does not support EEE in fiber mode */
   2532             rv = SOC_E_UNAVAIL;
   2533             break;
   2534         }
   2535         /* enable/disable AutoGrEEEn */
   2536         rv = bmacsec_phy_54380_eee_auto_enable(phy_dev_addr,
   2537                           (bmacsec_port_t) port, port_mode,
   2538                           (value) ? 1 : 0 );
   2539         break;
   2540 
   2541     case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD:
   2542         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2543             rv = SOC_E_UNAVAIL;
   2544             break;
   2545         }
   2546         SOC_IF_ERROR_RETURN
   2547                 (bmacsec_phy_54380_eee_control_set(phy_dev_addr, 
   2548                                BMACSEC_PHY_54380_CONTROL_EEE_AUTO_IDLE_THRESHOLD,
   2549                                value));
   2550         break;       
   2551 
   2552     case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY:
   2553         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2554             rv = SOC_E_UNAVAIL;
   2555             break;
   2556         }
   2557         SOC_IF_ERROR_RETURN
   2558                 (bmacsec_phy_54380_eee_control_set(phy_dev_addr, 
   2559                                BMACSEC_PHY_54380_CONTROL_EEE_AUTO_FIXED_LATENCY, 
   2560                                value));
   2561         break;       
   2562     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   2563 
   2564         if(PHY_COPPER_MODE(unit, port)) {
   2565             SOC_IF_ERROR_RETURN(
   2566                bmacsec_phy54380_remote_loopback_set(phy_dev_addr, port_mode, value));
   2567         }else{
   2568             return SOC_E_UNAVAIL;
   2569 
   2570         }
   2571         break;    
   2572     case SOC_PHY_CONTROL_EEE_AUTO_BUFFER_LIMIT:
   2573         /* Buffer limit modification is not allowed */
   2574     case SOC_PHY_CONTROL_EEE_TRANSMIT_WAKE_TIME:
   2575     case SOC_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME:
   2576     case SOC_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME:
   2577     case SOC_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME:
   2578     case SOC_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME:
   2579     case SOC_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME:
   2580     case SOC_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME:
   2581         return SOC_E_UNAVAIL;
   2582 
   2583     case SOC_PHY_CONTROL_EEE_STATISTICS_CLEAR:
   2584         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2585             rv = SOC_E_UNAVAIL;
   2586             break;
   2587         }
   2588         SOC_IF_ERROR_RETURN
   2589                 (bmacsec_phy_54380_eee_control_set(phy_dev_addr, 
   2590                                BMACSEC_PHY_54380_CONTROL_EEE_STATISTICS_CLEAR, 
   2591                                value));
   2592         break;
   2593 
   2594     case SOC_PHY_CONTROL_SUPER_ISOLATE:
   2595         rv = bmacsec_phy54380_super_isolate_set(phy_dev_addr, value);
   2596         break;
   2597 
   2598     case SOC_PHY_CONTROL_MACSEC_ENABLE:
   2599         rv = bmacsec_phy54380_macsec_enable(phy_dev_addr,
   2600                                         pc->macsec_dev_addr, pc->macsec_enable);
   2601         if ( rv != BMACSEC_E_NONE ) {
   2602             return  SOC_E_FAIL;
   2603         }
   2604         if ( pc->macsec_enable ) {
   2605             rv = soc_macsecphy_init(unit, port, pc,
   2606                                     BMACSEC_CORE_BCM5438X, bmacsec_io_mmi1_quad);
   2607             if ( SOC_SUCCESS(rv) ) {
   2608                 LOG_INFO(BSL_LS_SOC_PHY, (BSL_META_U(unit,
   2609                          "MACSEC init for u=%d p=%d SUCCESS\n"), unit, port));
   2610             } else {
   2611                 LOG_ERROR(BSL_ERROR    , (BSL_META_U(unit,
   2612                          "MACSEC init for u=%d p=%d FAIL !!\n"), unit, port));
   2613             }
   2614         }
   2615         break;
   2616 
   2617     default:
   2618         return  SOC_E_UNAVAIL;
   2619     }  /* switch ( type ) */
   2620 
   2621     return (SOC_ERROR(rv));
   2622 }
   2623 
   2624 /*
   2625  * Function:
   2626  *      phy_54380_control_get
   2627  * Purpose:
   2628  *      Get current control settign of the PHY.                                
   2629  * Parameters:
   2630  *      unit  - StrataSwitch unit #.
   2631  *      port  - StrataSwitch port #.
   2632  *      type  - Control to update
   2633  *      value - (OUT)Current setting for the control
   2634  * Returns:
   2635  *      SOC_E_NONE
   2636  */
   2637 STATIC int 
   2638 phy_54380_control_get(int unit, soc_port_t port,
   2639                       soc_phy_control_t type, uint32 *value)
   2640 {
   2641     int rv = SOC_E_NONE, offset;
   2642     phy_ctrl_t    *pc;
   2643     bmacsec_dev_addr_t phy_dev_addr;
   2644     soc_port_t primary;
   2645     bmacsec_phy_port_mode_t port_mode = BMACSEC_PHY_COPPER;
   2646 
   2647     pc = EXT_PHY_SW_STATE(unit, port);
   2648     if(PHY_COPPER_MODE(unit, port)) {
   2649         port_mode = BMACSEC_PHY_COPPER;
   2650     } else {
   2651         if(PHY_FIBER_MODE(unit, port)) {
   2652             port_mode = BMACSEC_PHY_FIBER;
   2653         } else {
   2654             return SOC_E_NONE;
   2655         }
   2656     }
   2657     
   2658     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 
   2659    
   2660     if (NULL == value) {
   2661         return SOC_E_PARAM;
   2662     }
   2663 
   2664     if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) {
   2665         return SOC_E_PARAM;
   2666     }
   2667 
   2668     /* PHY Control types APIs*/
   2669     switch ( type ) {
   2670 
   2671     case SOC_PHY_CONTROL_POWER:
   2672         *value = pc->power_mode;
   2673         break;
   2674 
   2675     case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME:
   2676         bmacsec_phy54380_power_auto_sleep_time_get(phy_dev_addr, value); 
   2677         break;
   2678     
   2679     case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME:
   2680         bmacsec_phy54380_power_auto_wake_time_get(phy_dev_addr, value); 
   2681         break;
   2682 
   2683     case SOC_PHY_CONTROL_PORT_PRIMARY:
   2684         SOC_IF_ERROR_RETURN
   2685             (soc_phyctrl_primary_get(unit, port, &primary));
   2686         *value = (uint32) primary;
   2687         break;
   2688 
   2689     case SOC_PHY_CONTROL_PORT_OFFSET:
   2690         SOC_IF_ERROR_RETURN
   2691             (soc_phyctrl_offset_get(unit, port, &offset));
   2692         *value = (uint32) offset;
   2693         break;
   2694 
   2695     case SOC_PHY_CONTROL_CLOCK_ENABLE:
   2696         SOC_IF_ERROR_RETURN
   2697             (soc_phyctrl_offset_get(unit, port, &offset));
   2698         bmacsec_phy54380_clock_enable_get(phy_dev_addr, offset, value);
   2699         break;
   2700 
   2701     case SOC_PHY_CONTROL_CLOCK_SECONDARY_ENABLE:
   2702         SOC_IF_ERROR_RETURN
   2703             (soc_phyctrl_offset_get(unit, port, &offset));
   2704         bmacsec_phy54380_clock_secondary_enable_get(phy_dev_addr, offset, value); 
   2705         break;
   2706 
   2707     case SOC_PHY_CONTROL_EEE:
   2708         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2709             rv = SOC_E_UNAVAIL;
   2710             break;
   2711         }
   2712         bmacsec_phy_54380_get_eee_control_status(phy_dev_addr, value);
   2713         break;
   2714     
   2715     case SOC_PHY_CONTROL_EEE_AUTO:
   2716         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2717             rv = SOC_E_UNAVAIL;
   2718             break;
   2719         }
   2720         bmacsec_phy_54380_get_auto_eee_control_status(phy_dev_addr,
   2721                                (bmacsec_port_t)port, value);
   2722         break;
   2723 
   2724     case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY:
   2725         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2726             rv = SOC_E_UNAVAIL;
   2727             break;
   2728         }
   2729         SOC_IF_ERROR_RETURN
   2730                 (bmacsec_phy_54380_eee_control_get(phy_dev_addr,
   2731                                BMACSEC_PHY_54380_CONTROL_EEE_AUTO_FIXED_LATENCY,  
   2732                                value));
   2733             break;
   2734 
   2735     case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD:
   2736         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2737             rv = SOC_E_UNAVAIL;
   2738             break;
   2739         }
   2740         SOC_IF_ERROR_RETURN
   2741                 (bmacsec_phy_54380_eee_control_get(phy_dev_addr,
   2742                                BMACSEC_PHY_54380_CONTROL_EEE_AUTO_IDLE_THRESHOLD,  
   2743                                value));
   2744         break;
   2745     
   2746     case SOC_PHY_CONTROL_EEE_TRANSMIT_EVENTS:
   2747         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2748             rv = SOC_E_UNAVAIL;
   2749             break;
   2750         }
   2751         SOC_IF_ERROR_RETURN
   2752                 (bmacsec_phy_54380_eee_control_get(phy_dev_addr,
   2753                                BMACSEC_PHY_54380_CONTROL_EEE_TRANSMIT_EVENTS,  
   2754                                value));
   2755         break;
   2756     
   2757     case SOC_PHY_CONTROL_EEE_TRANSMIT_DURATION:
   2758         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2759             rv = SOC_E_UNAVAIL;
   2760             break;
   2761         }
   2762         SOC_IF_ERROR_RETURN
   2763                 (bmacsec_phy_54380_eee_control_get(phy_dev_addr,
   2764                                BMACSEC_PHY_54380_CONTROL_EEE_TRANSMIT_DURATION,  
   2765                                value));
   2766         break;
   2767 
   2768     case SOC_PHY_CONTROL_EEE_RECEIVE_EVENTS:
   2769         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2770             rv = SOC_E_UNAVAIL;
   2771             break;
   2772         }
   2773         SOC_IF_ERROR_RETURN
   2774                 (bmacsec_phy_54380_eee_control_get(phy_dev_addr,
   2775                                BMACSEC_PHY_54380_CONTROL_EEE_RECEIVE_EVENTS,  
   2776                                value));
   2777         break;
   2778 
   2779     case SOC_PHY_CONTROL_EEE_RECEIVE_DURATION:
   2780         if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) {
   2781             rv = SOC_E_UNAVAIL;
   2782             break;
   2783         }
   2784         SOC_IF_ERROR_RETURN
   2785                 (bmacsec_phy_54380_eee_control_get(phy_dev_addr,
   2786                                BMACSEC_PHY_54380_CONTROL_EEE_RECEIVE_DURATION,  
   2787                                value));
   2788         break;
   2789     case SOC_PHY_CONTROL_LOOPBACK_REMOTE:
   2790 
   2791         if(PHY_COPPER_MODE(unit, port)) {
   2792             SOC_IF_ERROR_RETURN(
   2793                bmacsec_phy54380_remote_loopback_get(phy_dev_addr, port_mode, value));
   2794         }else{
   2795             return SOC_E_UNAVAIL;
   2796 
   2797         }
   2798         break;    
   2799 
   2800     default:
   2801         return SOC_E_UNAVAIL;    
   2802     }  /* switch ( type ) */
   2803     
   2804     return rv;
   2805 }
   2806 
   2807 STATIC int 
   2808 phy_54380_probe(int unit, phy_ctrl_t *pc) {
   2809     int rv = SOC_E_NONE, oui = 0, model = 0, rev = 0;
   2810     soc_phy_info_t *pi;
   2811     bmacsec_dev_addr_t phy_dev_addr;
   2812 
   2813     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0);
   2814 
   2815     phy54380_get_model_rev(phy_dev_addr, &oui, &model, &rev);
   2816 
   2817     pi = &SOC_PHY_INFO(unit, pc->port);
   2818 
   2819     switch (model) {
   2820     
   2821         case PHY_BCM54380_MODEL:
   2822         case PHY_BCM54340_MODEL:
   2823         break;
   2824 
   2825         case PHY_BCM54382_MODEL:
   2826         /*case PHY_BCM54385_MODEL  (same as PHY_BCM54382_MODEL)
   2827          */
   2828             if (rev & 0x8)  {
   2829                 /* 54382 detected  - A0/B0/.. */
   2830                 pi->phy_name = "BCM54382";
   2831             } else {
   2832                 /* 54385 detected */
   2833                 pi->phy_name = "BCM54385";
   2834             }
   2835             break;
   2836         default:
   2837             return SOC_E_NOT_FOUND;
   2838     }
   2839     return rv;
   2840 }
   2841 
   2842 
   2843 STATIC int
   2844 phy_54380_link_up(int unit, soc_port_t port)
   2845 {
   2846     int speed;
   2847     phy_ctrl_t    *pc;
   2848     pc = EXT_PHY_SW_STATE(unit, port);
   2849     
   2850     /* get the speed status from line side */
   2851     SOC_IF_ERROR_RETURN
   2852         (phy_54380_speed_get(unit, port, &speed));
   2853     
   2854     /* Notify interface to internal PHY */
   2855     SOC_IF_ERROR_RETURN
   2856         (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII));
   2857 
   2858     /* Situation observed with Saber devices XGXS16g1l+BCM54640E
   2859        Linkscan is not updating speed for internal phy xgxs16g1l. 
   2860        It was observed that when speed is set to 100M the int phy 
   2861        is still set to 1G and traffic does not flow through untill 
   2862        int phy speed is also update to 100M. This applies to other 
   2863        speeds as well. 
   2864        Explicitly send speed notify to int phy from ext phy.
   2865     */
   2866     SOC_IF_ERROR_RETURN
   2867         (soc_phyctrl_notify(unit, port, phyEventSpeed, speed));
   2868 
   2869     /* Check if MACSEC_SWITCH_SIDE_POLICY is DUPLEX_GATEWAY mode */
   2870     if ( (pc->macsec_enable) &&
   2871          (pc->macsec_mac_policy == BMACSEC_BCM54380_SWITCH_DUPLEX_GATEWAY) ) {
   2872         int duplex;
   2873         bmacsec_dev_addr_t phy_dev_addr;
   2874         phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0);
   2875 
   2876         /* Duplex Gateway mode for supporting half-duplex-free switches:   *\
   2877         |* When line-side PHY lilnks up at half-duplex,                    *|
   2878         \* set half-duplex to line-side MAC, full-duplex to switch-side MAC*/
   2879 
   2880         /* get the duplex status from line side */
   2881         SOC_IF_ERROR_RETURN(
   2882             phy_54380_duplex_get(unit, port, &duplex) );
   2883         if ( pc->macsec_switch_fixed_speed  == speed  &&
   2884              pc->macsec_switch_fixed_duplex == duplex) {
   2885             return SOC_E_NONE;    /* speed/duplex unchanged */
   2886         }
   2887 
   2888         pc->macsec_switch_fixed_speed  = speed;
   2889         pc->macsec_switch_fixed_duplex = duplex;
   2890         /* Config duplex Gateway parameters accordingly */
   2891         SOC_IF_ERROR_RETURN(
   2892                 bmacsec_phy54380_switch_side_set_params(phy_dev_addr,
   2893                               (bmacsec_phy_mac_policy_t) pc->macsec_mac_policy,
   2894                               speed, duplex, pc->macsec_switch_fixed_pause) );
   2895         /* under DUPLEX_GATEWAY mode, always Full-Duplex on system side */
   2896         SOC_IF_ERROR_RETURN
   2897             (soc_phyctrl_notify(unit, port, phyEventDuplex, TRUE));
   2898     }
   2899 
   2900     return SOC_E_NONE;
   2901 }
   2902 
   2903 /*
   2904  * Variable:    phy_54380drv_ge
   2905  * Purpose:     PHY driver for 54380
   2906  */
   2907 phy_driver_t phy_54380drv_ge = {
   2908     "54380 (MACSec PHY) Gigabit PHY Driver",
   2909     phy_54380_init,
   2910     phy_54380_reset,
   2911     phy_54380_link_get,
   2912     phy_54380_enable_set,
   2913     phy_54380_enable_get,
   2914     phy_54380_duplex_set,
   2915     phy_54380_duplex_get,
   2916     phy_54380_speed_set,
   2917     phy_54380_speed_get,
   2918     phy_54380_master_set,
   2919     phy_54380_master_get,
   2920     phy_54380_autoneg_set,
   2921     phy_54380_autoneg_get,
   2922     NULL,                       /* pd_adv_local_set */
   2923     NULL,                       /* pd_adv_local_get */
   2924     NULL,                       /* pd_adv_remote_get */
   2925     phy_54380_lb_set,
   2926     phy_54380_lb_get,
   2927     phy_54380_interface_set,
   2928     phy_54380_interface_get,
   2929     NULL,                       /* pd_ability */
   2930     phy_54380_link_up,          /* pd_linkup */
   2931     NULL,                       /* pd_linkdn_evt */
   2932     phy_54380_mdix_set,
   2933     phy_54380_mdix_get,
   2934     phy_54380_mdix_status_get,
   2935     phy_54380_medium_config_set,
   2936     phy_54380_medium_config_get,
   2937     phy_54380_medium_status,
   2938     phy_54380_cable_diag_dispatch,
   2939     NULL,                       /* pd_link_change */
   2940     phy_54380_control_set,
   2941     phy_54380_control_get,
   2942     phy_54380_reg_read,
   2943     phy_54380_reg_write,
   2944     phy_54380_reg_modify,
   2945     NULL,                       /* pd_notify */
   2946     phy_54380_probe,
   2947     phy_54380_ability_advert_set,
   2948     phy_54380_ability_advert_get,
   2949     phy_54380_ability_remote_get,
   2950     phy_54380_ability_local_get,
   2951     NULL,                        /* pd_firmware_set */
   2952     phy_54380_timesync_config_set,
   2953     phy_54380_timesync_config_get,
   2954     phy_54380_timesync_control_set,
   2955     phy_54380_timesync_control_get
   2956 };
   2957 
   2958 
   2959 #else /* INCLUDE_PHY_54380 */
   2960 int _soc_phy_54380_not_empty;
   2961 #endif /* INCLUDE_PHY_54380 */
   2962 #endif /* INCLUDE_MACSEC */
   2963 
   2964