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

phy545xx.c (90987B)


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