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

phy84756.c (64621B)


      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:        phy84756.c
     11  * Purpose:     SDK PHY driver for BCM84756 (MACSec)
     12  *
     13  * Supported BCM546X Family of PHY devices:
     14  *
     15  *      Device  Ports   Media                           MAC Interface
     16  *      84756    4       2 10G SFP+, 2 1G SFP            XFI
     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 #if defined(INCLUDE_MACSEC)
     43 #if defined(INCLUDE_PHY_84756)
     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 "phy84756.h"
     51 #include "phy84756_i2c.h"
     52 
     53 #if defined(INCLUDE_MACSEC)
     54 #include <soc/macsecphy.h>
     55 #include <bmacsec.h>
     56 #include <bmacsec_io.h>
     57 #endif
     58 
     59 #if defined(INCLUDE_FCMAP)
     60 #include <soc/fcmapphy.h>
     61 #include <bfcmap.h>
     62 #include <bfcmap_io.h>
     63 #endif
     64 
     65 #define ADVERT_ALL_COPPER \
     66         (SOC_PA_PAUSE | SOC_PA_SPEED_10MB | \
     67          SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB)
     68 
     69 #define ADVERT_ALL_FIBER \
     70         (SOC_PA_PAUSE | SOC_PA_SPEED_1000MB) 
     71 
     72 #define ADVERT_ALL_10GFIBER \
     73         (SOC_PA_PAUSE | SOC_PA_SPEED_10GB) 
     74 
     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 PHY84756_REG_READ(_unit, _phy_ctrl, _addr, _val) \
    101             READ_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val))
    102 
    103 #define READ_PHY84756_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \
    104             PHY84756_REG_READ((_unit), (_phy_ctrl), \
    105               SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val))
    106 
    107 #define PHY84756_REG_WRITE(_unit, _phy_ctrl, _addr, _val) \
    108                 WRITE_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val))
    109               
    110 #define WRITE_PHY84756_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \
    111                 PHY84756_REG_WRITE((_unit), (_phy_ctrl), \
    112                   SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val))
    113 
    114 STATIC int phy_84756_init(int unit, soc_port_t port);
    115 STATIC int phy_84756_link_get(int unit, soc_port_t port, int *link);
    116 STATIC int phy_84756_enable_set(int unit, soc_port_t port, int enable);
    117 STATIC int phy_84756_duplex_set(int unit, soc_port_t port, int duplex);
    118 STATIC int phy_84756_duplex_get(int unit, soc_port_t port, int *duplex);
    119 STATIC int phy_84756_speed_set(int unit, soc_port_t port, int speed);
    120 STATIC int phy_84756_speed_get(int unit, soc_port_t port, int *speed);
    121 #if 0
    122 STATIC int phy_84756_master_set(int unit, soc_port_t port, int master);
    123 STATIC int phy_84756_master_get(int unit, soc_port_t port, int *master);
    124 #endif
    125 STATIC int phy_84756_an_set(int unit, soc_port_t port, int autoneg);
    126 STATIC int phy_84756_an_get(int unit, soc_port_t port,
    127                                 int *autoneg, int *autoneg_done);
    128 STATIC int phy_84756_lb_set(int unit, soc_port_t port, int enable);
    129 STATIC int phy_84756_lb_get(int unit, soc_port_t port, int *enable);
    130 STATIC int phy_84756_medium_config_set(int unit, soc_port_t port, 
    131                                       soc_port_medium_t  medium,
    132                                       soc_phy_config_t  *cfg);
    133 STATIC int phy_84756_medium_config_get(int unit, soc_port_t port, 
    134                                       soc_port_medium_t medium,
    135                                       soc_phy_config_t *cfg);
    136 STATIC int phy_84756_ability_advert_set(int unit, soc_port_t port, 
    137                                        soc_port_ability_t *ability);
    138 STATIC int phy_84756_ability_advert_get(int unit, soc_port_t port,
    139                                        soc_port_ability_t *ability);
    140 STATIC int phy_84756_ability_remote_get(int unit, soc_port_t port,
    141                                        soc_port_ability_t *ability);
    142 STATIC int phy_84756_ability_local_get(int unit, soc_port_t port, 
    143                                 soc_port_ability_t *ability);
    144 STATIC int phy_84756_firmware_set(int unit, int port, int offset, 
    145                                  uint8 *data, int len);
    146 STATIC int phy_84756_control_set(int unit, soc_port_t port,
    147                      soc_phy_control_t type, uint32 value);
    148 STATIC int phy_84756_control_get(int unit, soc_port_t port,
    149                      soc_phy_control_t type, uint32 *value);
    150 STATIC int phy_84756_linkup(int unit, soc_port_t port);
    151 STATIC int phy_84756_interface_get(int unit, soc_port_t port,
    152                                    soc_port_if_t *pif);
    153 
    154 STATIC int phy_84756_reg_read(int unit, soc_port_t port, uint32 flags,
    155                                    uint32 phy_reg_addr, uint32 *phy_data);
    156 
    157 STATIC int phy_84756_reg_write(int unit, soc_port_t port, uint32 flags,
    158                                    uint32 phy_reg_addr, uint32 phy_data);
    159 
    160 typedef struct phy84756_data_s {
    161     int phy_ext_rom_boot;
    162     bmacsec_dev_addr_t phy_dev_addr;
    163     int line_mode;
    164     int macsec_enable;
    165     int fcmap_enable;
    166 }phy84756_data_t;
    167 
    168 #define PHY_EXT_ROM_BOOT(_pc)  (((phy84756_data_t *)((_pc) + 1))->phy_ext_rom_boot)
    169 #define PHY_DEV_ADDR(_pc)      (((phy84756_data_t *)((_pc) + 1))->phy_dev_addr)
    170 #define LINE_MODE(_pc)         (((phy84756_data_t *)((_pc) + 1))->line_mode)
    171 #define MACSEC_ENABLE(_pc)     (((phy84756_data_t *)((_pc) + 1))->macsec_enable)
    172 #define FCMAP_ENABLE(_pc)      (((phy84756_data_t *)((_pc) + 1))->fcmap_enable)
    173 
    174 /*
    175  * Function:
    176  *      _phy_84756_medium_config_update
    177  * Purpose:
    178  *      Update the PHY with config parameters
    179  * Parameters:
    180  *      unit - StrataSwitch unit #.
    181  *      port - StrataSwitch port #.
    182  *      cfg - Config structure.
    183  * Returns:
    184  *      SOC_E_XXX
    185  */
    186 
    187 STATIC int
    188 _phy_84756_medium_config_update(int unit, soc_port_t port,
    189                                 soc_phy_config_t *cfg)
    190 {
    191 
    192     SOC_IF_ERROR_RETURN
    193         (phy_84756_speed_set(unit, port, cfg->force_speed));
    194     SOC_IF_ERROR_RETURN
    195         (phy_84756_duplex_set(unit, port, cfg->force_duplex));
    196     SOC_IF_ERROR_RETURN
    197         (phy_84756_ability_advert_set(unit, port, &cfg->advert_ability));
    198     SOC_IF_ERROR_RETURN
    199         (phy_84756_an_set(unit, port, cfg->autoneg_enable));
    200 
    201     return SOC_E_NONE;
    202 }
    203 
    204 /* Function:
    205  *    phy_84756_init
    206  * Purpose:    
    207  *    Initialize 84756 phys
    208  * Parameters:
    209  *    unit - StrataSwitch unit #.
    210  *    port - StrataSwitch port #. 
    211  * Returns:    
    212  *    SOC_E_NONE
    213  */
    214 
    215 STATIC int
    216 phy_84756_init(int unit, soc_port_t port)
    217 {
    218     phy_ctrl_t     *pc;
    219     int rv = SOC_E_NONE;
    220 
    221     pc     = EXT_PHY_SW_STATE(unit, port);
    222 
    223     MACSEC_ENABLE(pc) = 0;
    224     FCMAP_ENABLE(pc) = 0;
    225 
    226     if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT ||
    227         PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1   ) {
    228         int fiber_preferred;
    229         int mmi_mdio_addr;
    230 
    231 #if defined(INCLUDE_MACSEC)
    232         /* By default MACSEC is disable */
    233         /* Check if enable property is set */
    234         pc->macsec_enable = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0);
    235         MACSEC_ENABLE(pc) = pc->macsec_enable;
    236 
    237         pc->macsec_dev_port = soc_property_port_get(unit, port, 
    238                                            spn_MACSEC_PORT_INDEX, -1);
    239         PHY_DEV_ADDR(pc) = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    240 
    241         /* Base PHY ID is used to access MACSEC core */
    242         mmi_mdio_addr = soc_property_port_get(unit, port, 
    243                                             spn_MACSEC_DEV_ADDR, -1);
    244         if (mmi_mdio_addr < 0) {
    245             LOG_WARN(BSL_LS_SOC_PHY,
    246                      (BSL_META_U(unit,
    247                                  "phy_84756_init: "
    248                                  "MACSEC_DEV_ADDR property "
    249                                  "not configured for u=%d p=%d\n"), unit, port));
    250             return SOC_E_CONFIG;
    251         }
    252 
    253         pc->macsec_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1);
    254 
    255         rv = bmacsec_phy84756_phy_mac_addr_set(PHY_DEV_ADDR(pc), 
    256                                               pc->macsec_dev_addr, 
    257                                               pc->macsec_dev_port,
    258                                               bmacsec_io_mmi1_cl45);
    259 #endif
    260 
    261 #if defined(INCLUDE_FCMAP)
    262 
    263         pc->fcmap_enable = soc_property_port_get(unit, port, spn_FCMAP_ENABLE, 0);
    264         FCMAP_ENABLE(pc) = pc->fcmap_enable;
    265 
    266         pc->fcmap_dev_port = soc_property_port_get(unit, port, 
    267                                            spn_FCMAP_PORT_INDEX, -1);
    268         PHY_DEV_ADDR(pc) = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    269 
    270         /* Base PHY ID is used to access MACSEC core */
    271         mmi_mdio_addr = soc_property_port_get(unit, port, 
    272                                             spn_FCMAP_DEV_ADDR, -1);
    273         if (mmi_mdio_addr < 0) {
    274             LOG_WARN(BSL_LS_SOC_PHY,
    275                      (BSL_META_U(unit,
    276                                  "phy_84756_init: "
    277                                  "FCMAP_DEV_ADDR property "
    278                                  "not configured for u=%d p=%d\n"), unit, port));
    279             return SOC_E_CONFIG;
    280         }
    281 
    282         pc->fcmap_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1);
    283         pc->fcmap_uc_dev_addr = PHY_DEV_ADDR(pc);
    284 
    285         rv = bmacsec_phy84756_phy_mac_addr_set(PHY_DEV_ADDR(pc), 
    286                                               pc->fcmap_dev_addr, 
    287                                               pc->fcmap_dev_port,
    288                                               bfcmap_io_mmi1_cl45);
    289 
    290 #endif
    291 
    292         if(rv != BMACSEC_E_NONE) {
    293             LOG_WARN(BSL_LS_SOC_PHY,
    294                      (BSL_META_U(unit,
    295                                  "phy_84756_init: bmacsec_phy_mac_addr_set "
    296                                  "returned error for u=%d p=%d\n"), unit, port));
    297             return SOC_E_FAIL;
    298         }
    299 
    300         LOG_INFO(BSL_LS_SOC_PHY,
    301                  (BSL_META_U(unit,
    302                              "phy_84756_init: u=%d p=%d\n"),unit, port));
    303 
    304         /* Preferred mode:
    305          * phy_fiber_pref = 1 ; Port is in SFI mode in 10G Default
    306          *                      when speed is changed to 1G, its 1000X
    307          * phy_fiber_pref = 0; Port is in SGMII mode, allows only 1G/100M/10M
    308          */
    309         fiber_preferred =
    310             soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 1);
    311 
    312         /* Initially configure for the preferred medium. */
    313         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
    314         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
    315         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU);
    316         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX);
    317 
    318         if (fiber_preferred) {
    319             LINE_MODE(pc) = BMACSEC_PHY84756_INTF_SFI;
    320             pc->copper.enable = FALSE;
    321             pc->fiber.enable = TRUE;
    322             pc->interface = SOC_PORT_IF_XFI;
    323             PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
    324         } else {
    325             pc->interface = SOC_PORT_IF_SGMII;
    326             LINE_MODE(pc) = BMACSEC_PHY84756_INTF_SGMII;
    327             pc->copper.enable = TRUE;
    328             pc->fiber.enable = FALSE;
    329             PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
    330         }
    331         PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45);
    332 
    333         pc->copper.preferred = !fiber_preferred;
    334         pc->copper.autoneg_enable = TRUE;
    335         pc->copper.autoneg_advert = ADVERT_ALL_COPPER;
    336         pc->copper.force_speed = 1000;
    337         pc->copper.force_duplex = TRUE;
    338         pc->copper.master = SOC_PORT_MS_AUTO;
    339         pc->copper.mdix = SOC_PORT_MDIX_AUTO;
    340 
    341         pc->fiber.preferred = TRUE;
    342         pc->fiber.autoneg_enable = FALSE;
    343         pc->fiber.autoneg_advert = ADVERT_ALL_FIBER;
    344         pc->fiber.force_speed = 10000;
    345         pc->fiber.force_duplex = TRUE;
    346         pc->fiber.master = SOC_PORT_MS_NONE;
    347         pc->fiber.mdix = SOC_PORT_MDIX_NORMAL;
    348 
    349         PHY_EXT_ROM_BOOT(pc) = soc_property_port_get(unit, port,
    350                                                 spn_PHY_EXT_ROM_BOOT, 1);
    351         if ((!PHY_EXT_ROM_BOOT(pc)) && (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT)) {
    352                 pc->flags |= PHYCTRL_MDIO_BCST;
    353                 pc->dev_name = "BCM84756";
    354         }
    355 
    356         if ( PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT ) {
    357             /* indicate second pass of init is needed */
    358             PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_PASS2);
    359 
    360             return SOC_E_NONE;
    361         }
    362 
    363     }
    364 
    365     if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) ||
    366         (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) {
    367 
    368         /* Init PHYS and MACs to defaults */
    369         rv = bmacsec_phy84756_init(PHY_DEV_ADDR(pc), 1, 
    370                                    LINE_MODE(pc), 
    371                                    MACSEC_ENABLE(pc), 
    372                                    FCMAP_ENABLE(pc), 
    373                                    PHY_EXT_ROM_BOOT(pc) ? 1 : (pc->flags & PHYCTRL_MDIO_BCST ? -1 : 0));
    374 
    375         if (rv != BMACSEC_E_NONE) {
    376             return SOC_E_FAIL;
    377         }
    378 
    379 
    380         /* Get Requested LED selectors (defaults are hardware defaults) */
    381         pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0);
    382         pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1);
    383         pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3);
    384         pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6);
    385         pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8);
    386         pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0);
    387 
    388         /*
    389          * Some reasonable defaults
    390          */
    391 #if defined(INCLUDE_MACSEC)
    392         pc->macsec_switch_fixed = 0;
    393         pc->macsec_switch_fixed_speed = 10000;
    394         pc->macsec_switch_fixed_duplex = 1;
    395         pc->macsec_switch_fixed_pause = 1;
    396         pc->macsec_pause_rx_fwd = 0;
    397         pc->macsec_pause_tx_fwd = 0;
    398         pc->macsec_line_ipg = 0xc;
    399         pc->macsec_switch_ipg = 0xc;
    400 #endif
    401 
    402 #if defined(INCLUDE_FCMAP)
    403         pc->fcmap_switch_fixed = 0;
    404         pc->fcmap_switch_fixed_speed = 10000;
    405         pc->fcmap_switch_fixed_duplex = 1;
    406         pc->fcmap_switch_fixed_pause = 1;
    407         pc->fcmap_pause_rx_fwd = 0;
    408         pc->fcmap_pause_tx_fwd = 0;
    409         pc->fcmap_line_ipg = 0xc;
    410         pc->fcmap_switch_ipg = 0xc;
    411 #endif
    412 
    413         SOC_IF_ERROR_RETURN
    414             (_phy_84756_medium_config_update(unit, port,
    415                                         PHY_COPPER_MODE(unit, port) ?
    416                                         &pc->copper :
    417                                         &pc->fiber));
    418 
    419 #if defined(INCLUDE_MACSEC)
    420         if (MACSEC_ENABLE(pc)) {
    421             rv = soc_macsecphy_init(unit, port, pc, 
    422                         BMACSEC_CORE_BCM84756, bmacsec_io_mmi1_cl45);
    423             if (!SOC_SUCCESS(rv)) {
    424             LOG_ERROR(BSL_LS_SOC_PHY,
    425                       (BSL_META_U(unit,
    426                                   "soc_macsecphy_init: MACSEC init for"
    427                                   " u=%d p=%d FAILED "), unit, port));
    428             } else {
    429             LOG_INFO(BSL_LS_SOC_PHY,
    430                      (BSL_META_U(unit,
    431                                  "soc_macsecphy_init: MACSEC init for"
    432                                  " u=%d p=%d SUCCESS "), unit, port));
    433             }
    434         }
    435 #endif
    436 
    437 #if defined(INCLUDE_FCMAP)
    438         if (FCMAP_ENABLE(pc)) {
    439             rv = soc_fcmapphy_init(unit, port, pc, 
    440                         BFCMAP_CORE_BCM84756, bfcmap_io_mmi1_cl45);
    441             if (!SOC_SUCCESS(rv)) {
    442             LOG_ERROR(BSL_LS_SOC_PHY,
    443                       (BSL_META_U(unit,
    444                                   "soc_fcmapphy_init: FCMAP init for"
    445                                   " u=%d p=%d FAILED "), unit, port));
    446             } else {
    447             LOG_INFO(BSL_LS_SOC_PHY,
    448                      (BSL_META_U(unit,
    449                                  "soc_fcmapphy_init: FCMAP init for"
    450                                  " u=%d p=%d SUCCESS "), unit, port));
    451             }
    452         }
    453 #endif
    454         PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_DEFAULT);
    455 
    456     }
    457 
    458     return SOC_E_NONE;
    459 }
    460 
    461 
    462 /*
    463  * Function:
    464  *    phy_84756_link_get
    465  * Purpose:
    466  *    Get layer2 connection status.
    467  * Parameters:
    468  *    unit - StrataSwitch unit #.
    469  *    port - StrataSwitch port #. 
    470  *      link - address of memory to store link up/down state.
    471  * Returns:    
    472  *    SOC_E_NONE
    473  */
    474 
    475 STATIC int
    476 phy_84756_link_get(int unit, soc_port_t port, int *link)
    477 {
    478     phy_ctrl_t    *pc;
    479     int rv = SOC_E_NONE;
    480     bmacsec_dev_addr_t phy_dev_addr;
    481     bmacsec_phy84756_intf_t bmacsec_mode;
    482     int bmacsec_link;
    483 
    484     pc    = EXT_PHY_SW_STATE(unit, port);
    485     *link = FALSE;      /* Default return */
    486 
    487     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
    488         return SOC_E_NONE;
    489     }
    490 
    491 #if defined(INCLUDE_MACSEC)
    492     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
    493 #endif
    494 #if defined(INCLUDE_FCMAP)
    495     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    496 #endif
    497 
    498     rv = bmacsec_phy84756_line_intf_get(phy_dev_addr, 0, &bmacsec_mode);
    499     if (!BMACSEC_E_SUCCESS(rv)) {
    500         return SOC_E_FAIL;
    501     }
    502 
    503     if (bmacsec_mode == BMACSEC_PHY84756_INTF_SGMII) {
    504         PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER);
    505         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER);
    506     } else {
    507         PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER);
    508         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER);
    509     }
    510 
    511     rv = bmacsec_phy84756_link_get(phy_dev_addr, &bmacsec_link);
    512     if (!BMACSEC_E_SUCCESS(rv)) {
    513         return SOC_E_FAIL;
    514     }
    515     if (bmacsec_link) {
    516         *link = TRUE;
    517     } else {
    518         *link = FALSE;
    519     }
    520 
    521     LOG_VERBOSE(BSL_LS_SOC_PHY,
    522                 (BSL_META_U(unit,
    523                             "phy_84756_link_get: u=%d p=%d link=%d\n"),
    524                  unit, port,
    525                  *link));
    526 
    527     return SOC_E_NONE;
    528 }
    529 
    530 /*
    531  * Function:
    532  *      phy_84756_enable_set
    533  * Purpose:
    534  *      Enable or disable the physical interface.
    535  * Parameters:
    536  *      unit - StrataSwitch unit #.
    537  *      port - StrataSwitch port #.
    538  *      enable - Boolean, true = enable PHY, false = disable.
    539  * Returns:
    540  *      SOC_E_XXX
    541  */
    542 
    543 STATIC int
    544 phy_84756_enable_set(int unit, soc_port_t port, int enable)
    545 {
    546     phy_ctrl_t    *pc;
    547     int rv = SOC_E_NONE;
    548     bmacsec_dev_addr_t phy_dev_addr;
    549 
    550     pc     = EXT_PHY_SW_STATE(unit, port);
    551 
    552     if (enable) {
    553         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
    554     } else {
    555         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
    556     }
    557 
    558 #if defined(INCLUDE_MACSEC)
    559     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    560 #endif
    561 #if defined(INCLUDE_FCMAP)
    562     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    563 #endif
    564 
    565     rv = bmacsec_phy84756_enable_set(phy_dev_addr, enable);
    566 
    567     if(rv != BMACSEC_E_NONE) {
    568         return SOC_E_FAIL;
    569     }
    570 
    571     LOG_INFO(BSL_LS_SOC_PHY,
    572              (BSL_META_U(unit,
    573                          "phy_84756_enable_set: "
    574                          "Power %s fiber medium\n"), (enable) ? "up" : "down"));
    575 
    576     return SOC_E_NONE;
    577 }
    578 
    579 /*
    580  * Function:
    581  *      phy_84756_duplex_set
    582  * Purpose:
    583  *      Set the current duplex mode
    584  * Parameters:
    585  *      unit - StrataSwitch unit #.
    586  *      port - StrataSwitch port #.
    587  *      duplex - Boolean, true indicates full duplex, false indicates half.
    588  * Returns:
    589  *      SOC_E_NONE
    590  *      SOC_E_UNAVAIL - Half duplex requested, and not supported.
    591  * Notes:
    592  */
    593 STATIC int
    594 phy_84756_duplex_set(int unit, soc_port_t port, int duplex)
    595 {
    596     int                          rv;
    597     phy_ctrl_t                   *pc;
    598     bmacsec_dev_addr_t           phy_dev_addr;
    599     bmacsec_phy84756_duplex_t    bmacsec_duplex;
    600 
    601     pc = EXT_PHY_SW_STATE(unit, port);
    602 
    603 #if defined(INCLUDE_MACSEC)
    604     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    605 #endif
    606 #if defined(INCLUDE_FCMAP)
    607     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    608 #endif
    609 
    610     if (duplex) {
    611         bmacsec_duplex = BMACSEC_PHY84756_FULL_DUPLEX;
    612     } else {
    613         bmacsec_duplex = BMACSEC_PHY84756_HALF_DUPLEX;
    614     }
    615     rv = bmacsec_phy84756_duplex_set(phy_dev_addr, bmacsec_duplex);
    616 
    617     if(BMACSEC_E_SUCCESS(rv)) {
    618         pc->copper.force_duplex = duplex;
    619     }
    620 
    621     LOG_INFO(BSL_LS_SOC_PHY,
    622              (BSL_META_U(unit,
    623                          "phy_84756_duplex_set: u=%d p=%d d=%d rv=%d\n"),
    624               unit, port, duplex, rv));
    625     return (SOC_ERROR(rv));
    626 }
    627 
    628 /*
    629  * Function:
    630  *      phy_84756_duplex_get
    631  * Purpose:
    632  *      Get the current operating duplex mode. If autoneg is enabled,
    633  *      then operating mode is returned, otherwise forced mode is returned.
    634  * Parameters:
    635  *      unit - StrataSwitch unit #.
    636  *      port - StrataSwitch port #.
    637  *      duplex - (OUT) Boolean, true indicates full duplex, false
    638  *              indicates half.
    639  * Returns:
    640  *      SOC_E_NONE
    641  * Notes:
    642  *      The duplex is retrieved for the ACTIVE medium.
    643  *      No synchronization performed at this level. Autonegotiation is
    644  *      not manipulated.
    645  */
    646 
    647 STATIC int
    648 phy_84756_duplex_get(int unit, soc_port_t port, int *duplex)
    649 {
    650 
    651     int rv = SOC_E_NONE;
    652     phy_ctrl_t                   *pc;
    653     bmacsec_dev_addr_t phy_dev_addr;
    654     bmacsec_phy84756_duplex_t bmacsec_duplex;
    655 
    656     pc = EXT_PHY_SW_STATE(unit, port);
    657 
    658 #if defined(INCLUDE_MACSEC)
    659     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    660 #endif
    661 #if defined(INCLUDE_FCMAP)
    662     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    663 #endif
    664 
    665     rv = bmacsec_phy84756_duplex_get(phy_dev_addr, &bmacsec_duplex);
    666     if (rv != BMACSEC_E_NONE) {
    667         return SOC_E_FAIL;
    668     }
    669     if (bmacsec_duplex == BMACSEC_PHY84756_FULL_DUPLEX) {
    670         *duplex = TRUE;
    671     } else {
    672         *duplex = FALSE;
    673     }
    674 
    675     LOG_INFO(BSL_LS_SOC_PHY,
    676              (BSL_META_U(unit,
    677                          "phy_84756_duplex_get: u=%d p=%d d=%d rv=%d\n"),
    678               unit, port, *duplex, rv));
    679     return SOC_E_NONE;
    680 }
    681 
    682 
    683 /*
    684  * Function:
    685  *      phy_84756_speed_set
    686  * Purpose:
    687  *      Set PHY speed
    688  * Parameters:
    689  *      unit - StrataSwitch unit #.
    690  *      port - StrataSwitch port #.
    691  *      speed - link speed in Mbps
    692  * Returns:
    693  *      SOC_E_NONE
    694  */
    695 STATIC int
    696 phy_84756_speed_set(int unit, soc_port_t port, int speed)
    697 {
    698     phy_ctrl_t *pc;
    699     phy_ctrl_t  *int_pc;
    700     int            rv; 
    701     bmacsec_dev_addr_t phy_dev_addr;
    702 
    703     pc = EXT_PHY_SW_STATE(unit, port);
    704     int_pc = INT_PHY_SW_STATE(unit, port);
    705     rv = SOC_E_NONE;
    706 
    707     if (speed > 10000) {
    708         return SOC_E_UNAVAIL;
    709     }
    710 
    711 #if defined(INCLUDE_MACSEC)
    712     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    713 #endif
    714 #if defined(INCLUDE_FCMAP)
    715     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    716 #endif
    717 
    718     if(PHY_FIBER_MODE(unit, port)) {
    719         if (speed < 1000) {
    720             return SOC_E_UNAVAIL;
    721         }
    722     }
    723 
    724     rv = bmacsec_phy84756_speed_set(phy_dev_addr, speed);
    725     if(BMACSEC_E_SUCCESS(rv)) {
    726         if (NULL != int_pc) {
    727             PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0);
    728             PHY_SPEED_SET(int_pc->pd, unit, port, speed);
    729         }
    730         if(PHY_COPPER_MODE(unit, port)) {
    731             pc->copper.force_speed = speed;
    732         } else {
    733             if(PHY_FIBER_MODE(unit, port)) {
    734                 pc->fiber.force_speed = speed;
    735             }
    736         }
    737     }
    738     LOG_INFO(BSL_LS_SOC_PHY,
    739              (BSL_META_U(unit,
    740                          "phy_84756_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"),
    741               unit, port, speed, PHY_FIBER_MODE(unit, port), rv));
    742 
    743     return SOC_ERROR(rv);
    744 }
    745 
    746 /*
    747  * Function:
    748  *      phy_84756_speed_get
    749  * Purpose:
    750  *      Get the current operating speed for a 84756 device.
    751  * Parameters:
    752  *      unit - StrataSwitch unit #.
    753  *      port - StrataSwitch port #.
    754  *      speed - (OUT) Speed of the phy
    755  * Returns:
    756  *      SOC_E_NONE
    757  * Notes:
    758  *      The speed is retrieved for the ACTIVE medium.
    759  */
    760 
    761 STATIC int
    762 phy_84756_speed_get(int unit, soc_port_t port, int *speed)
    763 {
    764     int rv = SOC_E_NONE;
    765     bmacsec_dev_addr_t phy_dev_addr;
    766     phy_ctrl_t    *pc;
    767 
    768     pc = EXT_PHY_SW_STATE(unit, port);
    769 
    770 #if defined(INCLUDE_MACSEC)
    771     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    772 #endif
    773 #if defined(INCLUDE_FCMAP)
    774     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    775 #endif
    776 
    777     rv = bmacsec_phy84756_speed_get(phy_dev_addr, speed);
    778 
    779     if(!BMACSEC_E_SUCCESS(rv)) {
    780         LOG_WARN(BSL_LS_SOC_PHY,
    781                  (BSL_META_U(unit,
    782                              "phy_84756_speed_get: u=%d p=%d invalid speed\n"),
    783                   unit, port));
    784     } else {
    785         LOG_INFO(BSL_LS_SOC_PHY,
    786                  (BSL_META_U(unit,
    787                              "phy_84756_speed_get: u=%d p=%d speed=%d"),
    788                   unit, port, *speed));
    789     }
    790 
    791     return SOC_ERROR(rv);
    792 }
    793 
    794 /*
    795  * Function:
    796  *      phy_84756_an_set
    797  * Purpose:
    798  *      Enable or disable auto-negotiation on the specified port.
    799  * Parameters:
    800  *      unit - StrataSwitch unit #.
    801  *      port - StrataSwitch port #.
    802  *      autoneg - Boolean, if true, auto-negotiation is enabled
    803  *              (and/or restarted). If false, autonegotiation is disabled.
    804  * Returns:
    805  *      SOC_E_XXX
    806  * Notes:
    807  *      The autoneg mode is set only for the ACTIVE medium.
    808  */
    809 
    810 STATIC int
    811 phy_84756_an_set(int unit, soc_port_t port, int autoneg)
    812 {
    813     int                 rv;
    814     phy_ctrl_t   *pc;
    815     int autoneg_advert = 0;
    816     bmacsec_dev_addr_t phy_dev_addr;
    817 
    818     if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_REPEATER) ) {
    819         soc_port_if_t  pif;
    820         SOC_IF_ERROR_RETURN( phy_84756_interface_get(unit, port, &pif) );
    821         if ( SOC_PORT_IF_SGMII == pif ) {
    822             /* in Repeater and SGMII mode,               *\
    823             \* AN need to be done by the Internal SerDes */
    824             phy_ctrl_t* int_pc = INT_PHY_SW_STATE(unit, port);
    825             rv = PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, autoneg);
    826             return  rv;
    827         }
    828     }
    829 
    830     pc = EXT_PHY_SW_STATE(unit, port);
    831     rv = SOC_E_NONE;
    832 
    833     if(PHY_COPPER_MODE(unit, port)) {
    834         autoneg_advert = 0;
    835     } else {
    836         if(PHY_FIBER_MODE(unit, port)) {
    837             autoneg_advert = pc->fiber.autoneg_advert;
    838         }
    839     }
    840 #if defined(INCLUDE_MACSEC)
    841     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    842 #endif
    843 #if defined(INCLUDE_FCMAP)
    844     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    845 #endif
    846 
    847     rv = bmacsec_phy84756_an_set(phy_dev_addr, autoneg, autoneg_advert);
    848     if(BMACSEC_E_SUCCESS(rv)) {
    849         if(PHY_COPPER_MODE(unit, port)) {
    850             pc->copper.autoneg_enable = autoneg ? TRUE : FALSE;
    851         } else {
    852             if(PHY_FIBER_MODE(unit, port)) {
    853                 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE;
    854             }
    855         }
    856     }
    857 
    858     LOG_INFO(BSL_LS_SOC_PHY,
    859              (BSL_META_U(unit,
    860                          "phy_84756_an_set: u=%d p=%d autoneg=%d rv=%d\n"),
    861               unit, port, autoneg, rv));
    862     return SOC_ERROR(rv);
    863 }
    864 
    865 /*
    866  * Function:
    867  *      phy_84756_an_get
    868  * Purpose:
    869  *      Get the current auto-negotiation status (enabled/busy).
    870  * Parameters:
    871  *      unit - StrataSwitch unit #.
    872  *      port - StrataSwitch port #.
    873  *      autoneg - (OUT) if true, auto-negotiation is enabled.
    874  *      autoneg_done - (OUT) if true, auto-negotiation is complete. This
    875  *              value is undefined if autoneg == FALSE.
    876  * Returns:
    877  *      SOC_E_XXX
    878  * Notes:
    879  *      The autoneg mode is retrieved for the ACTIVE medium.
    880  */
    881 
    882 STATIC int
    883 phy_84756_an_get(int unit, soc_port_t port,
    884                      int *autoneg, int *autoneg_done)
    885 {
    886     int           rv;
    887     phy_ctrl_t   *pc;
    888     bmacsec_dev_addr_t phy_dev_addr;
    889 
    890     pc = EXT_PHY_SW_STATE(unit, port);
    891 
    892     rv            = SOC_E_NONE;
    893     *autoneg      = FALSE;
    894     *autoneg_done = FALSE;
    895 
    896 #if defined(INCLUDE_MACSEC)
    897     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    898 #endif
    899 #if defined(INCLUDE_FCMAP)
    900     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    901 #endif
    902 
    903     rv = bmacsec_phy84756_an_get(phy_dev_addr, autoneg, autoneg_done);
    904 
    905     return SOC_ERROR(rv);
    906 }
    907 
    908 /*
    909  * Function:
    910  *      phy_84756_lb_set
    911  * Purpose:
    912  *      Set the local PHY loopback mode.
    913  * Parameters:
    914  *      unit - StrataSwitch unit #.
    915  *      port - StrataSwitch port #.
    916  *      loopback - Boolean: true = enable loopback, false = disable.
    917  * Returns:
    918  *      SOC_E_XXX
    919  * Notes:
    920  *      The loopback mode is set only for the ACTIVE medium.
    921  *      No synchronization performed at this level.
    922  */
    923 
    924 STATIC int
    925 phy_84756_lb_set(int unit, soc_port_t port, int enable)
    926 {
    927     int           rv;
    928 #if 0
    929     int           link = 0;
    930     soc_timeout_t  to;
    931 #endif
    932     phy_ctrl_t    *pc;
    933     bmacsec_dev_addr_t phy_dev_addr;
    934 
    935     pc = EXT_PHY_SW_STATE(unit, port);
    936     rv = SOC_E_NONE;
    937 
    938 #if defined(INCLUDE_MACSEC)
    939     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    940 #endif
    941 #if defined(INCLUDE_FCMAP)
    942     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    943 #endif
    944 
    945     rv = bmacsec_phy84756_loopback_set(phy_dev_addr, enable);
    946 
    947     if (rv == BMACSEC_E_NONE) {
    948         /* wait for link up when loopback is enabled */
    949         
    950         if (enable) {
    951             sal_usleep(2000000);
    952         }
    953     }
    954 
    955     LOG_INFO(BSL_LS_SOC_PHY,
    956              (BSL_META_U(unit,
    957                          "phy_84756_lb_set: u=%d p=%d en=%d rv=%d\n"), 
    958               unit, port, enable, rv));
    959 
    960     return SOC_ERROR(rv); 
    961 }
    962 
    963 /*
    964  * Function:
    965  *      phy_84756_lb_get
    966  * Purpose:
    967  *      Get the local PHY loopback mode.
    968  * Parameters:
    969  *      unit - StrataSwitch unit #.
    970  *      port - StrataSwitch port #.
    971  *      loopback - (OUT) Boolean: true = enable loopback, false = disable.
    972  * Returns:
    973  *      SOC_E_XXX
    974  * Notes:
    975  *      The loopback mode is retrieved for the ACTIVE medium.
    976  */
    977 
    978 STATIC int
    979 phy_84756_lb_get(int unit, soc_port_t port, int *enable)
    980 {
    981     int                  rv;
    982     phy_ctrl_t    *pc;
    983     bmacsec_dev_addr_t phy_dev_addr;
    984 
    985     pc = EXT_PHY_SW_STATE(unit, port);
    986     rv = SOC_E_NONE;
    987 
    988 #if defined(INCLUDE_MACSEC)
    989     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    990 #endif
    991 #if defined(INCLUDE_FCMAP)
    992     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
    993 #endif
    994 
    995     rv = bmacsec_phy84756_loopback_get(phy_dev_addr, enable);
    996 
    997     return SOC_ERROR(rv); 
    998 }
    999 
   1000 /*
   1001  * Function:
   1002  *      phy_84756_medium_config_set
   1003  * Purpose:
   1004  *      Set the operating parameters that are automatically selected
   1005  *      when medium switches type.
   1006  * Parameters:
   1007  *      unit - StrataSwitch unit #
   1008  *      port - Port number
   1009  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
   1010  *      cfg - Operating parameters
   1011  * Returns:
   1012  *      SOC_E_XXX
   1013  */
   1014 
   1015 STATIC int
   1016 phy_84756_medium_config_set(int unit, soc_port_t port, 
   1017                            soc_port_medium_t  medium,
   1018                            soc_phy_config_t  *cfg)
   1019 {
   1020     phy_ctrl_t    *pc;
   1021 #if 0
   1022     soc_phy_config_t *active_medium;  /* Currently active medium */
   1023     int               medium_update = FALSE;
   1024 #endif
   1025     soc_phy_config_t *change_medium;  /* Requested medium */
   1026     soc_phy_config_t *other_medium;   /* The other medium */
   1027     soc_port_mode_t   advert_mask;
   1028 
   1029     if (NULL == cfg) {
   1030         return SOC_E_PARAM;
   1031     }
   1032 
   1033     pc            = EXT_PHY_SW_STATE(unit, port);
   1034 
   1035    switch (medium) {
   1036     case SOC_PORT_MEDIUM_COPPER:
   1037         if (!pc->automedium && !PHY_COPPER_MODE(unit, port)) {
   1038             return SOC_E_UNAVAIL;
   1039         }
   1040         change_medium  = &pc->copper;
   1041         other_medium   = &pc->fiber;
   1042         advert_mask    = ADVERT_ALL_COPPER;
   1043         break;
   1044     case SOC_PORT_MEDIUM_FIBER:
   1045         if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) {
   1046             return SOC_E_UNAVAIL;
   1047         }
   1048         change_medium  = &pc->fiber;
   1049         other_medium   = &pc->copper;
   1050         advert_mask    = ADVERT_ALL_FIBER;
   1051         break;
   1052     default:
   1053         return SOC_E_PARAM;
   1054     }
   1055 
   1056     /*
   1057      * Changes take effect immediately if the target medium is active or
   1058      * the preferred medium changes.
   1059      */
   1060 #if 0
   1061     if (change_medium->enable != cfg->enable) {
   1062         medium_update = TRUE;
   1063     }
   1064 #endif
   1065     if (change_medium->preferred != cfg->preferred) {
   1066         /* Make sure that only one medium is preferred */
   1067         other_medium->preferred = !cfg->preferred;
   1068 #if 0
   1069         medium_update = TRUE;
   1070 #endif
   1071     }
   1072 
   1073     sal_memcpy(change_medium, cfg, sizeof(*change_medium));
   1074     change_medium->autoneg_advert &= advert_mask;
   1075 
   1076 #if 0
   1077     if (medium_update) {
   1078         /* The new configuration may cause medium change. Check
   1079          * and update medium.
   1080          */
   1081         SOC_IF_ERROR_RETURN
   1082             (_phy_84756_medium_change(unit, port, TRUE, medium));
   1083     } else {
   1084         active_medium = (PHY_COPPER_MODE(unit, port)) ?  
   1085                             &pc->copper : &pc->fiber;
   1086         if (active_medium == change_medium) {
   1087             /* If the medium to update is active, update the configuration */
   1088             SOC_IF_ERROR_RETURN
   1089                 (_phy_84756_medium_config_update(unit, port, change_medium));
   1090         }
   1091     }
   1092 #endif
   1093     return SOC_E_NONE;
   1094 }
   1095 
   1096 /*
   1097  * Function:
   1098  *      phy_84756_medium_config_get
   1099  * Purpose:
   1100  *      Get the operating parameters that are automatically selected
   1101  *      when medium switches type.
   1102  * Parameters:
   1103  *      unit - StrataSwitch unit #
   1104  *      port - Port number
   1105  *      medium - SOC_PORT_MEDIUM_COPPER/FIBER
   1106  *      cfg - (OUT) Operating parameters
   1107  * Returns:
   1108  *      SOC_E_XXX
   1109  */
   1110 
   1111 STATIC int
   1112 phy_84756_medium_config_get(int unit, soc_port_t port, 
   1113                            soc_port_medium_t medium,
   1114                            soc_phy_config_t *cfg)
   1115 {
   1116     int            rv;
   1117     phy_ctrl_t    *pc;
   1118 
   1119     pc = EXT_PHY_SW_STATE(unit, port);
   1120     rv = SOC_E_NONE;
   1121 
   1122     switch (medium) {
   1123     case SOC_PORT_MEDIUM_COPPER:
   1124         if (pc->automedium || PHY_COPPER_MODE(unit, port)) {
   1125             sal_memcpy(cfg, &pc->copper, sizeof (*cfg));
   1126         } else {
   1127             rv = SOC_E_UNAVAIL;
   1128         }
   1129         break;
   1130     case SOC_PORT_MEDIUM_FIBER:
   1131         if (pc->automedium || PHY_FIBER_MODE(unit, port)) {
   1132             sal_memcpy(cfg, &pc->fiber, sizeof (*cfg));
   1133         } else {
   1134             rv = SOC_E_UNAVAIL;
   1135         }
   1136         break;
   1137     default:
   1138         rv = SOC_E_PARAM;
   1139         break;
   1140     }
   1141 
   1142     return rv;
   1143 }
   1144 
   1145 /*
   1146  * Function:
   1147  *      phy_84756_ability_advert_set
   1148  * Purpose:
   1149  *      Set the current advertisement for auto-negotiation.
   1150  * Parameters:
   1151  *      unit - StrataSwitch unit #.
   1152  *      port - StrataSwitch port #.
   1153  *      mode - Port mode mask indicating supported options/speeds.
   1154  * Returns:
   1155  *      SOC_E_XXX
   1156  * Notes:
   1157  *      The advertisement is set only for the ACTIVE medium.
   1158  *      No synchronization performed at this level.
   1159  */
   1160 STATIC int
   1161 phy_84756_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability)
   1162 {
   1163     int        rv;
   1164     phy_ctrl_t *pc;
   1165     bmacsec_phy84756_port_ability_t local_ability;
   1166     bmacsec_dev_addr_t phy_dev_addr;
   1167 
   1168     pc = EXT_PHY_SW_STATE(unit, port);
   1169 
   1170     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1171         return SOC_E_NONE;
   1172     }
   1173 
   1174     if (NULL == ability) {
   1175         return (SOC_E_PARAM);
   1176     }
   1177 
   1178     if (PHY_COPPER_MODE(unit, port)) {
   1179         pc->copper.advert_ability = *ability;
   1180     } else {
   1181         pc->fiber.advert_ability = *ability;
   1182     }
   1183 
   1184     local_ability = 0;
   1185 
   1186     if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) {
   1187         local_ability |= BMACSEC_PHY84756_PA_1000MB_FD;
   1188     }
   1189     if(ability->speed_full_duplex & SOC_PA_SPEED_10GB) {
   1190         local_ability |= BMACSEC_PHY84756_PA_10000MB_FD;
   1191     }
   1192 
   1193     if(ability->pause & SOC_PA_PAUSE_TX) {
   1194         local_ability |= BMACSEC_PHY84756_PA_PAUSE_TX;
   1195     }
   1196     if(ability->pause & SOC_PA_PAUSE_RX) {
   1197         local_ability |= BMACSEC_PHY84756_PA_PAUSE_RX;
   1198     }
   1199     if(ability->pause & SOC_PA_PAUSE_ASYMM) {
   1200         local_ability |= BMACSEC_PHY84756_PA_PAUSE_ASYMM;
   1201     }
   1202 
   1203     if(ability->loopback & SOC_PA_LB_NONE) {
   1204         local_ability |= BMACSEC_PHY84756_PA_LB_NONE;
   1205     }
   1206     if(ability->loopback & SOC_PA_LB_PHY) {
   1207         local_ability |= BMACSEC_PHY84756_PA_LB_PHY;
   1208     }
   1209     if(ability->flags & SOC_PA_AUTONEG) {
   1210         local_ability |= BMACSEC_PHY84756_PA_AN;
   1211     }
   1212 
   1213 #if defined(INCLUDE_MACSEC)
   1214     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1215 #endif
   1216 #if defined(INCLUDE_FCMAP)
   1217     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1218 #endif
   1219 
   1220     rv = bmacsec_phy84756_ability_advert_set(phy_dev_addr, local_ability);
   1221 
   1222 
   1223     return SOC_ERROR(rv);
   1224 }
   1225 
   1226 /*
   1227  * Function:
   1228  *      phy_84756_ability_advert_get
   1229  * Purpose:
   1230  *      Get the current advertisement for auto-negotiation.
   1231  * Parameters:
   1232  *      unit - StrataSwitch unit #.
   1233  *      port - StrataSwitch port #.
   1234  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1235  * Returns:
   1236  *      SOC_E_XXX
   1237  * Notes:
   1238  *      The advertisement is retrieved for the ACTIVE medium.
   1239  *      No synchronization performed at this level.
   1240  */
   1241 STATIC int
   1242 phy_84756_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   1243 {
   1244     phy_ctrl_t      *pc;
   1245     int        rv;
   1246     bmacsec_phy84756_port_ability_t local_ability;
   1247     bmacsec_dev_addr_t phy_dev_addr;
   1248 
   1249     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1250         return SOC_E_NONE;
   1251     }
   1252 
   1253     if (NULL == ability) {
   1254         return (SOC_E_PARAM);
   1255     }
   1256 
   1257     pc = EXT_PHY_SW_STATE(unit, port);
   1258 
   1259     local_ability = 0;
   1260 
   1261 #if defined(INCLUDE_MACSEC)
   1262     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1263 #endif
   1264 #if defined(INCLUDE_FCMAP)
   1265     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1266 #endif
   1267 
   1268     rv = bmacsec_phy84756_ability_advert_get(phy_dev_addr, &local_ability);
   1269     if (rv != BMACSEC_E_NONE) {
   1270         return SOC_E_FAIL;
   1271     }
   1272 
   1273     if(local_ability & BMACSEC_PHY84756_PA_1000MB_FD) {
   1274         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1275     }
   1276     if(local_ability & BMACSEC_PHY84756_PA_10000MB_FD) {
   1277         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1278     }
   1279 
   1280     if(local_ability & BMACSEC_PHY84756_PA_PAUSE_TX) {
   1281         ability->pause |= SOC_PA_PAUSE_TX;
   1282     }
   1283     if(local_ability & BMACSEC_PHY84756_PA_PAUSE_RX) {
   1284         ability->pause |= SOC_PA_PAUSE_RX;
   1285     }
   1286     if(local_ability & BMACSEC_PHY84756_PA_PAUSE_ASYMM) {
   1287         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1288     }
   1289 
   1290     if(local_ability & BMACSEC_PHY84756_PA_LB_NONE) {
   1291         ability->loopback |= SOC_PA_LB_NONE;
   1292     }
   1293     if(local_ability & BMACSEC_PHY84756_PA_LB_PHY) {
   1294         ability->loopback |= SOC_PA_LB_PHY;
   1295     }
   1296     if(local_ability & BMACSEC_PHY84756_PA_AN) {
   1297         ability->flags = SOC_PA_AUTONEG;
   1298     }
   1299 
   1300     return SOC_E_NONE;
   1301 }
   1302 
   1303 /*
   1304  * Function:
   1305  *      phy_84756_ability_remote_get
   1306  * Purpose:
   1307  *      Get the current remote advertisement for auto-negotiation.
   1308  * Parameters:
   1309  *      unit - StrataSwitch unit #.
   1310  *      port - StrataSwitch port #.
   1311  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1312  * Returns:
   1313  *      SOC_E_XXX
   1314  * Notes:
   1315  *      The advertisement is retrieved for the ACTIVE medium.
   1316  *      No synchronization performed at this level.
   1317  */
   1318 STATIC int
   1319 phy_84756_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability)
   1320 {
   1321     phy_ctrl_t      *pc;
   1322     int        rv;
   1323     bmacsec_phy84756_port_ability_t remote_ability;
   1324     bmacsec_dev_addr_t phy_dev_addr;
   1325 
   1326     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
   1327         return SOC_E_NONE;
   1328     }
   1329 
   1330     if (NULL == ability) {
   1331         return (SOC_E_PARAM);
   1332     }
   1333 
   1334     pc = EXT_PHY_SW_STATE(unit, port);
   1335 
   1336     remote_ability = 0;
   1337 
   1338 #if defined(INCLUDE_MACSEC)
   1339     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1340 #endif
   1341 #if defined(INCLUDE_FCMAP)
   1342     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1343 #endif
   1344 
   1345     rv = bmacsec_phy84756_remote_ability_advert_get(phy_dev_addr,
   1346                                                    &remote_ability);
   1347     if (rv != BMACSEC_E_NONE) {
   1348         return SOC_E_FAIL;
   1349     }
   1350 
   1351     if(remote_ability & BMACSEC_PHY84756_PA_1000MB_FD) {
   1352         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1353     }
   1354     if(remote_ability & BMACSEC_PHY84756_PA_10000MB_FD) {
   1355         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1356     }
   1357 
   1358     if(remote_ability & BMACSEC_PHY84756_PA_PAUSE_TX) {
   1359         ability->pause |= SOC_PA_PAUSE_TX;
   1360     }
   1361     if(remote_ability & BMACSEC_PHY84756_PA_PAUSE_RX) {
   1362         ability->pause |= SOC_PA_PAUSE_RX;
   1363     }
   1364     if(remote_ability & BMACSEC_PHY84756_PA_PAUSE_ASYMM) {
   1365         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1366     }
   1367 
   1368     if(remote_ability & BMACSEC_PHY84756_PA_LB_NONE) {
   1369         ability->loopback |= SOC_PA_LB_NONE;
   1370     }
   1371     if(remote_ability & BMACSEC_PHY84756_PA_LB_PHY) {
   1372         ability->loopback |= SOC_PA_LB_PHY;
   1373     }
   1374     if(remote_ability & BMACSEC_PHY84756_PA_AN) {
   1375         ability->flags = SOC_PA_AUTONEG;
   1376     }
   1377 
   1378     return SOC_E_NONE;
   1379 }
   1380 
   1381 
   1382 
   1383 /*
   1384  * Function:
   1385  *      phy_84756_ability_local_get
   1386  * Purpose:
   1387  *      Get local abilities 
   1388  * Parameters:
   1389  *      unit - StrataSwitch unit #.
   1390  *      port - StrataSwitch port #.
   1391  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1392  * Returns:
   1393  *      SOC_E_NONE
   1394  * Notes:
   1395  *      The ability is retrieved only for the ACTIVE medium.
   1396  */
   1397 
   1398 STATIC int
   1399 phy_84756_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1400 {
   1401     int         rv = SOC_E_NONE;
   1402     phy_ctrl_t *pc;
   1403     bmacsec_phy84756_port_ability_t local_ability = 0;
   1404     bmacsec_dev_addr_t phy_dev_addr;
   1405 
   1406     if (NULL == ability) {
   1407         return SOC_E_PARAM;
   1408     }
   1409 
   1410     pc = EXT_PHY_SW_STATE(unit, port);
   1411 
   1412 #if defined(INCLUDE_MACSEC)
   1413     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1414 #endif
   1415 #if defined(INCLUDE_FCMAP)
   1416     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1417 #endif
   1418 
   1419     rv = bmacsec_phy84756_ability_local_get(phy_dev_addr, &local_ability);
   1420     if (rv != BMACSEC_E_NONE) {
   1421         return SOC_E_FAIL;
   1422     }
   1423 
   1424     if(local_ability & BMACSEC_PHY84756_PA_1000MB_FD) {
   1425         ability->speed_full_duplex |= SOC_PA_SPEED_1000MB;
   1426     }
   1427     if(local_ability & BMACSEC_PHY84756_PA_10000MB_FD) {
   1428         ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1429     }
   1430 
   1431     if(local_ability & BMACSEC_PHY84756_PA_PAUSE_TX) {
   1432         ability->pause |= SOC_PA_PAUSE_TX;
   1433     }
   1434     if(local_ability & BMACSEC_PHY84756_PA_PAUSE_RX) {
   1435         ability->pause |= SOC_PA_PAUSE_RX;
   1436     }
   1437     if(local_ability & BMACSEC_PHY84756_PA_PAUSE_ASYMM) {
   1438         ability->pause |= SOC_PA_PAUSE_ASYMM;
   1439     }
   1440 
   1441 
   1442     if(local_ability & BMACSEC_PHY84756_PA_LB_NONE) {
   1443         ability->loopback |= SOC_PA_LB_NONE;
   1444     }
   1445     if(local_ability & BMACSEC_PHY84756_PA_LB_PHY) {
   1446         ability->loopback |= SOC_PA_LB_PHY;
   1447     }
   1448     if(local_ability & BMACSEC_PHY84756_PA_AN) {
   1449         ability->flags = SOC_PA_AUTONEG;
   1450     }
   1451 
   1452     return SOC_E_NONE;
   1453 }
   1454 
   1455 /*
   1456  * Function:
   1457  *      phy_84756_firmware_set
   1458  * Purpose:
   1459  *      program the given firmware into the SPI-ROM
   1460  * Parameters:
   1461  *      unit - StrataSwitch unit #.
   1462  *      port - StrataSwitch port #.
   1463  *      offset - offset to the data stream
   1464  *      array  - the given data
   1465  *      datalen- the data length
   1466  * Returns:
   1467  *      SOC_E_NONE
   1468  */
   1469 
   1470 STATIC int
   1471 phy_84756_firmware_set(int unit, int port, int offset, uint8 *data,int len)
   1472 {
   1473     int            rv;
   1474     phy_ctrl_t *pc;
   1475     bmacsec_dev_addr_t phy_dev_addr;
   1476 
   1477     pc = EXT_PHY_SW_STATE(unit, port);
   1478 
   1479 #if defined(INCLUDE_MACSEC)
   1480     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1481 #endif
   1482 #if defined(INCLUDE_FCMAP)
   1483     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1484 #endif
   1485 
   1486     rv = bmacsec_phy84756_spi_firmware_update(phy_dev_addr, offset, data, len);
   1487     if (rv != BMACSEC_E_NONE) {
   1488             LOG_WARN(BSL_LS_SOC_PHY,
   1489                      (BSL_META_U(unit,
   1490                                  "PHY84756 firmware upgrade possibly failed:"
   1491                                  "u=%d p=%d\n"), unit, port));
   1492         return (SOC_E_FAIL);
   1493     }
   1494     LOG_INFO(BSL_LS_SOC_PHY,
   1495              (BSL_META_U(unit,
   1496                          "PHY84756 firmware upgrade successful:"
   1497                          "u=%d p=%d\n"), unit, port));
   1498 
   1499     return SOC_E_NONE;
   1500 }
   1501 
   1502 /*
   1503  * Function:
   1504  *      phy_84756_medium_status
   1505  * Purpose:
   1506  *      Indicate the current active medium
   1507  * Parameters:
   1508  *      unit - StrataSwitch unit #.
   1509  *      port - StrataSwitch port #.
   1510  *      medium - (OUT) One of:
   1511  *              SOC_PORT_MEDIUM_COPPER
   1512  *              SOC_PORT_MEDIUM_XAUI
   1513  * Returns:
   1514  *      SOC_E_NONE
   1515  */
   1516 
   1517 STATIC int
   1518 phy_84756_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium)
   1519 {
   1520     COMPILER_REFERENCE(unit);
   1521     COMPILER_REFERENCE(port);
   1522 
   1523     *medium = SOC_PORT_MEDIUM_FIBER;
   1524 
   1525     return SOC_E_NONE;
   1526 }
   1527 
   1528 
   1529 /*
   1530  * Function:
   1531  *      phy_84756_control_set
   1532  * Purpose:
   1533  *      Configure PHY device specific control fucntion.
   1534  * Parameters:
   1535  *      unit  - StrataSwitch unit #.
   1536  *      port  - StrataSwitch port #.
   1537  *      type  - Control to update
   1538  *      value - New setting for the control
   1539  * Returns:    
   1540  *      SOC_E_NONE
   1541  */
   1542 STATIC int
   1543 phy_84756_control_set(int unit, soc_port_t port,
   1544                      soc_phy_control_t type, uint32 value)
   1545 {
   1546     int rv = BMACSEC_E_NONE; 
   1547 
   1548 #ifdef INCLUDE_MACSEC
   1549 #ifdef PHY84756_SWITCH_FIXED_MODE
   1550     bmacsec_dev_addr_t phy_dev_addr;
   1551     bmacsec_phy84756_intf_t line_mode;
   1552     int pause_fwd =0, line_speed=0, line_duplex=0, line_pause=1;
   1553     phy_ctrl_t    *pc;
   1554 
   1555     rv = BMACSEC_E_NONE;    
   1556     pc = EXT_PHY_SW_STATE(unit, port);
   1557 
   1558 /* Disable switch fixed speed modes and supporting functions
   1559    Code not deleted to save the work already done if feature is enabled later
   1560 */
   1561     if (pc->macsec_enable != 1) {
   1562         return SOC_E_UNAVAIL;
   1563     }
   1564 
   1565     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 
   1566     rv = bmacsec_phy84756_line_intf_get(phy_dev_addr,
   1567                                        pc->macsec_dev_port, &line_mode);
   1568     if (rv != BMACSEC_E_NONE) {
   1569         return SOC_ERROR(rv);
   1570     }
   1571     switch(type) {
   1572         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED:
   1573             pc->macsec_switch_fixed = value;
   1574             if(value) {
   1575                 rv = bmacsec_phy84756_switch_side_set_params(phy_dev_addr, 
   1576                                 BMACSEC_BCM84756_SWITCH_FIXED, 
   1577                                 pc->macsec_switch_fixed_speed,
   1578                                 pc->macsec_switch_fixed_duplex,
   1579                                 pc->macsec_switch_fixed_pause);
   1580             } else { /* Switch side follows line side */
   1581                 SOC_IF_ERROR_RETURN
   1582                     (phy_84756_speed_get(unit, port, &line_speed));
   1583                 SOC_IF_ERROR_RETURN
   1584                     (phy_84756_duplex_get(unit, port, &line_duplex));
   1585 #if 0 
   1586                 SOC_IF_ERROR_RETURN
   1587                     (phy_84756_pause_get(unit, port, &line_pause));
   1588 #endif
   1589                 rv = bmacsec_phy84756_switch_side_set_params(phy_dev_addr, 
   1590                                 BMACSEC_BCM84756_SWITCH_FOLLOWS_LINE, 
   1591                                 line_speed, line_duplex, line_pause);
   1592             }
   1593             break;
   1594         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED:
   1595             /* Switch fixed speed is allowed only to be 1000Mbps */
   1596             if (pc->macsec_dev_port > 2) {
   1597                 if (value != 1000) {
   1598                     return SOC_E_CONFIG;
   1599                 }
   1600             } else {
   1601                 if (line_mode == BMACSEC_PHY84756_INTF_1000X) {
   1602                     if (value != 1000) {
   1603                         return SOC_E_CONFIG;
   1604                     }
   1605                 } else {
   1606                     if (value != 10000) {
   1607                         return SOC_E_CONFIG;
   1608                     }
   1609                 }
   1610             } 
   1611 
   1612             if(pc->macsec_switch_fixed_speed != value) {
   1613                 pc->macsec_switch_fixed_speed = value;
   1614             }
   1615             break;
   1616         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX:
   1617             /* Switch fixed Duplex is allowed only to be Full Duplex mode */
   1618             if (value != 1) {
   1619                 return SOC_E_CONFIG;
   1620             }
   1621             if(pc->macsec_switch_fixed_duplex != value) {
   1622                 pc->macsec_switch_fixed_duplex = value;
   1623             }
   1624             break;
   1625         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE:
   1626             if(pc->macsec_switch_fixed_pause != value) {
   1627                 pc->macsec_switch_fixed_pause = value;
   1628             }
   1629             break;
   1630         case SOC_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD:
   1631             pc->macsec_pause_rx_fwd = value;
   1632             pause_fwd = (value == 1) ? 1 : 0;
   1633 
   1634             rv = bmacsec_phy84756_line_side_pause_forward(phy_dev_addr,
   1635                                                          pause_fwd);
   1636             if (rv == BMACSEC_E_NONE) {
   1637                 rv = bmacsec_phy84756_switch_side_pause_forward(
   1638                                                      phy_dev_addr, pause_fwd);
   1639             }
   1640             break;
   1641         case SOC_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD:
   1642             pc->macsec_pause_tx_fwd = value;
   1643             pause_fwd = (value == 1) ? 1 : 0;
   1644 
   1645             rv = bmacsec_phy84756_line_side_pause_forward(phy_dev_addr,
   1646                                                           pause_fwd);
   1647             if (rv == BMACSEC_E_NONE) {
   1648                 rv = bmacsec_phy84756_switch_side_pause_forward(phy_dev_addr,
   1649                                                                 pause_fwd);
   1650             }
   1651             break;
   1652         case SOC_PHY_CONTROL_MACSEC_LINE_IPG:
   1653             pc->macsec_line_ipg = value;
   1654             rv = bmacsec_phy84756_line_side_ipg_set(phy_dev_addr, value);
   1655             break;
   1656         case SOC_PHY_CONTROL_MACSEC_SWITCH_IPG:
   1657             pc->macsec_switch_ipg = value;
   1658             rv = bmacsec_phy84756_switch_side_ipg_set(phy_dev_addr, value);
   1659             break;
   1660         default:
   1661             rv = SOC_E_UNAVAIL;
   1662             break;
   1663     }
   1664 #endif /* PHY84756_SWITCH_FIXED_MODE */
   1665 #else
   1666     bmacsec_dev_addr_t phy_dev_addr;
   1667     bmacsec_phy84756_intf_t line_mode;
   1668     int pause_fwd =0, line_speed=0, line_duplex=0, line_pause=1;
   1669 
   1670     pause_fwd = 0;
   1671     line_speed = 0;
   1672     line_duplex = 0;
   1673     line_pause = 1;
   1674     phy_dev_addr = 0;
   1675     line_mode = 0;
   1676 
   1677     rv = SOC_E_UNAVAIL;
   1678 #endif
   1679 
   1680     return SOC_ERROR(rv);
   1681 }
   1682 
   1683 /*
   1684  * Function:
   1685  *      phy_84756_control_get
   1686  * Purpose:
   1687  *      Get current control settign of the PHY.
   1688  * Parameters:
   1689  *      unit  - StrataSwitch unit #.
   1690  *      port  - StrataSwitch port #.
   1691  *      type  - Control to update
   1692  *      value - (OUT)Current setting for the control
   1693  * Returns:
   1694  *      SOC_E_NONE
   1695  */
   1696 STATIC int 
   1697 phy_84756_control_get(int unit, soc_port_t port,
   1698                      soc_phy_control_t type, uint32 *value)
   1699 {
   1700     int rv = SOC_E_NONE;
   1701 #ifdef INCLUDE_MACSEC
   1702 #ifdef PHY84756_SWITCH_FIXED_MODE
   1703     phy_ctrl_t    *pc;
   1704 
   1705     pc = EXT_PHY_SW_STATE(unit, port);
   1706 
   1707 /* Disable switch fixed speed modes and supporting functions
   1708    Code not deleted to save the work already done if feature is enabled later
   1709 */
   1710 
   1711     if (pc->macsec_enable != 1) {
   1712         return SOC_E_UNAVAIL;
   1713     }
   1714 
   1715     if (NULL == value) {
   1716         return SOC_E_PARAM;
   1717     }
   1718 
   1719     if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) {
   1720         return SOC_E_PARAM;
   1721     }
   1722 
   1723     rv = SOC_E_NONE;
   1724     switch(type) {
   1725         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED:
   1726             *value = pc->macsec_switch_fixed;
   1727             break;
   1728         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED:
   1729             *value = pc->macsec_switch_fixed_speed;
   1730             break;
   1731         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX:
   1732             *value = pc->macsec_switch_fixed_duplex;
   1733             break;
   1734         case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE:
   1735             *value = pc->macsec_switch_fixed_pause;
   1736             break;
   1737         case SOC_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD:
   1738             *value = pc->macsec_pause_rx_fwd;
   1739             break;
   1740         case SOC_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD:
   1741             *value = pc->macsec_pause_tx_fwd;
   1742             break;
   1743         case SOC_PHY_CONTROL_MACSEC_LINE_IPG:
   1744             *value = pc->macsec_line_ipg;
   1745             break;
   1746         case SOC_PHY_CONTROL_MACSEC_SWITCH_IPG:
   1747             *value = pc->macsec_switch_ipg;
   1748             break;
   1749         default:
   1750             rv = SOC_E_UNAVAIL;
   1751             break; 
   1752     }
   1753 #endif /* PHY84756_SWITCH_FIXED_MODE */
   1754 #else
   1755     rv = SOC_E_UNAVAIL;
   1756 #endif
   1757     return rv;
   1758 }
   1759 
   1760 /*
   1761  * Function:
   1762  *      phy_84756_linkup
   1763  * Purpose:
   1764  *      Link up handler
   1765  * Parameters:
   1766  *      unit  - StrataSwitch unit #.
   1767  *      port  - StrataSwitch port #.
   1768  * Returns:
   1769  *      SOC_E_NONE
   1770  */
   1771 STATIC int 
   1772 phy_84756_linkup(int unit, soc_port_t port)
   1773 {
   1774     int rv = SOC_E_NONE;
   1775     phy_ctrl_t    *pc;
   1776     bmacsec_dev_addr_t phy_dev_addr;
   1777     pc = EXT_PHY_SW_STATE(unit, port);
   1778 
   1779 #ifdef INCLUDE_MACSEC
   1780     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1781 
   1782     rv = bmacsec_84756_phy_linkup(phy_dev_addr, pc->macsec_enable);
   1783 #else
   1784     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1785 
   1786     rv = bmacsec_84756_phy_linkup(phy_dev_addr, pc->fcmap_enable);
   1787 #endif
   1788 
   1789     return SOC_ERROR(rv);
   1790 }
   1791 
   1792 /*
   1793  * Function:
   1794  *      phy_84756_interface_get
   1795  * Purpose:
   1796  *      Get interface on a given port.
   1797  * Parameters:
   1798  *      unit  - StrataSwitch unit #.
   1799  *      port  - StrataSwitch port #.
   1800  *      pif   - Interface.
   1801  * Returns:
   1802  *      SOC_E_NONE
   1803  */
   1804 STATIC int
   1805 phy_84756_interface_get(int unit, soc_port_t port, soc_port_if_t *pif)
   1806 {
   1807     *pif = PHY_COPPER_MODE(unit, port) ? SOC_PORT_IF_SGMII : SOC_PORT_IF_XFI;
   1808     return SOC_E_NONE;
   1809 }
   1810 
   1811 /*
   1812  * Function:
   1813  *      phy_84756_probe
   1814  * Purpose:
   1815  *      Complement the generic phy probe routine to identify this phy when its
   1816  *      phy id0 and id1 is same as some other phy's.
   1817  * Parameters:
   1818  *      unit - StrataSwitch unit #.
   1819  *      pc   - phy ctrl descriptor.
   1820  * Returns:
   1821  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
   1822  */
   1823 STATIC int
   1824 phy_84756_probe(int unit, phy_ctrl_t *pc)
   1825 {
   1826     uint16  data1, data2;
   1827 
   1828     if (READ_PHY84756_PMA_PMD_REG(unit, pc, 0xc802, &data1) < 0) {
   1829         return SOC_E_NOT_FOUND;
   1830     }
   1831 
   1832     if (READ_PHY84756_PMA_PMD_REG(unit, pc, 0xc803, &data2) < 0) {
   1833         return SOC_E_NOT_FOUND;
   1834     }
   1835 
   1836     /* Use of Standalone MACSEC driver is selected by fcmap_enable=0xff */
   1837     if (0xff == soc_property_port_get(unit, pc->port, spn_FCMAP_ENABLE, 0)) {
   1838         pc->size = sizeof(phy84756_data_t);
   1839         LOG_CLI((BSL_META_U(unit,
   1840                             "u=%d p=%d Using Standalone PHY driver for BCM84756\n"),
   1841                  unit, pc->port));
   1842         return SOC_E_NONE;
   1843     }
   1844     return SOC_E_NOT_FOUND;
   1845 
   1846 }
   1847 
   1848 /*
   1849  * Function:
   1850  *      phy_84756_timesync_config_set
   1851  * Description:
   1852  *      
   1853  * Parameters:
   1854  *
   1855  * Return Value:
   1856  *      SOC_E_XXX
   1857  */
   1858 
   1859 int
   1860 phy_84756_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *timesync_config)
   1861 {
   1862     int                          rv;
   1863     phy_ctrl_t                   *pc;
   1864     bmacsec_dev_addr_t phy_dev_addr;
   1865 
   1866     pc = EXT_PHY_SW_STATE(unit, port);
   1867     rv = SOC_E_NONE;
   1868 #if defined(INCLUDE_MACSEC)
   1869     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1870 #endif
   1871 #if defined(INCLUDE_FCMAP)
   1872     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1873 #endif
   1874  
   1875     rv = bmacsec_phy84756_timesync_config_set(phy_dev_addr, (bmacsec_port_phy_timesync_config_t *)timesync_config);
   1876     return (SOC_ERROR(rv));
   1877 
   1878 }
   1879 
   1880 /*
   1881  * Function:
   1882  *     phy_84756_timesync_config_get 
   1883  * Description:
   1884  *     
   1885  * Parameters:
   1886  *
   1887  * Return Value:
   1888  *      SOC_E_XXX
   1889  */
   1890 
   1891 int
   1892 phy_84756_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *timesync_config)
   1893 {
   1894     int                          rv;
   1895     phy_ctrl_t                   *pc;
   1896     bmacsec_dev_addr_t phy_dev_addr;
   1897 
   1898     pc = EXT_PHY_SW_STATE(unit, port);
   1899     rv = SOC_E_NONE;
   1900 #if defined(INCLUDE_MACSEC)
   1901     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1902 #endif
   1903 #if defined(INCLUDE_FCMAP)
   1904     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1905 #endif
   1906  
   1907     rv = bmacsec_phy84756_timesync_config_get(phy_dev_addr, (bmacsec_port_phy_timesync_config_t *)timesync_config);
   1908     return (SOC_ERROR(rv));
   1909 
   1910 }
   1911 
   1912 /*
   1913  * Function:
   1914  *      phy_84756_timesync_control_set
   1915  * Description:
   1916  *      
   1917  * Parameters:
   1918  *
   1919  * Return Value:
   1920  *      SOC_E_XXX
   1921  */
   1922 
   1923 int
   1924 phy_84756_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t control_type, uint64 value)
   1925 {
   1926     int                          rv;
   1927     phy_ctrl_t                   *pc;
   1928     bmacsec_dev_addr_t phy_dev_addr;
   1929     buint64_t btemp64;
   1930 
   1931     COMPILER_64_SET(btemp64, COMPILER_64_HI(value), COMPILER_64_LO(value)); 
   1932 
   1933     pc = EXT_PHY_SW_STATE(unit, port);
   1934     rv = SOC_E_NONE;
   1935 #if defined(INCLUDE_MACSEC)
   1936     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1937 #endif
   1938 #if defined(INCLUDE_FCMAP)
   1939     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1940 #endif
   1941  
   1942     rv = bmacsec_phy84756_timesync_control_set(phy_dev_addr, control_type, btemp64);
   1943     return (SOC_ERROR(rv));
   1944 
   1945 }
   1946 
   1947 /*
   1948  * Function:
   1949  *      phy_84756_timesync_control_get
   1950  * Description:
   1951  *      
   1952  * Parameters:
   1953  *
   1954  * Return Value:
   1955  *      SOC_E_XXX
   1956  */
   1957 int
   1958 phy_84756_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t control_type, uint64 *value)
   1959 {
   1960     int                          rv;
   1961     phy_ctrl_t                   *pc;
   1962     bmacsec_dev_addr_t phy_dev_addr;
   1963     buint64_t btemp64;
   1964 
   1965     COMPILER_64_ZERO(btemp64);
   1966     pc = EXT_PHY_SW_STATE(unit, port);
   1967     rv = SOC_E_NONE;
   1968 #if defined(INCLUDE_MACSEC)
   1969     phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1970 #endif
   1971 #if defined(INCLUDE_FCMAP)
   1972     phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1);
   1973 #endif
   1974  
   1975     rv = bmacsec_phy84756_timesync_control_get(phy_dev_addr, control_type, &btemp64);
   1976   
   1977     COMPILER_64_SET(*value, COMPILER_64_HI(btemp64), COMPILER_64_LO(btemp64));
   1978 
   1979     return (SOC_ERROR(rv));
   1980 
   1981 }
   1982 
   1983 
   1984 STATIC int 
   1985 phy_84756_reg_read(int unit, soc_port_t port, uint32 flags,
   1986                         uint32 phy_reg_addr, uint32 *phy_data)
   1987 {
   1988 	uint16               data16;
   1989     uint16               regdata;
   1990     phy_ctrl_t          *pc;      /* PHY software state */
   1991     int rv = SOC_E_NONE;
   1992 	int	rd_cnt;
   1993 
   1994     pc = EXT_PHY_SW_STATE(unit, port);
   1995 
   1996     rd_cnt = 1;
   1997 
   1998     if (flags & SOC_PHY_I2C_DATA8) {
   1999 
   2000         SOC_IF_ERROR_RETURN
   2001             (phy_84756_i2cdev_read(pc,
   2002                         SOC_PHY_I2C_DEVAD(phy_reg_addr),
   2003                         SOC_PHY_I2C_REGAD(phy_reg_addr),
   2004                         rd_cnt,
   2005                         (uint8 *)&data16));
   2006         *phy_data = *((uint8 *)&data16);
   2007 
   2008     } else if (flags & SOC_PHY_I2C_DATA16) {
   2009         /* This operation is generally targeted to access 16-bit device,
   2010          * such as PHY IC inside the SFP.  However there is no 16-bit
   2011          * scratch register space on the device.  Use 1.800e
   2012          * for this operation.
   2013          */
   2014         SOC_IF_ERROR_RETURN
   2015             (READ_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM,
   2016                    &regdata));
   2017 
   2018         rv = _phy_84756_bsc_rw(pc,
   2019                SOC_PHY_I2C_DEVAD(phy_reg_addr),
   2020                PHY84756_I2C_OP_TYPE(PHY84756_I2CDEV_READ,PHY84756_I2C_16BIT),
   2021                SOC_PHY_I2C_REGAD(phy_reg_addr),1,
   2022                (void *)&data16,PHY84756_I2C_TEMP_RAM);
   2023 
   2024         *phy_data = data16;
   2025 
   2026         /* restore the ram register value */
   2027         SOC_IF_ERROR_RETURN
   2028             (WRITE_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM,
   2029                  regdata));
   2030     } else {
   2031         SOC_IF_ERROR_RETURN
   2032             (READ_PHY_REG(unit, pc, phy_reg_addr, &data16));
   2033         *phy_data = data16;
   2034     } 
   2035 
   2036     return rv;
   2037 
   2038 }
   2039 
   2040 
   2041 
   2042 STATIC int
   2043 phy_84756_reg_write(int unit, soc_port_t port, uint32 flags,
   2044                         uint32 phy_reg_addr, uint32 phy_data)
   2045 {
   2046     uint8  data8[4];
   2047     uint16 data16[2];
   2048     uint16 regdata[2];
   2049     phy_ctrl_t          *pc;      /* PHY software state */
   2050     int rv = SOC_E_NONE;
   2051     int wr_cnt;
   2052 
   2053     pc = EXT_PHY_SW_STATE(unit, port);
   2054 
   2055     wr_cnt = 1;
   2056 
   2057     if (flags & SOC_PHY_I2C_DATA8) {
   2058         data8[0] = (uint8)phy_data;
   2059         SOC_IF_ERROR_RETURN
   2060             (phy_84756_i2cdev_write(pc,
   2061                         SOC_PHY_I2C_DEVAD(phy_reg_addr),
   2062                         SOC_PHY_I2C_REGAD(phy_reg_addr),
   2063                         wr_cnt,
   2064                         data8));
   2065     } else if (flags & SOC_PHY_I2C_DATA16) {
   2066 
   2067      /* This operation is generally targeted to access 16-bit device,
   2068          * such as PHY IC inside the SFP.  However there is no 16-bit
   2069          * scratch register space on the device.  Use 1.800e
   2070          * for this operation.
   2071          */
   2072         /* save the temp ram register */
   2073         SOC_IF_ERROR_RETURN
   2074             (READ_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM,
   2075                  &regdata[0]));
   2076         data16[0] = phy_data;
   2077         rv = _phy_84756_bsc_rw(pc,
   2078               SOC_PHY_I2C_DEVAD(phy_reg_addr),
   2079               PHY84756_I2C_OP_TYPE(PHY84756_I2CDEV_READ,PHY84756_I2C_16BIT),
   2080               SOC_PHY_I2C_REGAD(phy_reg_addr),wr_cnt,
   2081               (void *)data16,PHY84756_I2C_TEMP_RAM);
   2082 
   2083         /* restore the ram register value */
   2084         SOC_IF_ERROR_RETURN
   2085             (WRITE_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM,
   2086                   regdata[0]));
   2087     } else {
   2088         SOC_IF_ERROR_RETURN
   2089             (WRITE_PHY_REG(unit, pc, phy_reg_addr, (uint16)phy_data));
   2090     }
   2091     return rv;
   2092 }
   2093 
   2094 
   2095 
   2096 /*
   2097  * Variable:
   2098  *    phy_84756_drv
   2099  * Purpose:
   2100  *    Phy Driver for BCM84756 MACSEC PHY
   2101  */
   2102 
   2103 phy_driver_t phy_84756drv_xe = {
   2104     "84756 1G/10-Gigabit PHY Driver",
   2105     phy_84756_init,        /* Init */
   2106     phy_null_reset,       /* Reset */
   2107     phy_84756_link_get,    /* Link get   */
   2108     phy_84756_enable_set,  /* Enable set */
   2109     phy_null_enable_get,  /* Enable get */
   2110     phy_84756_duplex_set,  /* Duplex set */
   2111     phy_84756_duplex_get,  /* Duplex get */
   2112     phy_84756_speed_set,   /* Speed set  */
   2113     phy_84756_speed_get,   /* Speed get  */
   2114     phy_null_set,          /* Master set */
   2115     phy_null_zero_get,     /* Master get */
   2116     phy_84756_an_set,      /* ANA set */
   2117     phy_84756_an_get,      /* ANA get */
   2118     NULL,                 /* Local Advert set, deprecated */
   2119     NULL,                 /* Local Advert get, deprecated */
   2120     NULL,                 /* Remote Advert get, deprecated */
   2121     phy_84756_lb_set,      /* PHY loopback set */
   2122     phy_84756_lb_get,      /* PHY loopback set */
   2123     phy_null_interface_set, /* IO Interface set */
   2124     phy_84756_interface_get, /* IO Interface get */
   2125     NULL,                   /* pd_ability, deprecated */
   2126     phy_84756_linkup,
   2127     NULL,
   2128     phy_null_mdix_set,        /* phy_84756_mdix_set */
   2129     phy_null_mdix_get,        /* phy_84756_mdix_get */
   2130     phy_null_mdix_status_get, /* phy_84756_mdix_status_get */
   2131     phy_84756_medium_config_set, /* medium config setting set */
   2132     phy_84756_medium_config_get, /* medium config setting get */
   2133     phy_84756_medium_status,        /* active medium */
   2134     NULL,                    /* phy_cable_diag  */
   2135     NULL,                    /* phy_link_change */
   2136     phy_84756_control_set,    /* phy_control_set */
   2137     phy_84756_control_get,    /* phy_control_get */
   2138     phy_84756_reg_read,       /* phy_reg_read */
   2139     phy_84756_reg_write,      /* phy_reg_write */
   2140     NULL,                    /* phy_reg_modify */
   2141     NULL,                    /* phy_notify */
   2142     phy_84756_probe,         /* pd_probe  */
   2143     phy_84756_ability_advert_set,  /* pd_ability_advert_set */
   2144     phy_84756_ability_advert_get,  /* pd_ability_advert_get */
   2145     phy_84756_ability_remote_get,  /* pd_ability_remote_get */
   2146     phy_84756_ability_local_get,   /* pd_ability_local_get  */
   2147     phy_84756_firmware_set,
   2148     phy_84756_timesync_config_set,
   2149     phy_84756_timesync_config_get,
   2150     phy_84756_timesync_control_set,
   2151     phy_84756_timesync_control_get
   2152 };
   2153 
   2154 #else /* INCLUDE_PHY_84756 */
   2155 int _phy_84756_not_empty;
   2156 #endif /* INCLUDE_PHY_84756 */
   2157 #endif /* INCLUDE_MACSEC */