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

macsecphy.c (12583B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * StrataSwitch MACSEC PHY control
      8  * MACSEC PHY initialization 
      9  */
     10 
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <soc/drv.h>
     15 #include <soc/phy/phyctrl.h>
     16 #include <soc/phy/drv.h>
     17 #include <soc/debug.h>
     18 
     19 #ifdef INCLUDE_MACSEC 
     20 #include <bmacsec.h>
     21 #ifdef BCM_SWITCHMACSEC_SUPPORT
     22 #include <dummyphy.h>
     23 #endif  /* BCM_SWITCHMACSEC_SUPPORT */
     24 #if defined(INCLUDE_PHY_8729)
     25 #include <phy8729.h>
     26 #endif
     27 #include <soc/macsecphy.h>
     28 
     29 
     30 /* speed_get register */
     31 typedef int (*bmacsec_speed_get_f) (void * ext_port_handle, int * speed);
     32 
     33 extern void 
     34 _bmacsec_register_speed_get(int port, bmacsec_speed_get_f f, void *pc);
     35 
     36 
     37 
     38 int soc_macsecphy_speed_get(void * ext_port_handle, int * speed) {
     39 
     40     int                     rv;
     41     phy_ctrl_t *pc = (phy_ctrl_t *) ext_port_handle;
     42 
     43     if (speed == NULL) {
     44         return  -1;
     45     }
     46 
     47     *speed = 0;
     48 
     49     if (pc) {
     50         rv = PHYCTRL_SPEED_GET(pc, pc->unit, pc->port, speed);
     51         if (rv != SOC_E_NONE) {
     52             *speed = 0;
     53             return  -1;
     54         }
     55     }
     56 
     57     return 0;
     58 }
     59 
     60 
     61 /*
     62  * Function:
     63  *      soc_macsecphy_init
     64  * Purpose:
     65  *      Initializes the MACSEC phy port.
     66  * Parameters:
     67  *      unit - SOC Unit #.
     68  *      port - Port number.
     69  *      pc  - Phy control structure
     70  * Returns:
     71  *      SOC_E_XXX
     72  */
     73 int
     74 soc_macsecphy_init(int unit, soc_port_t port, phy_ctrl_t *pc, 
     75                    bmacsec_core_t core_type, bmacsec_dev_io_f iofn)
     76 {
     77     int                     /* ii, */ p, rv;
     78     int                     macsec_enable = 0;
     79 
     80     p = SOC_MACSEC_PORTID(unit, port);
     81     /* Destroy the port if it were created before. */
     82     (void)bmacsec_port_destroy(p);
     83 
     84     macsec_enable = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0);
     85     pc->macsec_enable = macsec_enable;
     86 
     87     if (macsec_enable) {
     88         /* Create MACSEC Port */
     89         rv = bmacsec_port_create(p, core_type, pc->macsec_dev_addr, 
     90                                  pc->macsec_dev_port, iofn);
     91         if (rv != BMACSEC_E_NONE) {
     92             LOG_WARN(BSL_LS_SOC_COMMON,
     93                      (BSL_META_U(unit,
     94                                  "soc_macsecphy_init: "
     95                                  "MACSEC port create failed for u=%d p=%d rv = %d\n"),
     96                       unit, port, rv));
     97             return SOC_E_FAIL;
     98         }
     99 
    100         /* register speed_get */
    101         _bmacsec_register_speed_get(p, soc_macsecphy_speed_get, (void *) pc);
    102     }
    103     return SOC_E_NONE;
    104 }
    105 
    106 int 
    107 soc_macsecphy_miim_read(soc_macsec_dev_addr_t dev_addr, 
    108                         uint32 phy_reg_addr, uint16 *data)
    109 {
    110     int unit, phy_id, clause45;
    111     int rv = SOC_E_NONE;
    112 #ifdef BCM_SWITCHMACSEC_SUPPORT
    113     int nophy_macsec = 0;
    114 #endif /* BCM_SWITCHMACSEC_SUPPORT */
    115 
    116     /*
    117      * Decode dev_addr into phyid and unit.
    118      */
    119     unit = SOC_MACSECPHY_ADDR2UNIT(dev_addr);
    120     phy_id = SOC_MACSECPHY_ADDR2MDIO(dev_addr);
    121 #ifdef BCM_SWITCHMACSEC_SUPPORT
    122     nophy_macsec = SOC_MACSECPHY_ADDR_IS_FLAG_NOPHY(dev_addr);;
    123     clause45 = SOC_MACSECPHY_ADDR_IS_FLAG_CLAUSE45(dev_addr);
    124 #else /* BCM_SWITCHMACSEC_SUPPORT */
    125     clause45 = SOC_MACSECPHY_ADDR_IS_CLAUSE45(dev_addr);
    126 #endif /* BCM_SWITCHMACSEC_SUPPORT */
    127 
    128 #ifdef BCM_ESW_SUPPORT
    129     if (SOC_IS_ESW(unit)) {
    130         if (clause45) {
    131             rv = soc_esw_miimc45_read(unit, phy_id, 
    132                                   phy_reg_addr, data);
    133         } else {
    134             rv = soc_miim_read(unit, phy_id, phy_reg_addr, data);
    135         }
    136     }
    137 #endif /* BCM_ESW_SUPPORT */
    138 
    139     return (rv == SOC_E_NONE) ? 0 : -1;
    140 }
    141 
    142 int 
    143 soc_macsecphy_miim_write(soc_macsec_dev_addr_t dev_addr, 
    144                          uint32 phy_reg_addr, uint16 data)
    145 {
    146     int unit, phy_id, clause45;
    147     int rv = SOC_E_NONE;
    148 #ifdef BCM_SWITCHMACSEC_SUPPORT
    149     int     nophy_macsec = 0;
    150 #endif /* BCM_SWITCHMACSEC_SUPPORT */
    151 
    152     /*
    153      * Decode dev_addr into phyid and unit.
    154      */
    155     unit = SOC_MACSECPHY_ADDR2UNIT(dev_addr);
    156     phy_id = SOC_MACSECPHY_ADDR2MDIO(dev_addr);
    157 
    158 #ifdef BCM_SWITCHMACSEC_SUPPORT
    159     nophy_macsec = SOC_MACSECPHY_ADDR_IS_FLAG_NOPHY(dev_addr);;
    160     clause45 = SOC_MACSECPHY_ADDR_IS_FLAG_CLAUSE45(dev_addr);
    161 #else /* BCM_SWITCHMACSEC_SUPPORT */
    162     clause45 = SOC_MACSECPHY_ADDR_IS_CLAUSE45(dev_addr);
    163 #endif /* BCM_SWITCHMACSEC_SUPPORT */
    164 
    165 #ifdef BCM_ESW_SUPPORT
    166     if (SOC_IS_ESW(unit)) {
    167         if (clause45) {
    168             rv = soc_esw_miimc45_write(unit, phy_id, 
    169                                    phy_reg_addr, data);
    170         } else {
    171             rv = soc_miim_write(unit, phy_id, phy_reg_addr, data);
    172         }
    173     }
    174 #endif /* BCM_ESW_SUPPORT */
    175 
    176     return (rv == SOC_E_NONE) ? 0 : -1;
    177 }
    178 
    179 
    180 #ifdef BCM_SWITCHMACSEC_SUPPORT
    181 int 
    182 soc_switchmacsec_init(int unit, soc_port_t port)
    183 {
    184     int     rv = SOC_E_NONE;
    185     int     addr_flags = 0, macsec_devid = -1;    
    186     int     mmi_mdio_addr, port_index, macsec_enable, macsec_dev_port_cnt;
    187     phy_ctrl_t          *pc;
    188     bmacsec_core_t      macsec_core = BMACSEC_CORE_UNKNOWN;
    189     bmacsec_dev_io_f    macsec_mmi_io = NULL;
    190     bmacsec_mactype_t   macsec_mac = BMACSEC_MAC_CORE_UNKNOWN;
    191     bmacsec_dev_addr_t  macsec_dev_addr, macsec_dev_idx;
    192     
    193     LOG_INFO(BSL_LS_SOC_PHY,
    194              (BSL_META_U(unit,
    195                          "%s: u=%d port=%d\n"),
    196               FUNCTION_NAME(), unit, port));
    197 
    198     SOC_NOPHY_MACSEC_DEVID_GET(unit, port, macsec_devid);
    199     if (macsec_devid == -1) {
    200         return SOC_E_NONE; 
    201     }
    202     
    203     pc = EXT_PHY_SW_STATE(unit, port);
    204     if (pc == NULL) {
    205         pc = INT_PHY_SW_STATE(unit, port);
    206         if (pc == NULL) {
    207             LOG_ERROR(BSL_LS_SOC_COMMON,
    208                       (BSL_META_U(unit,
    209                                   "no PHY driver attached on u=%d p=%d\n"), 
    210                        unit, port));
    211             return SOC_E_CONFIG;
    212         }
    213     }
    214 
    215     mmi_mdio_addr = soc_property_port_get(unit, port, spn_MACSEC_DEV_ADDR, -1);
    216     if (mmi_mdio_addr == -1) {
    217         LOG_WARN(BSL_LS_SOC_COMMON,
    218                  (BSL_META_U(unit,
    219                              "MACSEC_DEV_ADDR property not configured for u=%d p=%d\n"), 
    220                   unit, port));
    221         return SOC_E_CONFIG;
    222     }
    223     
    224     port_index = soc_property_port_get(unit, port, spn_MACSEC_PORT_INDEX, -1);
    225     if (port_index == -1) {
    226         LOG_WARN(BSL_LS_SOC_COMMON,
    227                  (BSL_META_U(unit,
    228                              "MACSEC_PORT_INDEX property not configured for u=%d p=%d\n"), 
    229                   unit, port));
    230         return SOC_E_CONFIG;
    231     }
    232 
    233     macsec_enable = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0);
    234 
    235     pc->macsec_dev_addr = mmi_mdio_addr;
    236     pc->macsec_dev_port = port_index;
    237     pc->macsec_enable = macsec_enable;
    238     
    239     addr_flags = SOC_MACSECPHY_MDIO_FLAGS_NOPHY;
    240     macsec_dev_idx = SOC_MACSECPHY_MDIO_ADDR(unit, macsec_devid, addr_flags); 
    241     macsec_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, mmi_mdio_addr, addr_flags);
    242 
    243     /* core type and LMI/MMI io function assignment :
    244      * - The core type, MAC type, macsec_dev_port_cnt and LMI/MMI io-function in current SDK is force assigned.
    245      */
    246     SOC_NOPHY_MACSEC_CORE_GET(unit, macsec_core, macsec_dev_port_cnt);
    247     SOC_NOPHY_MACSEC_MAC_GET(unit, macsec_mac);
    248     SOC_NOPHY_MACSEC_MMI_GET(unit, macsec_mmi_io);
    249 
    250     /* core type and LMI/MMI io function assignment :
    251      * - The core type and LMI/MMI io-function in current SDK is force assigned.
    252      */
    253     /*
    254      * COVERITY
    255      *
    256      *  This default is unreachable in some conditional builds. 
    257      *  (Currently the SwitchMACSEC(MACSEC-in-Switch) is supported in ROBO 
    258      *  switch only)
    259      *  
    260      *  To keep this design for the supporting ability while different chip 
    261      *  Arch.(like ESW) in future has SwitchMACSEC chip design.
    262      */
    263     /* coverity[dead_error_begin] */
    264     if ((macsec_core == BMACSEC_CORE_UNKNOWN) || (macsec_dev_port_cnt <= 0) || \
    265             (macsec_mac == BMACSEC_MAC_CORE_UNKNOWN) || \
    266             (macsec_mmi_io == NULL)) {
    267         LOG_WARN(BSL_LS_SOC_COMMON,
    268                  (BSL_META_U(unit,
    269                              "MACSEC core, MAC or LMI iofu is not predefined!\n")));
    270     }
    271 
    272     /* call to bmacsec_dummyphy_phy_mac_addr_set() for assigning those macsec 
    273      * related address and id for MDIO access.
    274      *  Flow :
    275      *  1. assigning address mapping table between PHY/MAC/port.
    276      *  2. attaching MAC driver. (in UNIMAC/BIGMAC/XMAC)
    277      */
    278     rv = bmacsec_dummyphy_mac_addr_set(macsec_dev_idx, macsec_dev_addr,
    279            port_index, macsec_dev_port_cnt, macsec_mmi_io, macsec_mac); 
    280     if(rv != BMACSEC_E_NONE) {
    281         LOG_WARN(BSL_LS_SOC_COMMON,
    282                  (BSL_META_U(unit,
    283                              "bmacsec_phy_mac_addr_set returned error for u=%d p=%d\n"), 
    284                   unit, port));
    285         return SOC_E_INTERNAL;
    286     }
    287 
    288     if (macsec_enable) {
    289         /* init MACSEC's Line/Switch MAC */
    290         rv = bmacsec_dummyphy_mac_init(macsec_dev_idx, macsec_enable);
    291         if(rv != BMACSEC_E_NONE) {
    292             LOG_ERROR(BSL_LS_SOC_COMMON,
    293                       (BSL_META_U(unit,
    294                                   "failed on init MACSEC's MAC for u=%d p=%d\n"), 
    295                        unit, port));
    296             return SOC_E_INTERNAL;
    297         }
    298     }
    299     
    300     /* set MACSEC bypass control */
    301     rv = soc_macsecphy_dev_control_set(unit, port, 
    302             SOC_MACSECPHY_DEV_CONTROL_BYPASS, (macsec_enable ? FALSE : TRUE));
    303     if (!SOC_SUCCESS(rv)) {
    304         LOG_ERROR(BSL_LS_SOC_COMMON,
    305                   (BSL_META_U(unit,
    306                               "failed on setting MACSEC Bypass for u=%d p=%d\n"), 
    307                    unit, port));
    308         return SOC_E_INTERNAL;
    309     }
    310 
    311     /* performing common macsecphy init process */
    312     rv = soc_macsecphy_init(unit, port, pc, macsec_core, macsec_mmi_io);
    313  
    314     if (!SOC_SUCCESS(rv)) {
    315         LOG_ERROR(BSL_LS_SOC_COMMON,
    316                   (BSL_META_U(unit,
    317                               "soc_switchmacsec_init: MACSEC init for"
    318                               " u=%d p=%d FAILED\n"), unit, port));
    319     } else {
    320         LOG_INFO(BSL_LS_SOC_PHY,
    321                  (BSL_META_U(unit,
    322                              "soc_switchmacsec_init: MACSEC init for"
    323                              " u=%d p=%d SUCCESS\n"), unit, port));
    324     }
    325     return rv;
    326     
    327 }
    328 
    329 #endif /* BCM_SWITCHMACSEC_SUPPORT */
    330 
    331 /* The routine for control set/get is for the setting items which are unable 
    332  *  to be accessed in MACSEC's internal registers. Normally, this is for the 
    333  *  control on whole MACSEC unit like bypass, power-down or reset etc.
    334  *  
    335  *  This request normally is for MACSEC-in-SWITCH solution
    336  *  (i.e. NOPHY_MACSEC). And the reasons is MACSEC-in-PHY solution for the 
    337  *  purpose to control whole MACSEC unit can through PHY expanded regsiter. 
    338  *
    339  *  In current existed SDK solution(MACSEC-in-PHY solution), such contorl 
    340  *  set/get all implemented in each independent PHY driver already.
    341  */
    342 int 
    343 soc_macsecphy_dev_control_set(int unit, soc_port_t port, int type, uint32 value)
    344 {
    345     int rv = SOC_E_NONE;
    346     
    347     switch (type) {
    348     case SOC_MACSECPHY_DEV_CONTROL_BYPASS:
    349 
    350         rv = SOC_E_UNAVAIL;
    351         break;
    352     case SOC_MACSECPHY_DEV_CONTROL_POWERDOWN:
    353     case SOC_MACSECPHY_DEV_CONTROL_RESET:
    354         rv = SOC_E_UNAVAIL;
    355         break;
    356     default:
    357         rv = SOC_E_PARAM;
    358     }
    359     
    360     return rv;
    361 }
    362 
    363 int 
    364 soc_macsecphy_dev_control_get(int unit, soc_port_t port, int type, uint32 *value)
    365 {
    366     int rv = SOC_E_NONE;
    367     
    368     switch (type) {
    369     case SOC_MACSECPHY_DEV_CONTROL_BYPASS:
    370 
    371         rv = SOC_E_UNAVAIL;
    372         break;
    373     case SOC_MACSECPHY_DEV_CONTROL_POWERDOWN:
    374     case SOC_MACSECPHY_DEV_CONTROL_RESET:
    375         rv = SOC_E_UNAVAIL;
    376         break;
    377     default:
    378         rv = SOC_E_PARAM;
    379     }
    380     
    381     return rv;
    382 }
    383 
    384 /* Function : soc_macsecphy_dev_info_get() : 
    385  *  - for the purpose to report the MACSEC related information.
    386  *
    387  * Parameters :
    388  *  - port      : the switch port ID.
    389  *  - type      : information type
    390  *  - value     : (OUTPUT) value for this information type
    391  */
    392 int 
    393 soc_macsecphy_dev_info_get(int unit, soc_port_t port, int type, uint32 *value)
    394 {
    395     int     rv = SOC_E_NONE;
    396 
    397     switch (type) {
    398     case SOC_MACSECPHY_DEV_INFO_SWITCHMACSEC_ATTACHED:
    399         *value = FALSE;
    400         
    401 
    402         break;
    403     default:
    404         rv = SOC_E_PARAM;
    405     }
    406 
    407     return rv;
    408 }
    409 
    410 #else /* INCLUDE_MACSEC */
    411 
    412 int 
    413 soc_macsecphy_init(int unit, soc_port_t port, void *pc)
    414 {
    415     return SOC_E_NONE;
    416 }
    417 #endif /* INCLUDE_MACSEC */
    418