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

portctrl.c (13595B)


      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  * portctrl soc routines
      8  */
      9 
     10 #include <sal/core/libc.h>
     11 
     12 #include <soc/debug.h>
     13 #include <soc/util.h>
     14 #include <soc/mem.h>
     15 #include <soc/esw/portctrl.h>
     16 #include <soc/esw/portctrl_internal.h>
     17 #include <soc/greyhound.h>
     18 #include <shared/bsl.h>
     19 #include <soc/phy/phymod_sim.h>
     20 #include <soc/portmod/portmod.h>
     21 
     22 #ifdef BCM_GREYHOUND_SUPPORT
     23 #define SOC_GH_PM4X10_COUNT         6
     24 #define SOC_GH_PM4X10_PORT_0        02
     25 #define SOC_GH_PM4X10_PORT_1        18
     26 #define SOC_GH_PM4X10_PORT_2        22
     27 #define SOC_GH_PM4X10_PORT_3        26
     28 #define SOC_GH_PM4X10_PORT_4        30
     29 #define SOC_GH_PM4X10_PORT_5        34
     30 
     31 static uint32_t _gh_addr[SOC_GH_PM4X10_COUNT] = {
     32     0x81, 0xA1, 0xA5, 0xA9, 0xAD, 0xB1};
     33 
     34 static uint32_t _gh_port[SOC_GH_PM4X10_COUNT] = {
     35     SOC_GH_PM4X10_PORT_0,
     36     SOC_GH_PM4X10_PORT_1,
     37     SOC_GH_PM4X10_PORT_2,
     38     SOC_GH_PM4X10_PORT_3,
     39     SOC_GH_PM4X10_PORT_4,
     40     SOC_GH_PM4X10_PORT_5,
     41 };
     42 
     43 portmod_pm_instances_t gh_pm_types[] = {
     44 #ifdef PORTMOD_PM4X10_SUPPORT
     45     {portmodDispatchTypePm4x10,  SOC_GH_PM4X10_COUNT},
     46 #endif
     47 };
     48 
     49 #define SOC_GH_MAX_PHYS              160   /* 128 XLMACS, 32 CLMAC's */
     50 
     51 #ifdef PORTMOD_PM4X10_SUPPORT
     52 static portmod_default_user_access_t *pm4x10_gh_user_acc[SOC_MAX_NUM_DEVICES];
     53 #endif /* PORTMOD_PM4X10_SUPPORT */
     54 
     55 soc_portctrl_functions_t soc_gh_portctrl_func = {
     56     soc_gh_portctrl_pm_portmod_init,
     57     soc_gh_portctrl_pm_portmod_deinit,
     58     NULL, /*soc_portctrl_pm_port_config_get*/
     59     NULL, /*soc_portctrl_pm_port_phyaddr_get*/
     60     NULL, /*soc_portctrl_port_ability_update*/
     61     NULL, /*soc_portctrl_pm_type_get*/
     62     NULL,
     63     NULL
     64 };
     65 
     66 STATIC int
     67 _soc_gh_portctrl_pm_init(int unit, int *max_phys,
     68                          portmod_pm_instances_t **pm_types,
     69                          int *pms_arr_len)
     70 {
     71     *max_phys = SOC_GH_MAX_PHYS;
     72     *pm_types = gh_pm_types;
     73     *pms_arr_len = sizeof(gh_pm_types)/sizeof(portmod_pm_instances_t);
     74     return SOC_E_NONE;
     75 }
     76 
     77 STATIC int
     78 _soc_gh_portctrl_device_addr_port_get(int unit, int pm_type,
     79                                       uint32_t **addr,
     80                                       uint32_t **port,
     81                                       uint32_t **core_num)
     82 {
     83     *addr = _gh_addr;
     84     *port = _gh_port;
     85     *core_num = NULL;
     86     return SOC_E_NONE;
     87 }
     88 
     89 STATIC int
     90 _soc_gh_portctrl_pm_user_acc_flag_set(int unit,
     91                     portmod_default_user_access_t* pm_user_access)
     92 {
     93     PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_SET((pm_user_access));
     94     return SOC_E_NONE;
     95 }
     96 
     97 STATIC int
     98 _soc_gh_portctrl_pm4x10_portmod_init(int unit, int num_of_instances) 
     99 {
    100 #ifdef PORTMOD_PM4X10_SUPPORT
    101     int rv = SOC_E_NONE;
    102     portmod_pm_create_info_t pm_info;
    103     int pmid = 0, blk, is_sim, lane, phy, found, logical_port;
    104     int first_port, idx, ref_clk_prop = 0, core_num, core_cnt;
    105     uint32 txlane_map, rxlane_map, *pAddr, *pPort, *pCoreNum;
    106     uint32 tx_polarity, rx_polarity;
    107 
    108     SOC_IF_ERROR_RETURN
    109         (_soc_gh_portctrl_device_addr_port_get(unit,
    110                                                portmodDispatchTypePm4x10,
    111                                             &pAddr, &pPort, &pCoreNum));
    112     if (!pAddr || !pPort) {
    113         return SOC_E_INTERNAL;
    114     }
    115 
    116     /* Allocate PMs */
    117     SOC_IF_ERROR_RETURN
    118         (soc_esw_portctrl_pm_user_access_alloc(unit,
    119                                            num_of_instances,
    120                                                &pm4x10_gh_user_acc[unit]));
    121 
    122     for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) {
    123 
    124         rv = portmod_pm_create_info_t_init(unit, &pm_info);
    125         if (PORTMOD_FAILURE(rv)) {
    126             break;
    127         }
    128         /* PM info */
    129         first_port = pPort[pmid];
    130 
    131         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port);
    132         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1);
    133         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2);
    134         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3);
    135 
    136         found = 0;
    137         for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){
    138             blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk;
    139             if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT){
    140                 found = 1;
    141                 break;
    142             }
    143         }
    144 
    145         if (!found) {
    146             rv = SOC_E_INTERNAL;
    147             break;
    148         } 
    149 
    150         pm_info.type         = portmodDispatchTypePm4x10;
    151 
    152         /* Init user_acc for phymod access struct */
    153         rv = portmod_default_user_access_t_init(unit,
    154                                                 &(pm4x10_gh_user_acc[unit][pmid]));
    155         if (PORTMOD_FAILURE(rv)) {
    156             break;
    157         }
    158 
    159         SOC_IF_ERROR_RETURN(
    160             _soc_gh_portctrl_pm_user_acc_flag_set(unit,
    161                 &(pm4x10_gh_user_acc[unit][pmid])));
    162 
    163         pm4x10_gh_user_acc[unit][pmid].unit = unit;
    164         pm4x10_gh_user_acc[unit][pmid].blk_id = blk; 
    165         pm4x10_gh_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex");
    166         if (pm4x10_gh_user_acc[unit][pmid].mutex == NULL) {
    167             rv = SOC_E_MEMORY;
    168             break;
    169         }
    170 
    171         /* Specific info for PM4x10 */
    172         rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x10.access);
    173         if (PORTMOD_FAILURE(rv)) {
    174             break;
    175         }
    176 
    177         pm_info.pm_specific_info.pm4x10.access.user_acc =
    178             &(pm4x10_gh_user_acc[unit][pmid]);
    179         pm_info.pm_specific_info.pm4x10.access.addr     = pAddr[pmid];
    180         pm_info.pm_specific_info.pm4x10.access.bus      = NULL; /* Use default bus */
    181 
    182         rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce,
    183                                   &(pm_info.pm_specific_info.pm4x10.access),
    184                                   0, &is_sim);
    185         if (PORTMOD_FAILURE(rv)) {
    186             break;
    187         }
    188 
    189         if (is_sim) {
    190             pm_info.pm_specific_info.pm4x10.access.bus->bus_capabilities |=
    191                 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL);
    192 
    193             /* Firmward loader : Don't allow FW load on sim enviroment */
    194             pm_info.pm_specific_info.pm4x10.fw_load_method =
    195                 phymodFirmwareLoadMethodNone;
    196         } else {
    197             pm_info.pm_specific_info.pm4x10.fw_load_method =
    198                 soc_property_suffix_num_get(unit, pmid, 
    199                                             spn_LOAD_FIRMWARE, "quad",
    200                                             phymodFirmwareLoadMethodExternal);
    201             pm_info.pm_specific_info.pm4x10.fw_load_method &= 0xff;
    202         }
    203 
    204         /* Use default external loader if NULL */
    205         pm_info.pm_specific_info.pm4x10.external_fw_loader = NULL;
    206 
    207        rv = phymod_polarity_t_init
    208             (&(pm_info.pm_specific_info.pm4x10.polarity));
    209         if (PORTMOD_FAILURE(rv)) {
    210             break;
    211         }
    212 
    213         /* Polarity */
    214         for (lane = 0; lane < SOC_PM4X10_NUM_LANES; lane++) {
    215             /* need to add more conditions */
    216             phy = first_port+lane;
    217             rx_polarity =  soc_property_suffix_num_get(unit, phy,
    218                             spn_PHY_RX_POLARITY_FLIP, "phy", 0xFFFFFFFF);
    219             tx_polarity = soc_property_suffix_num_get(unit, phy,
    220                             spn_PHY_TX_POLARITY_FLIP, "phy", 0xFFFFFFFF); 
    221                                
    222             logical_port = SOC_INFO(unit).port_p2l_mapping[phy];
    223 
    224             if (rx_polarity  == 0xFFFFFFFF) {
    225                 rx_polarity = soc_property_port_get(unit, logical_port,
    226                                            spn_PHY_RX_POLARITY_FLIP, 0);
    227                 pm_info.pm_specific_info.pm4x10.polarity.rx_polarity
    228                             |= rx_polarity;
    229             } else {
    230                 pm_info.pm_specific_info.pm4x10.polarity.rx_polarity
    231                             |= ((rx_polarity & 0x1) << lane);
    232             }             
    233 
    234             if (tx_polarity  == 0xFFFFFFFF) {
    235                 tx_polarity = soc_property_port_get(
    236                                            unit, logical_port,
    237                                            spn_PHY_TX_POLARITY_FLIP, 0);
    238                 pm_info.pm_specific_info.pm4x10.polarity.tx_polarity
    239                             |= tx_polarity;
    240             } else {
    241                 pm_info.pm_specific_info.pm4x10.polarity.tx_polarity
    242                             |= ((tx_polarity & 0x1) << lane);
    243             }
    244         }
    245 
    246         /* Lane map */
    247         rv = phymod_lane_map_t_init
    248             (&(pm_info.pm_specific_info.pm4x10.lane_map));
    249         if (PORTMOD_FAILURE(rv)) {
    250             break;
    251         }
    252 
    253         logical_port = SOC_INFO(unit).port_p2l_mapping[first_port];
    254         core_cnt = 1; 
    255 
    256         for (core_num = 0; core_num < core_cnt; core_num++) {
    257             txlane_map = soc_property_port_suffix_num_get(unit, logical_port,
    258                                                      core_num,
    259                                                      spn_XGXS_TX_LANE_MAP,
    260                                                      "core", 0x3210);
    261             rxlane_map = soc_property_port_suffix_num_get(unit, logical_port,
    262                                                      core_num,
    263                                                      spn_XGXS_RX_LANE_MAP,
    264                                                      "core", 0x3210);
    265 
    266 #ifdef _PORTMOD_VERBOSE_
    267             soc_esw_portctrl_dump_txrx_lane_map(unit, first_port, logical_port,
    268                                 core_num, txlane_map, rxlane_map,
    269                                 txlane_map, rxlane_map);
    270 #endif /* _PORTMOD_VERBOSE_ */
    271             pm_info.pm_specific_info.pm4x10.lane_map.num_of_lanes =
    272                 SOC_PM4X10_NUM_LANES;
    273     
    274             pm_info.pm_specific_info.pm4x10.core_num = pCoreNum? pCoreNum[pmid] : pmid;
    275             pm_info.pm_specific_info.pm4x10.core_num_int = 0;
    276             pm_info.pm_specific_info.pm4x10.rescal = -1;
    277 
    278             for(lane=0 ; lane<SOC_PM4X10_NUM_LANES; lane++) {
    279                 pm_info.pm_specific_info.pm4x10.lane_map.lane_map_tx[lane] =  
    280                     (txlane_map >> (lane * SOC_PM4X10_NUM_LANES)) &
    281                     SOC_PM4X10_LANE_MASK;
    282                 pm_info.pm_specific_info.pm4x10.lane_map.lane_map_rx[lane] =  
    283                     (rxlane_map >> (lane * SOC_PM4X10_NUM_LANES)) &
    284                     SOC_PM4X10_LANE_MASK;
    285             }
    286         }
    287 
    288         ref_clk_prop = soc_property_port_get(unit, first_port,
    289                                  spn_XGXS_LCPLL_XTAL_REFCLK, phymodRefClk156Mhz);
    290 
    291         if ((ref_clk_prop == 125) ||( ref_clk_prop == 1))
    292             pm_info.pm_specific_info.pm4x10.ref_clk = phymodRefClk125Mhz;
    293         else      /* ((ref_clk_prop == 156) ||( ref_clk_prop == 0)) */
    294             pm_info.pm_specific_info.pm4x10.ref_clk = phymodRefClk156Mhz;
    295 
    296         pm_info.pm_specific_info.pm4x10.portmod_phy_external_reset
    297             = soc_esw_portctrl_reset_tsc3_cb;
    298 
    299         /* Add PM to PortMod */
    300         rv = portmod_port_macro_add(unit, &pm_info);
    301     }
    302 
    303     if (PORTMOD_FAILURE(rv)) {
    304         for (pmid=0; pmid < num_of_instances; pmid++) {
    305             if (pm4x10_gh_user_acc[unit][pmid].mutex) {
    306                 sal_mutex_destroy(pm4x10_gh_user_acc[unit][pmid].mutex);
    307                 pm4x10_gh_user_acc[unit][pmid].mutex = NULL;
    308             }
    309         }
    310     }
    311 
    312     return rv;
    313 #else /* PORTMOD_PM4X10_SUPPORT */
    314     return SOC_E_UNAVAIL;
    315 #endif /* PORTMOD_PM4X10_SUPPORT */
    316 }
    317 
    318 /*
    319  * Function:
    320  *      soc_gh_portctrl_pm_portmod_init
    321  * Purpose:
    322  *      Initialize PortMod and PortMacro for Greyhound. 
    323  *      Add port macros (PM) to the unit's PortMod Manager (PMM).
    324  * Parameters:
    325  *      unit             - (IN) Unit number.
    326  * Returns:
    327  *      SOC_E_XXX
    328  */
    329 int
    330 soc_gh_portctrl_pm_portmod_init(int unit)
    331 {
    332     int rv = SOC_E_NONE, pms_arr_len = 0, count, max_phys= 0;
    333     portmod_pm_instances_t *pm_types = NULL;
    334 
    335     /* Call PortMod library initialization */
    336     SOC_IF_ERROR_RETURN(
    337         _soc_gh_portctrl_pm_init(unit, &max_phys,
    338                                         &pm_types, &pms_arr_len));
    339     if (pms_arr_len == 0) {
    340         return SOC_E_UNAVAIL;
    341     }
    342 
    343     /*
    344      * If portmod was create - destroy and create again
    345      * Better way would be to create once and leave it.
    346      */
    347     if (SOC_E_NONE == soc_esw_portctrl_init_check(unit)) {
    348         SOC_IF_ERROR_RETURN(portmod_destroy(unit));
    349     }
    350 
    351     SOC_IF_ERROR_RETURN
    352         (portmod_create(unit, 0, SOC_MAX_NUM_PORTS, max_phys,
    353                         pms_arr_len, pm_types));
    354 
    355     for (count = 0; SOC_SUCCESS(rv) && (count < pms_arr_len); count++) {
    356 #ifdef PORTMOD_PM4X10_SUPPORT
    357         if (pm_types[count].type == portmodDispatchTypePm4x10) {
    358             rv = _soc_gh_portctrl_pm4x10_portmod_init
    359                 (unit, pm_types[count].instances);
    360         } else
    361 #endif
    362         {
    363             rv = SOC_E_INTERNAL;
    364         }
    365     }
    366 
    367     return rv;
    368 }
    369 
    370 /*
    371  * Function:
    372  *      soc_gh_portctrl_pm_portmod_deinit
    373  * Purpose:
    374  *      Deinitialize PortMod and PortMacro for Greyhound. 
    375  *      Free pm user access data.
    376  * Parameters:
    377  *      unit      - (IN) Unit number.
    378  * Returns:
    379  *      SOC_E_NONE
    380  */
    381 int
    382 soc_gh_portctrl_pm_portmod_deinit(int unit)
    383 {
    384     if (SOC_E_INIT == soc_esw_portctrl_init_check(unit)) {
    385         return SOC_E_NONE;
    386     }
    387 
    388     /* Free PMs structures */
    389 #ifdef PORTMOD_PM4X10_SUPPORT
    390     if (pm4x10_gh_user_acc[unit] != NULL) {
    391         sal_free(pm4x10_gh_user_acc[unit]);
    392     }
    393 #endif /* PORTMOD_PM4X10_SUPPORT */
    394     return SOC_E_NONE;
    395 }
    396 
    397 #endif /* BCM_GREYHOUND_SUPPORT */
    398