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

phy8729.c (57198B)


      1 /*
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  */
      8 
      9 /*
     10  * File:        phy8729.c
     11  * Purpose:     SDK PHY driver for BCM8729 (MACSec)
     12  *
     13  * Supported BCM546X Family of PHY devices:
     14  *
     15  *      Device  Ports   Media                           MAC Interface
     16  *      8729    4       2 10G SFP+, 2 1G SFP            XFI/SGMII
     17  *
     18  * Workarounds:
     19  *
     20  * References:
     21  *     
     22  * Notes:
     23  */ 
     24 
     25 
     26 #include <sal/types.h>
     27 #include <sal/core/spl.h>
     28 #include <shared/bsl.h>
     29 #include <soc/drv.h>
     30 #include <soc/debug.h>
     31 #include <soc/error.h>
     32 #include <soc/phyreg.h>
     33 
     34 #include <soc/phy.h>
     35 #include <soc/phy/phyctrl.h>
     36 #include <soc/phy/drv.h>
     37 
     38 #include "phydefs.h"      /* Must include before other phy related includes */
     39 
     40 
     41 
     42 #ifdef INCLUDE_MACSEC
     43 #if defined(INCLUDE_PHY_8729)
     44 #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
     45 #include "phyident.h"
     46 #include "phyreg.h"
     47 #include "phynull.h"
     48 #include "phyfege.h"
     49 #include "phyxehg.h"
     50 #include "phy8729.h"
     51 #include <soc/macsecphy.h>
     52 #include <bmacsec.h>
     53 #include <bmacsec_io.h>
     54 
     55 #define ADVERT_ALL_COPPER \
     56         (SOC_PA_PAUSE | SOC_PA_SPEED_10MB | \
     57          SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB)
     58 
     59 #define ADVERT_ALL_FIBER \
     60         (SOC_PA_PAUSE | SOC_PA_SPEED_1000MB) 
     61 
     62 #define ADVERT_ALL_10GFIBER \
     63         (SOC_PA_PAUSE | SOC_PA_SPEED_10GB) 
     64 
     65 
     66 #define PHY_ID1_8729     0x603c
     67 
     68 static bmacsec_error_t error_tbl[] = {
     69                                 SOC_E_NONE,
     70                                 SOC_E_INTERNAL,
     71                                 SOC_E_MEMORY,
     72                                 SOC_E_PARAM,
     73                                 SOC_E_EMPTY,
     74                                 SOC_E_FULL,
     75                                 SOC_E_NOT_FOUND,
     76                                 SOC_E_EXISTS,
     77                                 SOC_E_TIMEOUT,
     78                                 SOC_E_FAIL,
     79                                 SOC_E_DISABLED,
     80                                 SOC_E_BADID,
     81                                 SOC_E_RESOURCE,
     82                                 SOC_E_CONFIG,
     83                                 SOC_E_UNAVAIL,
     84                                 SOC_E_INIT,
     85                                 SOC_E_PORT,
     86                             };
     87 /*
     88  * Convert BMACSEC return codes to SOC return code.
     89  */
     90 #define SOC_ERROR(e)    error_tbl[(-e)]
     91 
     92 
     93 STATIC int phy_8729_init(int unit, soc_port_t port);
     94 STATIC int phy_8729_link_get(int unit, soc_port_t port, int *link);
     95 STATIC int phy_8729_enable_set(int unit, soc_port_t port, int enable);
     96 STATIC int phy_8729_duplex_set(int unit, soc_port_t port, int duplex);
     97 STATIC int phy_8729_duplex_get(int unit, soc_port_t port, int *duplex);
     98 STATIC int phy_8729_speed_set(int unit, soc_port_t port, int speed);
     99 STATIC int phy_8729_speed_get(int unit, soc_port_t port, int *speed);
    100 STATIC int phy_8729_master_set(int unit, soc_port_t port, int master);
    101 STATIC int phy_8729_master_get(int unit, soc_port_t port, int *master);
    102 STATIC int phy_8729_an_set(int unit, soc_port_t port, int autoneg);
    103 STATIC int phy_8729_an_get(int unit, soc_port_t port,
    104                                 int *autoneg, int *autoneg_done);
    105 STATIC int phy_8729_lb_set(int unit, soc_port_t port, int enable);
    106 STATIC int phy_8729_lb_get(int unit, soc_port_t port, int *enable);
    107 STATIC int phy_8729_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode);
    108 STATIC int phy_8729_mdix_get(int unit, soc_port_t port, 
    109                              soc_port_mdix_t *mode);
    110 STATIC int phy_8729_mdix_status_get(int unit, soc_port_t port, 
    111                                     soc_port_mdix_status_t *status);
    112 STATIC int phy_8729_medium_config_set(int unit, soc_port_t port, 
    113                                       soc_port_medium_t  medium,
    114                                       soc_phy_config_t  *cfg);
    115 STATIC int phy_8729_medium_config_get(int unit, soc_port_t port, 
    116                                       soc_port_medium_t medium,
    117                                       soc_phy_config_t *cfg);
    118 STATIC int phy_8729_ability_advert_set(int unit, soc_port_t port, 
    119                                        soc_port_ability_t *ability);
    120 STATIC int phy_8729_ability_advert_get(int unit, soc_port_t port,
    121                                        soc_port_ability_t *ability);
    122 STATIC int phy_8729_ability_remote_get(int unit, soc_port_t port,
    123                                        soc_port_ability_t *ability);
    124 STATIC int phy_8729_ability_local_get(int unit, soc_port_t port, 
    125                                 soc_port_ability_t *ability);
    126 STATIC int phy_8729_firmware_set(int unit, int port, int offset, 
    127                                  uint8 *data, int len);
    128 STATIC int phy_8729_control_set(int unit, soc_port_t port,
    129                      soc_phy_control_t type, uint32 value);
    130 STATIC int phy_8729_control_get(int unit, soc_port_t port,
    131                      soc_phy_control_t type, uint32 *value);
    132 STATIC int phy_8729_linkup(int unit, soc_port_t port);
    133 
    134 
    135 
    136 
    137 /*
    138  * Function:
    139  *      _phy_8729_medium_config_update
    140  * Purpose:
    141  *      Update the PHY with config parameters
    142  * Parameters:
    143  *      unit - StrataSwitch unit #.
    144  *      port - StrataSwitch port #.
    145  *      cfg - Config structure.
    146  * Returns:
    147  *      SOC_E_XXX
    148  */
    149 
    150 STATIC int
    151 _phy_8729_medium_config_update(int unit, soc_port_t port,
    152                                 soc_phy_config_t *cfg)
    153 {
    154 
    155     SOC_IF_ERROR_RETURN
    156         (phy_8729_speed_set(unit, port, cfg->force_speed));
    157     SOC_IF_ERROR_RETURN
    158         (phy_8729_duplex_set(unit, port, cfg->force_duplex));
    159     SOC_IF_ERROR_RETURN
    160         (phy_8729_master_set(unit, port, cfg->master));
    161     SOC_IF_ERROR_RETURN
    162         (phy_8729_ability_advert_set(unit, port, &cfg->advert_ability));
    163     SOC_IF_ERROR_RETURN
    164         (phy_8729_an_set(unit, port, cfg->autoneg_enable));
    165 /*
    166     SOC_IF_ERROR_RETURN
    167         (phy_8729_mdix_set(unit, port, cfg->mdix));
    168 */
    169 
    170     return SOC_E_NONE;
    171 }
    172 
    173 /* Function:
    174  *    phy_8729_init
    175  * Purpose:    
    176  *    Initialize 8729 phys
    177  * Parameters:
    178  *    unit - StrataSwitch unit #.
    179  *    port - StrataSwitch port #. 
    180  * Returns:    
    181  *    SOC_E_NONE
    182  */
    183 
    184 STATIC int
    185 phy_8729_init(int unit, soc_port_t port)
    186 {
    187     phy_ctrl_t     *pc;
    188     bmacsec_dev_addr_t phy_dev_addr;
    189     bmacsec_dev_addr_t macsec_dev_addr;
    190     int rv = SOC_E_NONE;
    191     bmacsec_phy8729_intf_t line_mode;
    192     int fiber_preferred, fiber_enable = FALSE, copper_enable = FALSE;
    193     int macsec_enable = 0, mmi_mdio_addr;
    194     int     xaui_interface = 0;
    195 
    196     pc     = EXT_PHY_SW_STATE(unit, port);
    197 
    198     /* By default MACSEC is disable */
    199     /* Check if enable property is set */
    200     macsec_enable = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0);
    201 
    202     pc->macsec_enable = macsec_enable;
    203 
    204     pc->macsec_dev_port = soc_property_port_get(unit, port, 
    205                                        spn_MACSEC_PORT_INDEX, -1);
    206 
    207     phy_dev_addr    = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    208 
    209     /* Base PHY ID is used to access MACSEC core */
    210     mmi_mdio_addr = soc_property_port_get(unit, port, 
    211                                         spn_MACSEC_DEV_ADDR, -1);
    212     if (mmi_mdio_addr < 0) {
    213         LOG_WARN(BSL_LS_SOC_PHY,
    214                  (BSL_META_U(unit,
    215                              "phy_8729_init: "
    216                              "MACSEC_DEV_ADDR property "
    217                              "not configured for u=%d p=%d\n"), unit, port));
    218         return SOC_E_CONFIG;
    219     }
    220     macsec_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1);
    221     pc->macsec_dev_addr = macsec_dev_addr;
    222 
    223     rv = bmacsec_phy8729_phy_mac_addr_set(phy_dev_addr, 
    224                                           macsec_dev_addr, 
    225                                           pc->macsec_dev_port,
    226                                           bmacsec_io_mmi1_cl45);
    227     if(rv != BMACSEC_E_NONE) {
    228         LOG_WARN(BSL_LS_SOC_PHY,
    229                  (BSL_META_U(unit,
    230                              "phy_8729_init: bmacsec_phy_mac_addr_set "
    231                              "returned error for u=%d p=%d\n"), unit, port));
    232         return SOC_E_FAIL;
    233     }
    234 
    235 
    236     /* 
    237      * Deafult :
    238      * Ports 0 and 1, line side will be in 10G SFI mode 
    239      * Ports 2 and 3, line side will be in SGMII mode
    240      */
    241     if ((pc->macsec_dev_port == 2) || (pc->macsec_dev_port == 3)) {
    242         fiber_preferred =
    243             soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 0);
    244     } else {
    245         fiber_preferred =
    246             soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 1);
    247     }
    248 
    249     LOG_INFO(BSL_LS_SOC_PHY,
    250              (BSL_META_U(unit,
    251                          "phy_8729_init: "
    252                          "u=%d p=%d type=8729%s fiber_pref=%d\n"),
    253               unit, port, fiber_preferred ? "S" : "", fiber_preferred));
    254 
    255     if ((pc->macsec_dev_port == 2) || (pc->macsec_dev_port == 3)) {
    256         if (fiber_preferred == 0) {
    257             line_mode = BMACSEC_PHY8729_INTF_SGMII;
    258             copper_enable = TRUE;
    259             fiber_enable = FALSE;
    260         } else {
    261             line_mode = BMACSEC_PHY8729_INTF_1000X;
    262             copper_enable = FALSE;
    263             fiber_enable = TRUE;
    264         }
    265     } else {
    266         if (fiber_preferred == 0) {
    267             line_mode = BMACSEC_PHY8729_INTF_SGMII;
    268             copper_enable = TRUE;
    269             fiber_enable = FALSE;
    270         } else {
    271             if ((PHY_OUI(pc->phy_id0, pc->phy_id1) == PHY_BCM8729_OUI) && 
    272                 (PHY_MODEL(pc->phy_id0, pc->phy_id1) == PHY_BCM8729_MODEL)) { 
    273                 xaui_interface = 1;
    274             }
    275             line_mode = BMACSEC_PHY8729_INTF_SFI;
    276             copper_enable = FALSE;
    277             fiber_enable = TRUE;
    278         }
    279     }
    280 
    281     /* Init PHYS and MACs to defaults */
    282     rv = bmacsec_phy8729_init(phy_dev_addr, 1, line_mode, pc->macsec_enable);
    283     if (rv != BMACSEC_E_NONE) {
    284         return SOC_E_FAIL;
    285     }
    286 
    287     pc->copper.enable = copper_enable;
    288     pc->copper.preferred = !fiber_preferred;
    289     pc->copper.autoneg_enable = TRUE;
    290     pc->copper.autoneg_advert = ADVERT_ALL_COPPER;
    291     pc->copper.force_speed = 1000;
    292     pc->copper.force_duplex = TRUE;
    293     pc->copper.master = SOC_PORT_MS_AUTO;
    294     pc->copper.mdix = SOC_PORT_MDIX_AUTO;
    295 
    296     pc->fiber.enable = fiber_enable;
    297     pc->fiber.preferred = fiber_preferred;
    298     pc->fiber.autoneg_enable = FALSE;
    299     pc->fiber.autoneg_advert = ADVERT_ALL_FIBER;
    300     pc->fiber.force_speed = 10000;
    301     pc->fiber.force_duplex = TRUE;
    302     pc->fiber.master = SOC_PORT_MS_NONE;
    303     pc->fiber.mdix = SOC_PORT_MDIX_NORMAL;
    304 
    305     if ((pc->macsec_dev_port == 2) || (pc->macsec_dev_port == 3)) {
    306         pc->interface = SOC_PORT_IF_SGMII;
    307         pc->fiber.force_speed = 1000;
    308     } else {
    309         if (xaui_interface) {
    310             pc->interface = SOC_PORT_IF_XAUI;
    311         } else {
    312             pc->interface = (line_mode == BMACSEC_PHY8729_INTF_SGMII) ? 
    313                                     SOC_PORT_IF_SGMII : SOC_PORT_IF_XFI;
    314         }
    315     }
    316 
    317     /* Initially configure for the preferred medium. */
    318     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
    319     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
    320     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU);
    321     PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
    322     if (pc->fiber.preferred) {
    323         PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
    324     } else {
    325         PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
    326     }
    327     PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45);
    328 
    329     /* Get Requested LED selectors (defaults are hardware defaults) */
    330     pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0);
    331     pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1);
    332     pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3);
    333     pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6);
    334     pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8);
    335     pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0);
    336 
    337     /*
    338      * Some reasonable defaults
    339      */
    340     pc->macsec_switch_fixed = 0;
    341     pc->macsec_switch_fixed_speed = 10000;
    342     pc->macsec_switch_fixed_duplex = 1;
    343     pc->macsec_switch_fixed_pause = 1;
    344     pc->macsec_pause_rx_fwd = 0;
    345     pc->macsec_pause_tx_fwd = 0;
    346     pc->macsec_line_ipg = 0xc;
    347     pc->macsec_switch_ipg = 0xc;
    348 
    349     if (!PHY_COPPER_MODE(unit, port)) {
    350         SOC_IF_ERROR_RETURN
    351             (_phy_8729_medium_config_update(unit, port,
    352                                         PHY_COPPER_MODE(unit, port) ?
    353                                         &pc->copper :
    354                                         &pc->fiber));
    355     }
    356 
    357     rv = soc_macsecphy_init(unit, port, pc, 
    358                             BMACSEC_CORE_BCM8729, bmacsec_io_mmi1_cl45);
    359     if (!SOC_SUCCESS(rv)) {
    360         LOG_ERROR(BSL_LS_SOC_PHY,
    361                   (BSL_META_U(unit,
    362                               "soc_macsecphy_init: MACSEC init for"
    363                               " u=%d p=%d FAILED "), unit, port));
    364     } else {
    365         LOG_INFO(BSL_LS_SOC_PHY,
    366                  (BSL_META_U(unit,
    367                              "soc_macsecphy_init: MACSEC init for"
    368                              " u=%d p=%d SUCCESS "), unit, port));
    369     }
    370     return SOC_E_NONE;
    371 }
    372 
    373 
    374 /*
    375  * Function:
    376  *    phy_8729_link_get
    377  * Purpose:
    378  *    Get layer2 connection status.
    379  * Parameters:
    380  *    unit - StrataSwitch unit #.
    381  *    port - StrataSwitch port #. 
    382  *      link - address of memory to store link up/down state.
    383  * Returns:    
    384  *    SOC_E_NONE
    385  */
    386 
    387 STATIC int
    388 phy_8729_link_get(int unit, soc_port_t port, int *link)
    389 {
    390     phy_ctrl_t    *pc;
    391     int rv = SOC_E_NONE;
    392     bmacsec_dev_addr_t phy_dev_addr;
    393     int bmacsec_link;
    394 
    395     pc    = EXT_PHY_SW_STATE(unit, port);
    396     *link = FALSE;      /* Default return */
    397 
    398     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
    399         return SOC_E_NONE;
    400     }
    401 
    402     if (!pc->fiber.enable && !pc->copper.enable) {
    403         return SOC_E_NONE;
    404     }
    405 
    406     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    407     rv = bmacsec_phy8729_link_get(phy_dev_addr, &bmacsec_link);
    408     if (!BMACSEC_E_SUCCESS(rv)) {
    409         return SOC_E_FAIL;
    410     }
    411     if (bmacsec_link == 1) {
    412         *link = TRUE;
    413     } else {
    414         *link = FALSE;
    415     }
    416 
    417     LOG_VERBOSE(BSL_LS_SOC_PHY,
    418                 (BSL_META_U(unit,
    419                             "phy_8729_link_get: u=%d p=%d mode=%s%s link=%d\n"),
    420                  unit, port,
    421                  PHY_COPPER_MODE(unit, port) ? "C" : "F",
    422                  PHY_FIBER_100FX_MODE(unit, port)? "(100FX)" : "",
    423                  *link));
    424 
    425     return SOC_E_NONE;
    426 }
    427 
    428 
    429 
    430 /*
    431  * Function:
    432  *      phy_8729_enable_set
    433  * Purpose:
    434  *      Enable or disable the physical interface.
    435  * Parameters:
    436  *      unit - StrataSwitch unit #.
    437  *      port - StrataSwitch port #.
    438  *      enable - Boolean, true = enable PHY, false = disable.
    439  * Returns:
    440  *      SOC_E_XXX
    441  */
    442 
    443 STATIC int
    444 phy_8729_enable_set(int unit, soc_port_t port, int enable)
    445 {
    446     phy_ctrl_t    *pc;
    447     int rv = SOC_E_NONE;
    448     bmacsec_dev_addr_t phy_dev_addr;
    449 
    450     pc     = EXT_PHY_SW_STATE(unit, port);
    451 
    452     if (enable) {
    453         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
    454     } else {
    455         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
    456     }
    457 
    458     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    459     rv = bmacsec_phy8729_enable_set(phy_dev_addr, enable);
    460     if(rv != BMACSEC_E_NONE) {
    461         return SOC_E_FAIL;
    462     }
    463 
    464     LOG_INFO(BSL_LS_SOC_PHY,
    465              (BSL_META_U(unit,
    466                          "phy_8729_enable_set: "
    467                          "Power %s fiber medium\n"), (enable) ? "up" : "down"));
    468 
    469     return SOC_E_NONE;
    470 }
    471 
    472 
    473 
    474 
    475 
    476 /*
    477  * Function:
    478  *      phy_8729_duplex_set
    479  * Purpose:
    480  *      Set the current duplex mode
    481  * Parameters:
    482  *      unit - StrataSwitch unit #.
    483  *      port - StrataSwitch port #.
    484  *      duplex - Boolean, true indicates full duplex, false indicates half.
    485  * Returns:
    486  *      SOC_E_NONE
    487  *      SOC_E_UNAVAIL - Half duplex requested, and not supported.
    488  * Notes:
    489  */
    490 STATIC int
    491 phy_8729_duplex_set(int unit, soc_port_t port, int duplex)
    492 {
    493     int                          rv;
    494     phy_ctrl_t                   *pc;
    495     bmacsec_dev_addr_t           phy_dev_addr;
    496     bmacsec_phy8729_duplex_t    bmacsec_duplex;
    497 
    498     pc = EXT_PHY_SW_STATE(unit, port);
    499 
    500     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
    501         return SOC_E_NONE;
    502     }
    503 
    504     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    505     if (duplex) {
    506         bmacsec_duplex = BMACSEC_PHY8729_FULL_DUPLEX;
    507     } else {
    508         bmacsec_duplex = BMACSEC_PHY8729_HALF_DUPLEX;
    509     }
    510     rv = bmacsec_phy8729_duplex_set(phy_dev_addr, bmacsec_duplex);
    511 
    512     if(BMACSEC_E_SUCCESS(rv)) {
    513         pc->copper.force_duplex = duplex;
    514     }
    515 
    516     LOG_INFO(BSL_LS_SOC_PHY,
    517              (BSL_META_U(unit,
    518                          "phy_8729_duplex_set: u=%d p=%d d=%d rv=%d\n"),
    519               unit, port, duplex, rv));
    520     return (SOC_ERROR(rv));
    521 }
    522 
    523 /*
    524  * Function:
    525  *      phy_8729_duplex_get
    526  * Purpose:
    527  *      Get the current operating duplex mode. If autoneg is enabled,
    528  *      then operating mode is returned, otherwise forced mode is returned.
    529  * Parameters:
    530  *      unit - StrataSwitch unit #.
    531  *      port - StrataSwitch port #.
    532  *      duplex - (OUT) Boolean, true indicates full duplex, false
    533  *              indicates half.
    534  * Returns:
    535  *      SOC_E_NONE
    536  * Notes:
    537  *      The duplex is retrieved for the ACTIVE medium.
    538  *      No synchronization performed at this level. Autonegotiation is
    539  *      not manipulated.
    540  */
    541 
    542 STATIC int
    543 phy_8729_duplex_get(int unit, soc_port_t port, int *duplex)
    544 {
    545 
    546     int rv = SOC_E_NONE;
    547     phy_ctrl_t                   *pc;
    548     bmacsec_dev_addr_t phy_dev_addr;
    549     bmacsec_phy8729_duplex_t bmacsec_duplex;
    550 
    551     pc = EXT_PHY_SW_STATE(unit, port);
    552 
    553     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    554     rv = bmacsec_phy8729_duplex_get(phy_dev_addr, &bmacsec_duplex);
    555     if (rv != BMACSEC_E_NONE) {
    556         return SOC_E_FAIL;
    557     }
    558     if (bmacsec_duplex == BMACSEC_PHY8729_FULL_DUPLEX) {
    559         *duplex = TRUE;
    560     } else {
    561         *duplex = FALSE;
    562     }
    563 
    564     LOG_INFO(BSL_LS_SOC_PHY,
    565              (BSL_META_U(unit,
    566                          "phy_8729_duplex_get: u=%d p=%d d=%d rv=%d\n"),
    567               unit, port, *duplex, rv));
    568     return SOC_E_NONE;
    569 }
    570 
    571 
    572 /*
    573  * Function:
    574  *      phy_8729_speed_set
    575  * Purpose:
    576  *      Set PHY speed
    577  * Parameters:
    578  *      unit - StrataSwitch unit #.
    579  *      port - StrataSwitch port #.
    580  *      speed - link speed in Mbps
    581  * Returns:
    582  *      SOC_E_NONE
    583  */
    584 STATIC int
    585 phy_8729_speed_set(int unit, soc_port_t port, int speed)
    586 {
    587     phy_ctrl_t *pc;
    588     phy_ctrl_t  *int_pc;
    589     int            rv; 
    590     bmacsec_dev_addr_t phy_dev_addr;
    591 
    592     pc = EXT_PHY_SW_STATE(unit, port);
    593     int_pc = INT_PHY_SW_STATE(unit, port);
    594     rv = SOC_E_NONE;
    595 
    596     if(PHY_FIBER_MODE(unit, port)) {
    597         if (speed < 1000) {
    598             return SOC_E_UNAVAIL;
    599         }
    600     }
    601     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    602     rv = bmacsec_phy8729_speed_set(phy_dev_addr, speed);
    603 
    604     if(BMACSEC_E_SUCCESS(rv)) {
    605         if (NULL != int_pc) {
    606             PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0);
    607             PHY_SPEED_SET(int_pc->pd, unit, port, speed);
    608         }
    609         if(PHY_COPPER_MODE(unit, port)) {
    610             pc->copper.force_speed = speed;
    611         } else {
    612             if(PHY_FIBER_MODE(unit, port)) {
    613                 pc->fiber.force_speed = speed;
    614             }
    615         }
    616     }
    617     LOG_INFO(BSL_LS_SOC_PHY,
    618              (BSL_META_U(unit,
    619                          "phy_8729_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"),
    620               unit, port, speed, PHY_FIBER_MODE(unit, port), rv));
    621 
    622     return SOC_ERROR(rv);
    623 }
    624 
    625 /*
    626  * Function:
    627  *      phy_8729_speed_get
    628  * Purpose:
    629  *      Get the current operating speed for a 8729 device.
    630  * Parameters:
    631  *      unit - StrataSwitch unit #.
    632  *      port - StrataSwitch port #.
    633  *      speed - (OUT) Speed of the phy
    634  * Returns:
    635  *      SOC_E_NONE
    636  * Notes:
    637  *      The speed is retrieved for the ACTIVE medium.
    638  */
    639 
    640 STATIC int
    641 phy_8729_speed_get(int unit, soc_port_t port, int *speed)
    642 {
    643     int rv = SOC_E_NONE;
    644     bmacsec_dev_addr_t phy_dev_addr;
    645     phy_ctrl_t    *pc;
    646 
    647     pc = EXT_PHY_SW_STATE(unit, port);
    648 
    649     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    650     rv = bmacsec_phy8729_speed_get(phy_dev_addr, speed);
    651 
    652     if(!BMACSEC_E_SUCCESS(rv)) {
    653         LOG_WARN(BSL_LS_SOC_PHY,
    654                  (BSL_META_U(unit,
    655                              "phy_8729_speed_get: u=%d p=%d invalid speed\n"),
    656                   unit, port));
    657     } else {
    658         LOG_INFO(BSL_LS_SOC_PHY,
    659                  (BSL_META_U(unit,
    660                              "phy_8729_speed_get: u=%d p=%d speed=%d"),
    661                   unit, port, *speed));
    662     }
    663 
    664     return SOC_ERROR(rv);
    665 }
    666 
    667 /*
    668  * Function:
    669  *      phy_8729_master_set
    670  * Purpose:
    671  *      Set the current master mode
    672  * Parameters:
    673  *      unit - StrataSwitch unit #.
    674  *      port - StrataSwitch port #.
    675  *      master - SOC_PORT_MS_*
    676  * Returns:
    677  *      SOC_E_XXX
    678  * Notes:
    679  *      The master mode is set only for the ACTIVE medium.
    680  */
    681 STATIC int
    682 phy_8729_master_set(int unit, soc_port_t port, int master)
    683 {
    684     int                  rv;
    685     phy_ctrl_t    *pc;
    686     bmacsec_dev_addr_t phy_dev_addr;
    687 
    688     pc = EXT_PHY_SW_STATE(unit, port);
    689     rv = SOC_E_NONE;
    690 
    691     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    692     rv = bmacsec_phy8729_master_set(phy_dev_addr, master);
    693     if(BMACSEC_E_SUCCESS(rv)) {
    694         pc->copper.master = master;
    695     }
    696 
    697     LOG_INFO(BSL_LS_SOC_PHY,
    698              (BSL_META_U(unit,
    699                          "phy_8729_master_set: u=%d p=%d master=%d fiber=%d rv=%d\n"),
    700               unit, port, master, PHY_FIBER_MODE(unit, port), rv));
    701 
    702     return SOC_ERROR(rv);
    703 }
    704 
    705 
    706 /*
    707  * Function:
    708  *      phy_8729_master_get
    709  * Purpose:
    710  *      Get the current master mode for a 8729 device.
    711  * Parameters:
    712  *      unit - StrataSwitch unit #.
    713  *      port - StrataSwitch port #.
    714  *      master - (OUT) SOC_PORT_MS_*
    715  * Returns:
    716  *      SOC_E_NONE
    717  * Notes:
    718  *      The master mode is retrieved for the ACTIVE medium.
    719  */
    720 
    721 STATIC int
    722 phy_8729_master_get(int unit, soc_port_t port, int *master)
    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     rv = SOC_E_NONE;
    730 
    731     if(PHY_FIBER_MODE(unit, port)) {
    732         *master = SOC_PORT_MS_NONE;
    733         return SOC_E_NONE;
    734     }
    735     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    736     rv = bmacsec_phy8729_master_get(phy_dev_addr, master);
    737 
    738     return SOC_ERROR(rv);
    739 }
    740 
    741 /*
    742  * Function:
    743  *      phy_8729_an_set
    744  * Purpose:
    745  *      Enable or disable auto-negotiation on the specified port.
    746  * Parameters:
    747  *      unit - StrataSwitch unit #.
    748  *      port - StrataSwitch port #.
    749  *      autoneg - Boolean, if true, auto-negotiation is enabled
    750  *              (and/or restarted). If false, autonegotiation is disabled.
    751  * Returns:
    752  *      SOC_E_XXX
    753  * Notes:
    754  *      The autoneg mode is set only for the ACTIVE medium.
    755  */
    756 
    757 STATIC int
    758 phy_8729_an_set(int unit, soc_port_t port, int autoneg)
    759 {
    760     int                 rv;
    761     phy_ctrl_t   *pc;
    762     int autoneg_advert = 0;
    763     bmacsec_dev_addr_t phy_dev_addr;
    764 
    765     pc = EXT_PHY_SW_STATE(unit, port);
    766     rv = SOC_E_NONE;
    767 
    768     if(PHY_COPPER_MODE(unit, port)) {
    769         autoneg_advert = 0;
    770     } else {
    771         if(PHY_FIBER_MODE(unit, port)) {
    772             autoneg_advert = pc->fiber.autoneg_advert;
    773         }
    774     }
    775     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    776     rv = bmacsec_phy8729_an_set(phy_dev_addr, autoneg, autoneg_advert);
    777     if(BMACSEC_E_SUCCESS(rv)) {
    778         if(PHY_COPPER_MODE(unit, port)) {
    779             pc->copper.autoneg_enable = autoneg ? TRUE : FALSE;
    780         } else {
    781             if(PHY_FIBER_MODE(unit, port)) {
    782                 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE;
    783             }
    784         }
    785     }
    786 
    787     LOG_INFO(BSL_LS_SOC_PHY,
    788              (BSL_META_U(unit,
    789                          "phy_8729_an_set: u=%d p=%d autoneg=%d rv=%d\n"),
    790               unit, port, autoneg, rv));
    791     return SOC_ERROR(rv);
    792 }
    793 
    794 /*
    795  * Function:
    796  *      phy_8729_an_get
    797  * Purpose:
    798  *      Get the current auto-negotiation status (enabled/busy).
    799  * Parameters:
    800  *      unit - StrataSwitch unit #.
    801  *      port - StrataSwitch port #.
    802  *      autoneg - (OUT) if true, auto-negotiation is enabled.
    803  *      autoneg_done - (OUT) if true, auto-negotiation is complete. This
    804  *              value is undefined if autoneg == FALSE.
    805  * Returns:
    806  *      SOC_E_XXX
    807  * Notes:
    808  *      The autoneg mode is retrieved for the ACTIVE medium.
    809  */
    810 
    811 STATIC int
    812 phy_8729_an_get(int unit, soc_port_t port,
    813                      int *autoneg, int *autoneg_done)
    814 {
    815     int           rv;
    816     phy_ctrl_t   *pc;
    817     bmacsec_dev_addr_t phy_dev_addr;
    818 
    819     pc = EXT_PHY_SW_STATE(unit, port);
    820 
    821     rv            = SOC_E_NONE;
    822     *autoneg      = FALSE;
    823     *autoneg_done = FALSE;
    824 
    825     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    826     rv = bmacsec_phy8729_an_get(phy_dev_addr, autoneg, autoneg_done);
    827 
    828     return SOC_ERROR(rv);
    829 }
    830 
    831 /*
    832  * Function:
    833  *      phy_8729_lb_set
    834  * Purpose:
    835  *      Set the local PHY loopback mode.
    836  * Parameters:
    837  *      unit - StrataSwitch unit #.
    838  *      port - StrataSwitch port #.
    839  *      loopback - Boolean: true = enable loopback, false = disable.
    840  * Returns:
    841  *      SOC_E_XXX
    842  * Notes:
    843  *      The loopback mode is set only for the ACTIVE medium.
    844  *      No synchronization performed at this level.
    845  */
    846 
    847 STATIC int
    848 phy_8729_lb_set(int unit, soc_port_t port, int enable)
    849 {
    850     int           rv;
    851 #if 0
    852     int           link = 0;
    853     soc_timeout_t  to;
    854 #endif
    855     phy_ctrl_t    *pc;
    856     bmacsec_dev_addr_t phy_dev_addr;
    857 
    858     pc = EXT_PHY_SW_STATE(unit, port);
    859     rv = SOC_E_NONE;
    860 
    861     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    862     rv = bmacsec_phy8729_loopback_set(phy_dev_addr, enable);
    863 
    864     if (rv == BMACSEC_E_NONE) {
    865         /* wait for link up when loopback is enabled */
    866         
    867         if (enable) {
    868             sal_usleep(2000000);
    869 
    870             SOC_IF_ERROR_RETURN
    871                 (phy_8729_linkup(unit, port));
    872         }
    873     }
    874 
    875     LOG_INFO(BSL_LS_SOC_PHY,
    876              (BSL_META_U(unit,
    877                          "phy_8729_lb_set: u=%d p=%d en=%d rv=%d\n"), 
    878               unit, port, enable, rv));
    879 
    880     return SOC_ERROR(rv); 
    881 }
    882 
    883 /*
    884  * Function:
    885  *      phy_8729_lb_get
    886  * Purpose:
    887  *      Get the local PHY loopback mode.
    888  * Parameters:
    889  *      unit - StrataSwitch unit #.
    890  *      port - StrataSwitch port #.
    891  *      loopback - (OUT) Boolean: true = enable loopback, false = disable.
    892  * Returns:
    893  *      SOC_E_XXX
    894  * Notes:
    895  *      The loopback mode is retrieved for the ACTIVE medium.
    896  */
    897 
    898 STATIC int
    899 phy_8729_lb_get(int unit, soc_port_t port, int *enable)
    900 {
    901     int                  rv;
    902     phy_ctrl_t    *pc;
    903     bmacsec_dev_addr_t phy_dev_addr;
    904 
    905     pc = EXT_PHY_SW_STATE(unit, port);
    906     rv = SOC_E_NONE;
    907 
    908     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    909     rv = bmacsec_phy8729_loopback_get(phy_dev_addr, enable);
    910 
    911     return SOC_ERROR(rv); 
    912 }
    913 
    914 
    915 /*
    916  * Function:
    917  *      phy_8729_mdix_set
    918  * Description:
    919  *      Set the Auto-MDIX mode of a port/PHY
    920  * Parameters:
    921  *      unit - Device number
    922  *      port - Port number
    923  *      mode - One of:
    924  *              SOC_PORT_MDIX_AUTO
    925  *                      Enable auto-MDIX when autonegotiation is enabled
    926  *              SOC_PORT_MDIX_FORCE_AUTO
    927  *                      Enable auto-MDIX always
    928  *              SOC_PORT_MDIX_NORMAL
    929  *                      Disable auto-MDIX
    930  *              SOC_PORT_MDIX_XOVER
    931  *                      Disable auto-MDIX, and swap cable pairs
    932  * Return Value:
    933  *      SOC_E_XXX
    934  */
    935 STATIC int
    936 phy_8729_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode)
    937 {
    938 
    939     int         rv;
    940     phy_ctrl_t  *pc;
    941     bmacsec_dev_addr_t phy_dev_addr;
    942     bmacsec_phy8729_port_mdix_t bmacsec_mode;
    943 
    944     pc = EXT_PHY_SW_STATE(unit, port);
    945 
    946     if(PHY_FIBER_MODE(unit, port)) {
    947         if (mode != SOC_PORT_MDIX_NORMAL) {
    948             return SOC_E_UNAVAIL;
    949         }
    950     }
    951     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    952     switch(mode) {
    953     case SOC_PORT_MDIX_AUTO:
    954         bmacsec_mode = BMACSEC_PHY8729_PORT_MDIX_AUTO;
    955         break;
    956     case SOC_PORT_MDIX_FORCE_AUTO:
    957         bmacsec_mode = BMACSEC_PHY8729_PORT_MDIX_FORCE_AUTO;
    958         break;
    959     case SOC_PORT_MDIX_NORMAL:
    960         bmacsec_mode = BMACSEC_PHY8729_PORT_MDIX_NORMAL;
    961         break;
    962     case SOC_PORT_MDIX_XOVER:
    963         bmacsec_mode = BMACSEC_PHY8729_PORT_MDIX_XOVER;
    964         break;
    965     default :
    966         return SOC_E_CONFIG;
    967     }
    968 
    969     rv = bmacsec_phy8729_mdix_set(phy_dev_addr, bmacsec_mode);
    970 
    971     if(BMACSEC_E_SUCCESS(rv)) {
    972         if(PHY_COPPER_MODE(unit, port)) {
    973             pc->copper.mdix = mode;
    974         }
    975     }
    976     return SOC_ERROR(rv);
    977 }        
    978 
    979 /*
    980  * Function:
    981  *      phy_8729_mdix_get
    982  * Description:
    983  *      Get the Auto-MDIX mode of a port/PHY
    984  * Parameters:
    985  *      unit - Device number
    986  *      port - Port number
    987  *      mode - (Out) One of:
    988  *              SOC_PORT_MDIX_AUTO
    989  *                      Enable auto-MDIX when autonegotiation is enabled
    990  *              SOC_PORT_MDIX_FORCE_AUTO
    991  *                      Enable auto-MDIX always
    992  *              SOC_PORT_MDIX_NORMAL
    993  *                      Disable auto-MDIX
    994  *              SOC_PORT_MDIX_XOVER
    995  *                      Disable auto-MDIX, and swap cable pairs
    996  * Return Value:
    997  *      SOC_E_XXX
    998  */
    999 STATIC int
   1000 phy_8729_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode)
   1001 {
   1002     phy_ctrl_t    *pc;
   1003     int            speed;
   1004 
   1005     if (mode == NULL) {
   1006         return SOC_E_PARAM;
   1007     }
   1008 
   1009     pc = EXT_PHY_SW_STATE(unit, port);
   1010 
   1011     if (PHY_COPPER_MODE(unit, port)) {
   1012         SOC_IF_ERROR_RETURN(phy_8729_speed_get(unit, port, &speed));
   1013         if (speed == 1000) {
   1014            *mode = SOC_PORT_MDIX_AUTO;
   1015         } else {
   1016             *mode = pc->copper.mdix;
   1017         }
   1018     } else {
   1019         *mode = SOC_PORT_MDIX_NORMAL;
   1020     }
   1021 
   1022     return SOC_E_NONE;
   1023 }    
   1024 
   1025 /*
   1026  * Function:
   1027  *      phy_8729_mdix_status_get
   1028  * Description:
   1029  *      Get the current MDIX status on a port/PHY
   1030  * Parameters:
   1031  *      unit    - Device number
   1032  *      port    - Port number
   1033  *      status  - (OUT) One of:
   1034  *              SOC_PORT_MDIX_STATUS_NORMAL
   1035  *                      Straight connection
   1036  *              SOC_PORT_MDIX_STATUS_XOVER
   1037  *                      Crossover has been performed
   1038  * Return Value:
   1039  *      SOC_E_XXX
   1040  */
   1041 STATIC int
   1042 phy_8729_mdix_status_get(int unit, soc_port_t port, 
   1043                          soc_port_mdix_status_t *status)
   1044 {
   1045     int         rv;
   1046     phy_ctrl_t    *pc;
   1047 
   1048     bmacsec_dev_addr_t phy_dev_addr;
   1049     bmacsec_phy8729_port_mdix_status_t mdix_status;
   1050 
   1051     if (status == NULL) {
   1052         return SOC_E_PARAM;
   1053     }
   1054 
   1055     pc = EXT_PHY_SW_STATE(unit, port);
   1056     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
   1057     rv = bmacsec_phy8729_mdix_status_get(phy_dev_addr, &mdix_status);
   1058     if(BMACSEC_E_SUCCESS(rv)) {
   1059         if(mdix_status == BMACSEC_PHY8729_PORT_MDIX_STATUS_NORMAL) {
   1060             *status = SOC_PORT_MDIX_STATUS_NORMAL;
   1061         }
   1062         if(mdix_status == BMACSEC_PHY8729_PORT_MDIX_STATUS_XOVER) {
   1063             *status = SOC_PORT_MDIX_STATUS_XOVER;
   1064         }
   1065         return SOC_E_NONE;
   1066     }
   1067 
   1068     return SOC_ERROR(rv);
   1069 }
   1070 
   1071 
   1072 /*
   1073  * Function:
   1074  *      phy_8729_medium_config_set
   1075  * Purpose:
   1076  *      Set the operating parameters that are automatically selected
   1077  *      when medium switches type.
   1078  * Parameters:
   1079  *      unit - StrataSwitch unit #
   1080  *      port - Port number
   1081  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
   1082  *      cfg - Operating parameters
   1083  * Returns:
   1084  *      SOC_E_XXX
   1085  */
   1086 
   1087 STATIC int
   1088 phy_8729_medium_config_set(int unit, soc_port_t port, 
   1089                            soc_port_medium_t  medium,
   1090                            soc_phy_config_t  *cfg)
   1091 {
   1092     phy_ctrl_t    *pc;
   1093 #if 0
   1094     soc_phy_config_t *active_medium;  /* Currently active medium */
   1095     int               medium_update = FALSE;
   1096 #endif
   1097     soc_phy_config_t *change_medium;  /* Requested medium */
   1098     soc_phy_config_t *other_medium;   /* The other medium */
   1099 
   1100     soc_port_mode_t   advert_mask;
   1101 
   1102     if (NULL == cfg) {
   1103         return SOC_E_PARAM;
   1104     }
   1105 
   1106     pc            = EXT_PHY_SW_STATE(unit, port);
   1107 
   1108    switch (medium) {
   1109     case SOC_PORT_MEDIUM_COPPER:
   1110         if (!pc->automedium && !PHY_COPPER_MODE(unit, port)) {
   1111             return SOC_E_UNAVAIL;
   1112         }
   1113         change_medium  = &pc->copper;
   1114         other_medium   = &pc->fiber;
   1115         advert_mask    = ADVERT_ALL_COPPER;
   1116         break;
   1117     case SOC_PORT_MEDIUM_FIBER:
   1118         if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) {
   1119             return SOC_E_UNAVAIL;
   1120         }
   1121         change_medium  = &pc->fiber;
   1122         other_medium   = &pc->copper;
   1123         advert_mask    = ADVERT_ALL_FIBER;
   1124         break;
   1125     default:
   1126         return SOC_E_PARAM;
   1127     }
   1128 
   1129     /*
   1130      * Changes take effect immediately if the target medium is active or
   1131      * the preferred medium changes.
   1132      */
   1133 #if 0
   1134     if (change_medium->enable != cfg->enable) {
   1135         medium_update = TRUE;
   1136     }
   1137 #endif
   1138     if (change_medium->preferred != cfg->preferred) {
   1139         /* Make sure that only one medium is preferred */
   1140         other_medium->preferred = !cfg->preferred;
   1141 #if 0
   1142         medium_update = TRUE;
   1143 #endif
   1144     }
   1145 
   1146     sal_memcpy(change_medium, cfg, sizeof(*change_medium));
   1147     change_medium->autoneg_advert &= advert_mask;
   1148 
   1149 #if 0
   1150     if (medium_update) {
   1151         /* The new configuration may cause medium change. Check
   1152          * and update medium.
   1153          */
   1154         SOC_IF_ERROR_RETURN
   1155             (_phy_8729_medium_change(unit, port, TRUE, medium));
   1156     } else {
   1157         active_medium = (PHY_COPPER_MODE(unit, port)) ?  
   1158                             &pc->copper : &pc->fiber;
   1159         if (active_medium == change_medium) {
   1160             /* If the medium to update is active, update the configuration */
   1161             SOC_IF_ERROR_RETURN
   1162                 (_phy_8729_medium_config_update(unit, port, change_medium));
   1163         }
   1164     }
   1165 #endif
   1166     return SOC_E_NONE;
   1167 }
   1168 
   1169 /*
   1170  * Function:
   1171  *      phy_8729_medium_config_get
   1172  * Purpose:
   1173  *      Get the operating parameters that are automatically selected
   1174  *      when medium switches type.
   1175  * Parameters:
   1176  *      unit - StrataSwitch unit #
   1177  *      port - Port number
   1178  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
   1179  *      cfg - (OUT) Operating parameters
   1180  * Returns:
   1181  *      SOC_E_XXX
   1182  */
   1183 
   1184 STATIC int
   1185 phy_8729_medium_config_get(int unit, soc_port_t port, 
   1186                            soc_port_medium_t medium,
   1187                            soc_phy_config_t *cfg)
   1188 {
   1189     int            rv;
   1190     phy_ctrl_t    *pc;
   1191 
   1192     pc = EXT_PHY_SW_STATE(unit, port);
   1193     rv = SOC_E_NONE;
   1194 
   1195     switch (medium) {
   1196     case SOC_PORT_MEDIUM_COPPER:
   1197         if (pc->automedium || PHY_COPPER_MODE(unit, port)) {
   1198             sal_memcpy(cfg, &pc->copper, sizeof (*cfg));
   1199         } else {
   1200             rv = SOC_E_UNAVAIL;
   1201         }
   1202         break;
   1203     case SOC_PORT_MEDIUM_FIBER:
   1204         if (pc->automedium || PHY_FIBER_MODE(unit, port)) {
   1205             sal_memcpy(cfg, &pc->fiber, sizeof (*cfg));
   1206         } else {
   1207             rv = SOC_E_UNAVAIL;
   1208         }
   1209         break;
   1210     default:
   1211         rv = SOC_E_PARAM;
   1212         break;
   1213     }
   1214 
   1215     return rv;
   1216 }
   1217 
   1218 /*
   1219  * Function:
   1220  *      phy_8729_ability_advert_set
   1221  * Purpose:
   1222  *      Set the current advertisement for auto-negotiation.
   1223  * Parameters:
   1224  *      unit - StrataSwitch unit #.
   1225  *      port - StrataSwitch port #.
   1226  *      mode - Port mode mask indicating supported options/speeds.
   1227  * Returns:
   1228  *      SOC_E_XXX
   1229  * Notes:
   1230  *      The advertisement is set only for the ACTIVE medium.
   1231  *      No synchronization performed at this level.
   1232  */
   1233 STATIC int
   1234 phy_8729_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability)
   1235 {
   1236     int        rv;
   1237     phy_ctrl_t *pc;
   1238     bmacsec_phy8729_port_ability_t local_ability;
   1239     bmacsec_dev_addr_t phy_dev_addr;
   1240 
   1241     pc = EXT_PHY_SW_STATE(unit, port);
   1242 
   1243     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1244         return SOC_E_NONE;
   1245     }
   1246 
   1247     if (NULL == ability) {
   1248         return (SOC_E_PARAM);
   1249     }
   1250 
   1251     if (PHY_COPPER_MODE(unit, port)) {
   1252         pc->copper.advert_ability = *ability;
   1253     } else {
   1254         pc->fiber.advert_ability = *ability;
   1255     }
   1256 
   1257     local_ability = 0;
   1258     if(ability->speed_half_duplex & SOC_PA_SPEED_10MB) {
   1259         local_ability |= BMACSEC_PHY8729_PA_10MB_HD;
   1260     }
   1261     if(ability->speed_half_duplex & SOC_PA_SPEED_100MB) {
   1262         local_ability |= BMACSEC_PHY8729_PA_100MB_HD;
   1263     }
   1264     if(ability->speed_full_duplex & SOC_PA_SPEED_10MB) {
   1265         local_ability |= BMACSEC_PHY8729_PA_10MB_FD;
   1266     }
   1267     if(ability->speed_full_duplex & SOC_PA_SPEED_100MB) {
   1268         local_ability |= BMACSEC_PHY8729_PA_100MB_FD;
   1269     }
   1270     if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) {
   1271         local_ability |= BMACSEC_PHY8729_PA_1000MB_FD;
   1272     }
   1273     if(ability->speed_full_duplex & SOC_PA_SPEED_10GB) {
   1274         local_ability |= BMACSEC_PHY8729_PA_10000MB_FD;
   1275     }
   1276 
   1277     if(ability->pause & SOC_PA_PAUSE_TX) {
   1278         local_ability |= BMACSEC_PHY8729_PA_PAUSE_TX;
   1279     }
   1280     if(ability->pause & SOC_PA_PAUSE_RX) {
   1281         local_ability |= BMACSEC_PHY8729_PA_PAUSE_RX;
   1282     }
   1283     if(ability->pause & SOC_PA_PAUSE_ASYMM) {
   1284         local_ability |= BMACSEC_PHY8729_PA_PAUSE_ASYMM;
   1285     }
   1286 
   1287 
   1288     if(ability->loopback & SOC_PA_LB_NONE) {
   1289         local_ability |= BMACSEC_PHY8729_PA_LB_NONE;
   1290     }
   1291     if(ability->loopback & SOC_PA_LB_PHY) {
   1292         local_ability |= BMACSEC_PHY8729_PA_LB_PHY;
   1293     }
   1294     if(ability->flags & SOC_PA_AUTONEG) {
   1295         local_ability |= BMACSEC_PHY8729_PA_AN;
   1296     }
   1297 
   1298     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1299     rv = bmacsec_phy8729_ability_advert_set(phy_dev_addr, local_ability);
   1300 
   1301 
   1302     return SOC_ERROR(rv);
   1303 }
   1304 
   1305 /*
   1306  * Function:
   1307  *      phy_8729_ability_advert_get
   1308  * Purpose:
   1309  *      Get the current advertisement for auto-negotiation.
   1310  * Parameters:
   1311  *      unit - StrataSwitch unit #.
   1312  *      port - StrataSwitch port #.
   1313  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1314  * Returns:
   1315  *      SOC_E_XXX
   1316  * Notes:
   1317  *      The advertisement is retrieved for the ACTIVE medium.
   1318  *      No synchronization performed at this level.
   1319  */
   1320 STATIC int
   1321 phy_8729_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   1322 {
   1323     phy_ctrl_t      *pc;
   1324     int        rv;
   1325     bmacsec_phy8729_port_ability_t local_ability;
   1326     bmacsec_dev_addr_t phy_dev_addr;
   1327 
   1328     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1329         return SOC_E_NONE;
   1330     }
   1331 
   1332     if (NULL == ability) {
   1333         return (SOC_E_PARAM);
   1334     }
   1335 
   1336     pc = EXT_PHY_SW_STATE(unit, port);
   1337 
   1338     local_ability = 0;
   1339 
   1340     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1341     rv = bmacsec_phy8729_ability_advert_get(phy_dev_addr, &local_ability);
   1342     if (rv != BMACSEC_E_NONE) {
   1343         return SOC_E_FAIL;
   1344     }
   1345 
   1346     if(local_ability & BMACSEC_PHY8729_PA_10MB_HD) {
   1347         ability->speed_half_duplex |= SOC_PA_SPEED_10MB;
   1348     }
   1349     if(local_ability & BMACSEC_PHY8729_PA_100MB_HD) {
   1350         ability->speed_half_duplex |= SOC_PA_SPEED_100MB;
   1351     }
   1352     if(local_ability & BMACSEC_PHY8729_PA_10MB_FD) {
   1353         ability->speed_full_duplex |= SOC_PA_SPEED_10MB;
   1354     }
   1355     if(local_ability & BMACSEC_PHY8729_PA_100MB_FD) {
   1356         ability->speed_full_duplex |= SOC_PA_SPEED_100MB;
   1357     }
   1358     if(local_ability & BMACSEC_PHY8729_PA_1000MB_FD) {
   1359         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1360     }
   1361     if(local_ability & BMACSEC_PHY8729_PA_10000MB_FD) {
   1362         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1363     }
   1364 
   1365     if(local_ability & BMACSEC_PHY8729_PA_PAUSE_TX) {
   1366         ability->pause |= SOC_PA_PAUSE_TX;
   1367     }
   1368     if(local_ability & BMACSEC_PHY8729_PA_PAUSE_RX) {
   1369         ability->pause |= SOC_PA_PAUSE_RX;
   1370     }
   1371     if(local_ability & BMACSEC_PHY8729_PA_PAUSE_ASYMM) {
   1372         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1373     }
   1374 
   1375 
   1376     if(local_ability & BMACSEC_PHY8729_PA_LB_NONE) {
   1377         ability->loopback |= SOC_PA_LB_NONE;
   1378     }
   1379     if(local_ability & BMACSEC_PHY8729_PA_LB_PHY) {
   1380         ability->loopback |= SOC_PA_LB_PHY;
   1381     }
   1382     if(local_ability & BMACSEC_PHY8729_PA_AN) {
   1383         ability->flags = SOC_PA_AUTONEG;
   1384     }
   1385 
   1386     return SOC_E_NONE;
   1387 }
   1388 
   1389 /*
   1390  * Function:
   1391  *      phy_8729_ability_remote_get
   1392  * Purpose:
   1393  *      Get the current remote advertisement for auto-negotiation.
   1394  * Parameters:
   1395  *      unit - StrataSwitch unit #.
   1396  *      port - StrataSwitch port #.
   1397  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1398  * Returns:
   1399  *      SOC_E_XXX
   1400  * Notes:
   1401  *      The advertisement is retrieved for the ACTIVE medium.
   1402  *      No synchronization performed at this level.
   1403  */
   1404 STATIC int
   1405 phy_8729_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   1406 {
   1407     phy_ctrl_t      *pc;
   1408     int        rv;
   1409     bmacsec_phy8729_port_ability_t remote_ability;
   1410     bmacsec_dev_addr_t phy_dev_addr;
   1411 
   1412     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1413         return SOC_E_NONE;
   1414     }
   1415 
   1416     if (NULL == ability) {
   1417         return (SOC_E_PARAM);
   1418     }
   1419 
   1420     pc = EXT_PHY_SW_STATE(unit, port);
   1421 
   1422     remote_ability = 0;
   1423 
   1424     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1425     rv = bmacsec_phy8729_remote_ability_advert_get(phy_dev_addr,
   1426                                                    &remote_ability);
   1427     if (rv != BMACSEC_E_NONE) {
   1428         return SOC_E_FAIL;
   1429     }
   1430 
   1431     if(remote_ability & BMACSEC_PHY8729_PA_10MB_HD) {
   1432         ability->speed_half_duplex |= SOC_PA_SPEED_10MB;
   1433     }
   1434     if(remote_ability & BMACSEC_PHY8729_PA_100MB_HD) {
   1435         ability->speed_half_duplex |= SOC_PA_SPEED_100MB;
   1436     }
   1437     if(remote_ability & BMACSEC_PHY8729_PA_10MB_FD) {
   1438         ability->speed_full_duplex |= SOC_PA_SPEED_10MB;
   1439     }
   1440     if(remote_ability & BMACSEC_PHY8729_PA_100MB_FD) {
   1441         ability->speed_full_duplex |= SOC_PA_SPEED_100MB;
   1442     }
   1443     if(remote_ability & BMACSEC_PHY8729_PA_1000MB_FD) {
   1444         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1445     }
   1446     if(remote_ability & BMACSEC_PHY8729_PA_10000MB_FD) {
   1447         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1448     }
   1449 
   1450     if(remote_ability & BMACSEC_PHY8729_PA_PAUSE_TX) {
   1451         ability->pause |= SOC_PA_PAUSE_TX;
   1452     }
   1453     if(remote_ability & BMACSEC_PHY8729_PA_PAUSE_RX) {
   1454         ability->pause |= SOC_PA_PAUSE_RX;
   1455     }
   1456     if(remote_ability & BMACSEC_PHY8729_PA_PAUSE_ASYMM) {
   1457         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1458     }
   1459 
   1460 
   1461     if(remote_ability & BMACSEC_PHY8729_PA_LB_NONE) {
   1462         ability->loopback |= SOC_PA_LB_NONE;
   1463     }
   1464     if(remote_ability & BMACSEC_PHY8729_PA_LB_PHY) {
   1465         ability->loopback |= SOC_PA_LB_PHY;
   1466     }
   1467     if(remote_ability & BMACSEC_PHY8729_PA_AN) {
   1468         ability->flags = SOC_PA_AUTONEG;
   1469     }
   1470 
   1471     return SOC_E_NONE;
   1472 }
   1473 
   1474 
   1475 
   1476 /*
   1477  * Function:
   1478  *      phy_8729_ability_local_get
   1479  * Purpose:
   1480  *      Get local abilities 
   1481  * Parameters:
   1482  *      unit - StrataSwitch unit #.
   1483  *      port - StrataSwitch port #.
   1484  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1485  * Returns:
   1486  *      SOC_E_NONE
   1487  * Notes:
   1488  *      The ability is retrieved only for the ACTIVE medium.
   1489  */
   1490 
   1491 STATIC int
   1492 phy_8729_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1493 {
   1494     int         rv = SOC_E_NONE;
   1495     phy_ctrl_t *pc;
   1496     bmacsec_phy8729_port_ability_t local_ability = 0;
   1497     bmacsec_dev_addr_t phy_dev_addr;
   1498 
   1499     if (NULL == ability) {
   1500         return SOC_E_PARAM;
   1501     }
   1502 
   1503     pc = EXT_PHY_SW_STATE(unit, port);
   1504 
   1505     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1506     rv = bmacsec_phy8729_ability_local_get(phy_dev_addr, &local_ability);
   1507     if (rv != BMACSEC_E_NONE) {
   1508         return SOC_E_FAIL;
   1509     }
   1510 
   1511     if(local_ability & BMACSEC_PHY8729_PA_10MB_HD) {
   1512         ability->speed_half_duplex |= SOC_PA_SPEED_10MB;
   1513     }
   1514     if(local_ability & BMACSEC_PHY8729_PA_100MB_HD) {
   1515         ability->speed_half_duplex |= SOC_PA_SPEED_100MB;
   1516     }
   1517     if(local_ability & BMACSEC_PHY8729_PA_10MB_FD) {
   1518         ability->speed_full_duplex |= SOC_PA_SPEED_10MB;
   1519     }
   1520     if(local_ability & BMACSEC_PHY8729_PA_100MB_FD) {
   1521         ability->speed_full_duplex |= SOC_PA_SPEED_100MB;
   1522     }
   1523     if(local_ability & BMACSEC_PHY8729_PA_1000MB_FD) {
   1524         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1525     }
   1526     if(local_ability & BMACSEC_PHY8729_PA_10000MB_FD) {
   1527         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1528     }
   1529 
   1530     if(local_ability & BMACSEC_PHY8729_PA_PAUSE_TX) {
   1531         ability->pause |= SOC_PA_PAUSE_TX;
   1532     }
   1533     if(local_ability & BMACSEC_PHY8729_PA_PAUSE_RX) {
   1534         ability->pause |= SOC_PA_PAUSE_RX;
   1535     }
   1536     if(local_ability & BMACSEC_PHY8729_PA_PAUSE_ASYMM) {
   1537         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1538     }
   1539 
   1540 
   1541     if(local_ability & BMACSEC_PHY8729_PA_LB_NONE) {
   1542         ability->loopback |= SOC_PA_LB_NONE;
   1543     }
   1544     if(local_ability & BMACSEC_PHY8729_PA_LB_PHY) {
   1545         ability->loopback |= SOC_PA_LB_PHY;
   1546     }
   1547     if(local_ability & BMACSEC_PHY8729_PA_AN) {
   1548         ability->flags = SOC_PA_AUTONEG;
   1549     }
   1550 
   1551     return SOC_E_NONE;
   1552 }
   1553 
   1554 /*
   1555  * Function:
   1556  *      phy_8729_firmware_set
   1557  * Purpose:
   1558  *      program the given firmware into the SPI-ROM
   1559  * Parameters:
   1560  *      unit - StrataSwitch unit #.
   1561  *      port - StrataSwitch port #.
   1562  *      offset - offset to the data stream
   1563  *      array  - the given data
   1564  *      datalen- the data length
   1565  * Returns:
   1566  *      SOC_E_NONE
   1567  */
   1568 
   1569 STATIC int
   1570 phy_8729_firmware_set(int unit, int port, int offset, uint8 *data,int len)
   1571 {
   1572     int            rv;
   1573     phy_ctrl_t *pc;
   1574     bmacsec_dev_addr_t phy_dev_addr;
   1575 
   1576     pc = EXT_PHY_SW_STATE(unit, port);
   1577     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1578 
   1579     rv = bmacsec_phy8729_spi_firmware_update(phy_dev_addr, data, len);
   1580     if (rv != BMACSEC_E_NONE) {
   1581             LOG_WARN(BSL_LS_SOC_PHY,
   1582                      (BSL_META_U(unit,
   1583                                  "PHY8729 firmware upgrade possibly failed:"
   1584                                  "u=%d p=%d\n"), unit, port));
   1585         return (SOC_E_FAIL);
   1586     }
   1587     LOG_INFO(BSL_LS_SOC_PHY,
   1588              (BSL_META_U(unit,
   1589                          "PHY8729 firmware upgrade successful:"
   1590                          "u=%d p=%d\n"), unit, port));
   1591 
   1592     return SOC_E_NONE;
   1593 }
   1594 
   1595 /*
   1596  * Function:
   1597  *      phy_8729_medium_status
   1598  * Purpose:
   1599  *      Indicate the current active medium
   1600  * Parameters:
   1601  *      unit - StrataSwitch unit #.
   1602  *      port - StrataSwitch port #.
   1603  *      medium - (OUT) One of:
   1604  *              SOC_PORT_MEDIUM_COPPER
   1605  *              SOC_PORT_MEDIUM_XAUI
   1606  * Returns:
   1607  *      SOC_E_NONE
   1608  */
   1609 
   1610 STATIC int
   1611 phy_8729_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium)
   1612 {
   1613     if (PHY_COPPER_MODE(unit, port)) {
   1614         *medium = SOC_PORT_MEDIUM_COPPER;
   1615     } else {
   1616         *medium = SOC_PORT_MEDIUM_FIBER;
   1617     }
   1618 
   1619     return SOC_E_NONE;
   1620 }
   1621 
   1622 
   1623 /*
   1624  * Function:
   1625  *      phy_8729_control_set
   1626  * Purpose:
   1627  *      Configure PHY device specific control fucntion.
   1628  * Parameters:
   1629  *      unit  - StrataSwitch unit #.
   1630  *      port  - StrataSwitch port #.
   1631  *      type  - Control to update
   1632  *      value - New setting for the control
   1633  * Returns:    
   1634  *      SOC_E_NONE
   1635  */
   1636 STATIC int
   1637 phy_8729_control_set(int unit, soc_port_t port,
   1638                      soc_phy_control_t type, uint32 value)
   1639 {
   1640     int rv, pause_fwd = 0, line_speed, line_duplex, line_pause=1;
   1641     phy_ctrl_t    *pc;
   1642     bmacsec_dev_addr_t phy_dev_addr;
   1643     bmacsec_phy8729_intf_t line_mode;
   1644 
   1645     rv = BMACSEC_E_NONE;    
   1646     pc = EXT_PHY_SW_STATE(unit, port);
   1647 
   1648     if (pc->macsec_enable != 1) {
   1649         return SOC_E_UNAVAIL;
   1650     }
   1651 
   1652     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
   1653     rv = bmacsec_phy8729_line_intf_get(phy_dev_addr,
   1654                                        pc->macsec_dev_port, &line_mode);
   1655     if (rv != BMACSEC_E_NONE) {
   1656         return SOC_ERROR(rv);
   1657     }
   1658     switch(type) {
   1659         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED:
   1660             pc->macsec_switch_fixed = value;
   1661             if(value) {
   1662                 rv = bmacsec_phy8729_switch_side_set_params(phy_dev_addr, 
   1663                                 BMACSEC_BCM8729_SWITCH_FIXED, 
   1664                                 pc->macsec_switch_fixed_speed,
   1665                                 pc->macsec_switch_fixed_duplex,
   1666                                 pc->macsec_switch_fixed_pause);
   1667             } else { /* Switch side follows line side */
   1668                 SOC_IF_ERROR_RETURN
   1669                     (phy_8729_speed_get(unit, port, &line_speed));
   1670                 SOC_IF_ERROR_RETURN
   1671                     (phy_8729_duplex_get(unit, port, &line_duplex));
   1672 #if 0 
   1673                 SOC_IF_ERROR_RETURN
   1674                     (phy_8729_pause_get(unit, port, &line_pause));
   1675 #endif
   1676                 rv = bmacsec_phy8729_switch_side_set_params(phy_dev_addr, 
   1677                                 BMACSEC_BCM8729_SWITCH_FOLLOWS_LINE, 
   1678                                 line_speed, line_duplex, line_pause);
   1679             }
   1680             break;
   1681         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED:
   1682             /* Switch fixed speed is allowed only to be 1000Mbps */
   1683             if (pc->macsec_dev_port > 2) {
   1684                 if (value != 1000) {
   1685                     return SOC_E_CONFIG;
   1686                 }
   1687             } else {
   1688                 if ((line_mode == BMACSEC_PHY8729_INTF_SGMII) || 
   1689                     (line_mode == BMACSEC_PHY8729_INTF_1000X)) {
   1690                     if (value != 1000) {
   1691                         return SOC_E_CONFIG;
   1692                     }
   1693                 } else {
   1694                     if (value != 10000) {
   1695                         return SOC_E_CONFIG;
   1696                     }
   1697                 }
   1698             } 
   1699 
   1700             if(pc->macsec_switch_fixed_speed != value) {
   1701                 pc->macsec_switch_fixed_speed = value;
   1702             }
   1703             break;
   1704         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX:
   1705             /* Switch fixed Duplex is allowed only to be Full Duplex mode */
   1706             if (value != 1) {
   1707                 return SOC_E_CONFIG;
   1708             }
   1709             if(pc->macsec_switch_fixed_duplex != value) {
   1710                 pc->macsec_switch_fixed_duplex = value;
   1711             }
   1712             break;
   1713         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE:
   1714             if(pc->macsec_switch_fixed_pause != value) {
   1715                 pc->macsec_switch_fixed_pause = value;
   1716             }
   1717             break;
   1718         case SOC_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD:
   1719             pc->macsec_pause_rx_fwd = value;
   1720             pause_fwd = (value == 1) ? 1 : 0;
   1721 
   1722             rv = bmacsec_phy8729_line_side_pause_forward(phy_dev_addr,
   1723                                                          pause_fwd);
   1724             if (rv == BMACSEC_E_NONE) {
   1725                 rv = bmacsec_phy8729_switch_side_pause_forward(
   1726                                                      phy_dev_addr, pause_fwd);
   1727             }
   1728             break;
   1729         case SOC_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD:
   1730             pc->macsec_pause_tx_fwd = value;
   1731             pause_fwd = (value == 1) ? 1 : 0;
   1732 
   1733             rv = bmacsec_phy8729_line_side_pause_forward(phy_dev_addr,
   1734                                                           pause_fwd);
   1735             if (rv == BMACSEC_E_NONE) {
   1736                 rv = bmacsec_phy8729_switch_side_pause_forward(phy_dev_addr,
   1737                                                                 pause_fwd);
   1738             }
   1739             break;
   1740         case SOC_PHY_CONTROL_MACSEC_LINE_IPG:
   1741             pc->macsec_line_ipg = value;
   1742             rv = bmacsec_phy8729_line_side_ipg_set(phy_dev_addr, value);
   1743             break;
   1744         case SOC_PHY_CONTROL_MACSEC_SWITCH_IPG:
   1745             pc->macsec_switch_ipg = value;
   1746             rv = bmacsec_phy8729_switch_side_ipg_set(phy_dev_addr, value);
   1747             break;
   1748         default:
   1749             rv = SOC_E_UNAVAIL;
   1750             break;
   1751     }
   1752 
   1753     return SOC_ERROR(rv);;
   1754 }
   1755 
   1756 /*
   1757  * Function:
   1758  *      phy_8729_control_get
   1759  * Purpose:
   1760  *      Get current control settign of the PHY.
   1761  * Parameters:
   1762  *      unit  - StrataSwitch unit #.
   1763  *      port  - StrataSwitch port #.
   1764  *      type  - Control to update
   1765  *      value - (OUT)Current setting for the control
   1766  * Returns:
   1767  *      SOC_E_NONE
   1768  */
   1769 STATIC int 
   1770 phy_8729_control_get(int unit, soc_port_t port,
   1771                      soc_phy_control_t type, uint32 *value)
   1772 {
   1773     int rv;
   1774     phy_ctrl_t    *pc;
   1775 
   1776     pc = EXT_PHY_SW_STATE(unit, port);
   1777 
   1778     if (pc->macsec_enable != 1) {
   1779         return SOC_E_UNAVAIL;
   1780     }
   1781 
   1782     if (NULL == value) {
   1783         return SOC_E_PARAM;
   1784     }
   1785 
   1786     if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) {
   1787         return SOC_E_PARAM;
   1788     }
   1789 
   1790     rv = SOC_E_NONE;
   1791     switch(type) {
   1792         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED:
   1793             *value = pc->macsec_switch_fixed;
   1794             break;
   1795         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED:
   1796             *value = pc->macsec_switch_fixed_speed;
   1797             break;
   1798         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX:
   1799             *value = pc->macsec_switch_fixed_duplex;
   1800             break;
   1801         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE:
   1802             *value = pc->macsec_switch_fixed_pause;
   1803             break;
   1804         case SOC_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD:
   1805             *value = pc->macsec_pause_rx_fwd;
   1806             break;
   1807         case SOC_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD:
   1808             *value = pc->macsec_pause_tx_fwd;
   1809             break;
   1810         case SOC_PHY_CONTROL_MACSEC_LINE_IPG:
   1811             *value = pc->macsec_line_ipg;
   1812             break;
   1813         case SOC_PHY_CONTROL_MACSEC_SWITCH_IPG:
   1814             *value = pc->macsec_switch_ipg;
   1815             break;
   1816         default:
   1817             rv = SOC_E_UNAVAIL;
   1818             break; 
   1819     }
   1820     return rv;
   1821 }
   1822 
   1823 /*
   1824  * Function:
   1825  *      phy_8729_linkup
   1826  * Purpose:
   1827  *      Link up handler
   1828  * Parameters:
   1829  *      unit  - StrataSwitch unit #.
   1830  *      port  - StrataSwitch port #.
   1831  * Returns:
   1832  *      SOC_E_NONE
   1833  */
   1834 STATIC int 
   1835 phy_8729_linkup(int unit, soc_port_t port)
   1836 {
   1837     int rv = SOC_E_NONE;
   1838     phy_ctrl_t    *pc;
   1839     bmacsec_dev_addr_t phy_dev_addr;
   1840     pc = EXT_PHY_SW_STATE(unit, port);
   1841 
   1842     if (pc->macsec_enable != 1) {
   1843         return SOC_E_NONE;
   1844     }
   1845 
   1846     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1847 
   1848     rv = bmacsec_8729_phy_linkup(phy_dev_addr, pc->macsec_enable);
   1849 
   1850     return SOC_ERROR(rv);
   1851 }
   1852 
   1853 /*
   1854  * Function:
   1855  *      phy_8729_interface_get
   1856  * Purpose:
   1857  *      Get interface on a given port.
   1858  * Parameters:
   1859  *      unit  - StrataSwitch unit #.
   1860  *      port  - StrataSwitch port #.
   1861  *      pif   - Interface.
   1862  * Returns:
   1863  *      SOC_E_NONE
   1864  */
   1865 STATIC int
   1866 phy_8729_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   1867 {
   1868     phy_ctrl_t     *pc;
   1869 
   1870     pc     = EXT_PHY_SW_STATE(unit, port);
   1871     if ((pc->macsec_dev_port == 2) || (pc->macsec_dev_port == 3)) {
   1872         *pif = SOC_PORT_IF_SGMII;
   1873     } else {
   1874         if (pc->phy_id1 == PHY_ID1_8729) {
   1875             *pif = SOC_PORT_IF_XAUI;
   1876         } else {
   1877             *pif = PHY_COPPER_MODE(unit, port) ? SOC_PORT_IF_SGMII : SOC_PORT_IF_XFI;
   1878         }
   1879     }
   1880     return SOC_E_NONE;
   1881 }
   1882 
   1883 
   1884 
   1885 
   1886 /*
   1887  * Variable:
   1888  *    phy_8729_drv
   1889  * Purpose:
   1890  *    Phy Driver for BCM8729 MACSEC PHY
   1891  */
   1892 
   1893 phy_driver_t phy_8729drv_gexe = {
   1894     "8729 1G/10-Gigabit PHY Driver",
   1895     phy_8729_init,        /* Init */
   1896     phy_null_reset,       /* Reset */
   1897     phy_8729_link_get,    /* Link get   */
   1898     phy_8729_enable_set,  /* Enable set */
   1899     phy_null_enable_get,  /* Enable get */
   1900     phy_8729_duplex_set,  /* Duplex set */
   1901     phy_8729_duplex_get,  /* Duplex get */
   1902     phy_8729_speed_set,   /* Speed set  */
   1903     phy_8729_speed_get,   /* Speed get  */
   1904     phy_8729_master_set,  /* Master set */
   1905     phy_8729_master_get,  /* Master get */
   1906     phy_8729_an_set,      /* ANA set */
   1907     phy_8729_an_get,      /* ANA get */
   1908     NULL,                 /* Local Advert set, deprecated */
   1909     NULL,                 /* Local Advert get, deprecated */
   1910     NULL,                 /* Remote Advert get, deprecated */
   1911     phy_8729_lb_set,      /* PHY loopback set */
   1912     phy_8729_lb_get,      /* PHY loopback set */
   1913     phy_null_interface_set, /* IO Interface set */
   1914     phy_8729_interface_get, /* IO Interface get */
   1915     NULL,                   /* pd_ability, deprecated */
   1916     phy_8729_linkup,
   1917     NULL,
   1918     phy_8729_mdix_set,
   1919     phy_8729_mdix_get,
   1920     phy_8729_mdix_status_get,
   1921     phy_8729_medium_config_set, /* medium config setting set */
   1922     phy_8729_medium_config_get, /* medium config setting get */
   1923     phy_8729_medium_status,        /* active medium */
   1924     NULL,                    /* phy_cable_diag  */
   1925     NULL,                    /* phy_link_change */
   1926     phy_8729_control_set,    /* phy_control_set */
   1927     phy_8729_control_get,    /* phy_control_get */
   1928     NULL,                    /* phy_reg_read */
   1929     NULL,                    /* phy_reg_write */
   1930     NULL,                    /* phy_reg_modify */
   1931     NULL,                    /* phy_notify */
   1932     NULL,          /* pd_probe  */
   1933     phy_8729_ability_advert_set,  /* pd_ability_advert_set */
   1934     phy_8729_ability_advert_get,  /* pd_ability_advert_get */
   1935     phy_8729_ability_remote_get,  /* pd_ability_remote_get */
   1936     phy_8729_ability_local_get,   /* pd_ability_local_get  */
   1937     phy_8729_firmware_set
   1938 };
   1939 
   1940 #else /* INCLUDE_PHY_8729 */
   1941 int _phy_8729_not_empty;
   1942 #endif /* INCLUDE_PHY_8729 */
   1943 #endif /* INCLUDE_MACSEC */