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 (27701B)


      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 <shared/bsl.h>
     11 
     12 #include <sal/core/libc.h>
     13 
     14 #include <soc/debug.h>
     15 #include <soc/util.h>
     16 #include <soc/mem.h>
     17 #include <soc/esw/portctrl.h>
     18 #include <soc/esw/portctrl_internal.h>
     19 #include <soc/tomahawk.h>
     20 #include <soc/phy/phymod_sim.h>
     21 #include <soc/portmod/portmod.h>
     22 
     23 #ifdef BCM_TOMAHAWK_SUPPORT
     24 #define SOC_TH_PM4X10_COUNT         1
     25 #define SOC_TH_PM4X25_COUNT         32 
     26 
     27 #define SOC_TH_PM4X10_PORT_1        129  /* xe0 = 66, xe1 = 100 */
     28 
     29 static uint32_t _th_pm4x10_addr[SOC_TH_PM4X10_COUNT] = { 0x1C1 };
     30 static uint32_t _th_pm4x10_port[SOC_TH_PM4X10_COUNT] = { SOC_TH_PM4X10_PORT_1};
     31 
     32 #define SOC_TH_PM4X25_PORT_1        1
     33 #define SOC_TH_PM4X25_PORT_2        5
     34 #define SOC_TH_PM4X25_PORT_3        9
     35 #define SOC_TH_PM4X25_PORT_4        13
     36 #define SOC_TH_PM4X25_PORT_5        17
     37 #define SOC_TH_PM4X25_PORT_6        21
     38 #define SOC_TH_PM4X25_PORT_7        25
     39 #define SOC_TH_PM4X25_PORT_8        29
     40 #define SOC_TH_PM4X25_PORT_9        33
     41 #define SOC_TH_PM4X25_PORT_10       37
     42 #define SOC_TH_PM4X25_PORT_11       41
     43 #define SOC_TH_PM4X25_PORT_12       45
     44 #define SOC_TH_PM4X25_PORT_13       49
     45 #define SOC_TH_PM4X25_PORT_14       53
     46 #define SOC_TH_PM4X25_PORT_15       57
     47 #define SOC_TH_PM4X25_PORT_16       61
     48 #define SOC_TH_PM4X25_PORT_17       65
     49 #define SOC_TH_PM4X25_PORT_18       69
     50 #define SOC_TH_PM4X25_PORT_19       73
     51 #define SOC_TH_PM4X25_PORT_20       77
     52 #define SOC_TH_PM4X25_PORT_21       81
     53 #define SOC_TH_PM4X25_PORT_22       85
     54 #define SOC_TH_PM4X25_PORT_23       89
     55 #define SOC_TH_PM4X25_PORT_24       93
     56 #define SOC_TH_PM4X25_PORT_25       97
     57 #define SOC_TH_PM4X25_PORT_26       101
     58 #define SOC_TH_PM4X25_PORT_27       105
     59 #define SOC_TH_PM4X25_PORT_28       109
     60 #define SOC_TH_PM4X25_PORT_29       113
     61 #define SOC_TH_PM4X25_PORT_30       117
     62 #define SOC_TH_PM4X25_PORT_31       121
     63 #define SOC_TH_PM4X25_PORT_32       125
     64 
     65 static uint32_t _th_pm4x25_addr[SOC_TH_PM4X25_COUNT] = {
     66     0x81,  0x85,  0x89,  0x8D,
     67     0x91,  0x95,  0xA1,  0xA5,
     68     0xA9,  0xAD,  0xc1,  0xC5,
     69     0xC9,  0xCD,  0xD1,  0xD5,
     70     0xE1,  0xE5,  0xE9,  0xED,
     71     0xF1,  0xF5,  0x181, 0x185,
     72     0x189, 0x18D, 0x1A1, 0x1A5,
     73     0x1A9, 0x1AD, 0x1B1, 0x1B5
     74 };
     75 
     76 static uint32_t _th_pm4x25_core_num[SOC_TH_PM4X25_COUNT] = {
     77     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
     78 
     79 static uint32_t _th_pm4x10_core_num[SOC_TH_PM4X10_COUNT] = {32};
     80 
     81 static uint32_t _th_pm4x25_port[SOC_TH_PM4X25_COUNT] = {
     82     SOC_TH_PM4X25_PORT_1,  SOC_TH_PM4X25_PORT_2,
     83     SOC_TH_PM4X25_PORT_3,  SOC_TH_PM4X25_PORT_4,
     84     SOC_TH_PM4X25_PORT_5,  SOC_TH_PM4X25_PORT_6,
     85     SOC_TH_PM4X25_PORT_7,  SOC_TH_PM4X25_PORT_8,
     86     SOC_TH_PM4X25_PORT_9,  SOC_TH_PM4X25_PORT_10,
     87     SOC_TH_PM4X25_PORT_11, SOC_TH_PM4X25_PORT_12,
     88     SOC_TH_PM4X25_PORT_13, SOC_TH_PM4X25_PORT_14,
     89     SOC_TH_PM4X25_PORT_15, SOC_TH_PM4X25_PORT_16,
     90     SOC_TH_PM4X25_PORT_17, SOC_TH_PM4X25_PORT_18,
     91     SOC_TH_PM4X25_PORT_19, SOC_TH_PM4X25_PORT_20,
     92     SOC_TH_PM4X25_PORT_21, SOC_TH_PM4X25_PORT_22,
     93     SOC_TH_PM4X25_PORT_23, SOC_TH_PM4X25_PORT_24,
     94     SOC_TH_PM4X25_PORT_25, SOC_TH_PM4X25_PORT_26,
     95     SOC_TH_PM4X25_PORT_27, SOC_TH_PM4X25_PORT_28,
     96     SOC_TH_PM4X25_PORT_29, SOC_TH_PM4X25_PORT_30,
     97     SOC_TH_PM4X25_PORT_31, SOC_TH_PM4X25_PORT_32
     98 };
     99 
    100 portmod_pm_instances_t th_pm_types[] = {
    101 #ifdef PORTMOD_PM4X10_SUPPORT
    102     {portmodDispatchTypePm4x10,  SOC_TH_PM4X10_COUNT}, 
    103 #endif
    104 #ifdef PORTMOD_PM4X25_SUPPORT
    105     {portmodDispatchTypePm4x25, SOC_TH_PM4X25_COUNT},
    106 #endif
    107 };  
    108 
    109 #define SOC_TH_MAX_PHYS               164    /* ((32+1)x4)  132 XLMACS, 32 CLMAC's */
    110 
    111 #ifdef PORTMOD_PM4X10_SUPPORT
    112 static portmod_default_user_access_t *pm4x10_th_user_acc[SOC_MAX_NUM_DEVICES];
    113 #endif /* PORTMOD_PM4X10_SUPPORT */
    114 
    115 #ifdef PORTMOD_PM4X25_SUPPORT
    116 static portmod_default_user_access_t *pm4x25_th_user_acc[SOC_MAX_NUM_DEVICES];
    117 #endif /* PORTMOD_PM4X25_SUPPORT */
    118 
    119 soc_portctrl_functions_t soc_th_portctrl_func = {
    120     soc_th_portctrl_pm_portmod_init,
    121     soc_th_portctrl_pm_portmod_deinit,
    122     NULL, /*soc_portctrl_pm_port_config_get*/
    123     soc_th_portctrl_pm_port_phyaddr_get,
    124     NULL, /* soc_portctrl_port_ability_update*/
    125     NULL, /* soc_portctrl_pm_type_get*/
    126     NULL,
    127     NULL
    128 };
    129 
    130 STATIC int
    131 _soc_th_portctrl_pm_init(int unit, int *max_phys,
    132                          portmod_pm_instances_t **pm_types,
    133                          int *pms_arr_len)
    134 {
    135     *max_phys = SOC_TH_MAX_PHYS;
    136     *pm_types = th_pm_types;
    137     *pms_arr_len = sizeof(th_pm_types)/sizeof(portmod_pm_instances_t);
    138     return SOC_E_NONE;
    139 }
    140 
    141 STATIC int
    142 _soc_th_portctrl_device_addr_port_get(int unit, int pm_type,
    143                                       uint32_t **addr,
    144                                       uint32_t **port,
    145                                       uint32_t **core_num)
    146 {
    147     *addr     = NULL;
    148     *port     = NULL;
    149     *core_num = NULL;
    150 
    151 #ifdef PORTMOD_PM4X10_SUPPORT
    152     if (pm_type == portmodDispatchTypePm4x10) {
    153         *addr = _th_pm4x10_addr;
    154         *port = _th_pm4x10_port;
    155         *core_num = _th_pm4x10_core_num;
    156     } 
    157 #endif
    158 #ifdef PORTMOD_PM4X25_SUPPORT
    159     if (pm_type == portmodDispatchTypePm4x25){
    160         *addr = _th_pm4x25_addr;
    161         *port = _th_pm4x25_port;
    162         *core_num = _th_pm4x25_core_num;
    163     }
    164 #endif
    165 
    166     return SOC_E_NONE;
    167 }
    168 
    169 STATIC int
    170 _soc_th_portctrl_pm_user_acc_flag_set(int unit,
    171                     portmod_default_user_access_t* pm_user_access)
    172 {
    173     PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((pm_user_access));
    174     PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_CLR((pm_user_access));
    175     return SOC_E_NONE;
    176 }
    177 
    178 /*
    179  * Polarity get looks for physical port based config first. This will enable
    180  * the user to define the polarity for all ports weather mapped to logical 
    181  * port or not.
    182  *
    183  * For legacy compatibility - we still look for the logical port
    184  * config setup.
    185  */
    186 STATIC void
    187 _soc_th_portctrl_pm_port_polarity_get
    188            (int unit, int logical_port, int physical_port, int lane,
    189             uint32 *tx_pol, uint32* rx_pol)
    190 {
    191     uint32 rx_polarity, tx_polarity, num_lanes = 1;
    192 
    193     if (logical_port != -1) {
    194         num_lanes = SOC_INFO(unit).port_num_lanes[logical_port];
    195     }
    196 
    197     rx_polarity = soc_property_phy_get (unit, physical_port, 0, 0, lane, 
    198                                         spn_PHY_RX_POLARITY_FLIP, 0xFFFFFFFF); 
    199 
    200     if (rx_polarity == 0xFFFFFFFF) {
    201         rx_polarity = soc_property_port_get(unit, logical_port,
    202                        spn_PHY_XAUI_RX_POLARITY_FLIP, 0x0);
    203         *rx_pol = (num_lanes == 1) ? ((rx_polarity & 0x1) << lane): rx_polarity;
    204     } else {
    205         *rx_pol = (rx_polarity & 0x1) << lane;
    206     }
    207 
    208     tx_polarity = soc_property_phy_get (unit, physical_port, 0, 0, lane, 
    209                                         spn_PHY_TX_POLARITY_FLIP, 0xFFFFFFFF); 
    210     if (tx_polarity == 0xFFFFFFFF) {
    211         tx_polarity =  soc_property_port_get(unit, logical_port,
    212                           spn_PHY_XAUI_TX_POLARITY_FLIP, 0x0);
    213         *tx_pol = (num_lanes == 1) ? ((tx_polarity & 0x1) << lane) : tx_polarity;
    214     } else {
    215         *tx_pol = (tx_polarity & 0x1) << lane;
    216     }
    217 
    218 }
    219 
    220 /*
    221  * lanemap get looks for physical port based config first. This will enable
    222  * the user to define the lanemap for all ports weather mapped to logical 
    223  * port or not.
    224  *
    225  * For legacy compatibility - we still look for the logical port
    226  * config setup.
    227  */
    228 STATIC 
    229 void _soc_th_portctrl_pm_port_lanemap_get
    230             (int unit, int logical_port, int physical_port, int core_num, 
    231             uint32 *txlane_map, uint32* rxlane_map)
    232 {
    233 
    234     *rxlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 
    235                                         spn_PHY_RX_LANE_MAP, 0xFFFFFFFF);
    236 
    237     if (*rxlane_map == 0xFFFFFFFF) {
    238         *rxlane_map = soc_property_port_suffix_num_get(unit, logical_port, 
    239                                         core_num, spn_XGXS_RX_LANE_MAP,
    240                                         "core", 0x3210);
    241     }
    242 
    243     *txlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 
    244                                         spn_PHY_TX_LANE_MAP, 0xFFFFFFFF);
    245 
    246     if (*txlane_map == 0xFFFFFFFF) {
    247         *txlane_map = soc_property_port_suffix_num_get(unit, logical_port, 
    248                                         core_num, spn_XGXS_TX_LANE_MAP,
    249                                         "core", 0x3210);
    250     }
    251 }
    252 
    253 STATIC int
    254 _soc_th_portctrl_pm4x10_portmod_init(int unit, int num_of_instances) 
    255 {
    256 #ifdef PORTMOD_PM4X10_SUPPORT
    257     int rv = SOC_E_NONE;
    258     portmod_pm_create_info_t pm_info;
    259     int pmid = 0, blk, is_sim, lane, phy, found, logical_port;
    260     int first_port, idx, ref_clk_prop = 0, core_num, core_cnt;
    261     uint32 txlane_map, rxlane_map, *pAddr, *pPort, *pCoreNum;
    262     uint32 tx_polarity, rx_polarity;
    263 
    264     SOC_IF_ERROR_RETURN
    265         (_soc_th_portctrl_device_addr_port_get(unit,
    266                                                portmodDispatchTypePm4x10,
    267                                                &pAddr, &pPort, &pCoreNum));
    268     if (!pAddr || !pPort) {
    269         return SOC_E_INTERNAL;
    270     }
    271 
    272     /* Allocate PMs */
    273     SOC_IF_ERROR_RETURN
    274         (soc_esw_portctrl_pm_user_access_alloc(unit,
    275                                            num_of_instances,
    276                                            &pm4x10_th_user_acc[unit]));
    277 
    278     for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) {
    279 
    280         rv = portmod_pm_create_info_t_init(unit, &pm_info);
    281         if (PORTMOD_FAILURE(rv)) {
    282             break;
    283         }
    284         /* PM info */
    285         first_port = pPort[pmid];
    286 
    287         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port);
    288         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1);
    289         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2);
    290         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3);
    291 
    292         found = 0;
    293         for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){
    294             blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk;
    295             if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT){
    296                 found = 1;
    297                 break;
    298             }
    299         }
    300 
    301         if (!found) {
    302             rv = SOC_E_INTERNAL;
    303             break;
    304         } 
    305 
    306         pm_info.type         = portmodDispatchTypePm4x10;
    307 
    308         /* Init user_acc for phymod access struct */
    309         rv = portmod_default_user_access_t_init(unit,
    310                                                 &(pm4x10_th_user_acc[unit][pmid]));
    311         if (PORTMOD_FAILURE(rv)) {
    312             break;
    313         }
    314 
    315         SOC_IF_ERROR_RETURN(
    316             _soc_th_portctrl_pm_user_acc_flag_set(unit,
    317                 &(pm4x10_th_user_acc[unit][pmid])));
    318 
    319         pm4x10_th_user_acc[unit][pmid].unit = unit;
    320         pm4x10_th_user_acc[unit][pmid].blk_id = blk; 
    321         pm4x10_th_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex");
    322         if (pm4x10_th_user_acc[unit][pmid].mutex == NULL) {
    323             rv = SOC_E_MEMORY;
    324             break;
    325         }
    326 
    327         /* Specific info for PM4x10 */
    328         rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x10.access);
    329         if (PORTMOD_FAILURE(rv)) {
    330             break;
    331         }
    332 
    333         pm_info.pm_specific_info.pm4x10.access.user_acc =
    334             &(pm4x10_th_user_acc[unit][pmid]);
    335         pm_info.pm_specific_info.pm4x10.access.addr     = pAddr[pmid];
    336         pm_info.pm_specific_info.pm4x10.access.bus      = NULL; /* Use default bus */
    337 
    338         rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce,
    339                                   &(pm_info.pm_specific_info.pm4x10.access),
    340                                   0, &is_sim);
    341         if (PORTMOD_FAILURE(rv)) {
    342             break;
    343         }
    344 
    345         if (is_sim) {
    346             pm_info.pm_specific_info.pm4x10.access.bus->bus_capabilities |=
    347                 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL);
    348 
    349             /* Firmward loader : Don't allow FW load on sim enviroment */
    350             pm_info.pm_specific_info.pm4x10.fw_load_method =
    351                 phymodFirmwareLoadMethodNone;
    352         } else {
    353             pm_info.pm_specific_info.pm4x10.fw_load_method =
    354                 soc_property_suffix_num_get(unit, pmid, 
    355                                             spn_LOAD_FIRMWARE, "quad",
    356                                             phymodFirmwareLoadMethodExternal);
    357             pm_info.pm_specific_info.pm4x10.fw_load_method &= 0xff;
    358         }
    359 
    360         /* Use default external loader if NULL */
    361         pm_info.pm_specific_info.pm4x10.external_fw_loader = NULL;
    362 
    363        /* Polarity */
    364        rv = phymod_polarity_t_init
    365             (&(pm_info.pm_specific_info.pm4x10.polarity));
    366         if (PORTMOD_FAILURE(rv)) {
    367             break;
    368         }
    369 
    370         for (lane = 0; lane < SOC_PM4X10_NUM_LANES; lane++) {
    371             phy = first_port+lane;
    372             logical_port = SOC_INFO(unit).port_p2l_mapping[phy];
    373 
    374             _soc_th_portctrl_pm_port_polarity_get
    375                 (unit, logical_port, phy, lane, &tx_polarity, &rx_polarity);
    376 
    377             pm_info.pm_specific_info.pm4x10.polarity.rx_polarity |= rx_polarity;
    378             pm_info.pm_specific_info.pm4x10.polarity.tx_polarity |= tx_polarity;
    379 
    380             if (SOC_INFO(unit).port_num_lanes[logical_port] >= SOC_PM4X10_NUM_LANES) break; 
    381         }
    382 
    383         /* Lane map */
    384         rv = phymod_lane_map_t_init
    385             (&(pm_info.pm_specific_info.pm4x10.lane_map));
    386         if (PORTMOD_FAILURE(rv)) {
    387             break;
    388         }
    389 
    390         logical_port = SOC_INFO(unit).port_p2l_mapping[first_port];
    391         core_cnt = 1; 
    392 
    393         for (core_num = 0; core_num < core_cnt; core_num++) {
    394             _soc_th_portctrl_pm_port_lanemap_get
    395                 (unit, logical_port, first_port, core_num, &txlane_map, &rxlane_map);
    396             
    397             /* possible internal swap to be added */
    398 
    399 #ifdef _PORTMOD_VERBOSE_
    400             soc_esw_portctrl_dump_txrx_lane_map(unit, first_port, logical_port,
    401                                 core_num, txlane_map, rxlane_map,
    402                                 txlane_map, rxlane_map);
    403 #endif /* _PORTMOD_VERBOSE_ */
    404             pm_info.pm_specific_info.pm4x10.lane_map.num_of_lanes =
    405                 SOC_PM4X10_NUM_LANES;
    406     
    407             pm_info.pm_specific_info.pm4x10.core_num = pCoreNum? pCoreNum[pmid] : pmid;
    408             pm_info.pm_specific_info.pm4x10.core_num_int = 0;
    409             pm_info.pm_specific_info.pm4x10.rescal = -1;
    410 
    411             for(lane=0 ; lane<SOC_PM4X10_NUM_LANES; lane++) {
    412                 pm_info.pm_specific_info.pm4x10.lane_map.lane_map_tx[lane] =  
    413                     (txlane_map >> (lane * SOC_PM4X10_NUM_LANES)) &
    414                     SOC_PM4X10_LANE_MASK;
    415                 pm_info.pm_specific_info.pm4x10.lane_map.lane_map_rx[lane] =  
    416                     (rxlane_map >> (lane * SOC_PM4X10_NUM_LANES)) &
    417                     SOC_PM4X10_LANE_MASK;
    418             }
    419         }
    420 
    421         ref_clk_prop = soc_property_port_get(unit, first_port,
    422                                 spn_XGXS_LCPLL_XTAL_REFCLK, 156);
    423 
    424         if ((ref_clk_prop == 156) ||( ref_clk_prop == 1)){
    425             pm_info.pm_specific_info.pm4x10.ref_clk = phymodRefClk156Mhz;
    426         }
    427         else if (ref_clk_prop == 125){     
    428             pm_info.pm_specific_info.pm4x10.ref_clk = phymodRefClk125Mhz;
    429         }
    430         else {
    431             LOG_ERROR(BSL_LS_SOC_PORT,
    432                     (BSL_META_UP(unit, first_port,
    433                               "ERROR: This %d MHz clk freq is not supported. Only 156 MHz and 125 MHz.\n"),ref_clk_prop));
    434             return SOC_E_PARAM ;
    435         }
    436 
    437         pm_info.pm_specific_info.pm4x10.portmod_phy_external_reset
    438             = soc_esw_portctrl_reset_tsc3_cb;
    439 
    440         /* 4x10 is only used in mgmt ports */
    441         pm_info.pm_specific_info.pm4x10.port_mode_aux_info = portmodModeInfoNone;
    442         
    443         /* Add PM to PortMod */
    444         rv = portmod_port_macro_add(unit, &pm_info);
    445     }
    446 
    447     if (PORTMOD_FAILURE(rv)) {
    448         for (pmid=0; pmid < num_of_instances; pmid++) {
    449             if (pm4x10_th_user_acc[unit][pmid].mutex) {
    450                 sal_mutex_destroy(pm4x10_th_user_acc[unit][pmid].mutex);
    451                 pm4x10_th_user_acc[unit][pmid].mutex = NULL;
    452             }
    453         }
    454     }
    455 
    456     return rv;
    457 #else /* PORTMOD_PM4X10_SUPPORT */
    458     return SOC_E_UNAVAIL;
    459 #endif /* PORTMOD_PM4X10_SUPPORT */
    460 }
    461 
    462 STATIC int
    463 _soc_th_portctrl_pm4x25_portmod_init(int unit, int num_of_instances) 
    464 {
    465 #ifdef PORTMOD_PM4X25_SUPPORT
    466     int rv = SOC_E_NONE;
    467     portmod_pm_create_info_t pm_info;
    468     int pmid = 0, blk, is_sim, lane, phy, found, logical_port;
    469     int first_port, idx, ref_clk_prop, core_num, core_cnt;
    470     uint32 txlane_map, rxlane_map, *pAddr, *pPort,*pCoreNum;
    471     uint32 tx_polarity, rx_polarity;
    472     
    473     SOC_IF_ERROR_RETURN
    474         (_soc_th_portctrl_device_addr_port_get(unit,
    475                                                portmodDispatchTypePm4x25,
    476                                                &pAddr, &pPort,&pCoreNum));
    477     if (!pAddr || !pPort) {
    478         return SOC_E_INTERNAL;
    479     }
    480 
    481     /* Allocate PMs */
    482     SOC_IF_ERROR_RETURN
    483         (soc_esw_portctrl_pm_user_access_alloc(unit,
    484                                            num_of_instances,
    485                                                &pm4x25_th_user_acc[unit]));
    486 
    487     for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) {
    488 
    489         rv = portmod_pm_create_info_t_init(unit, &pm_info);
    490         if (PORTMOD_FAILURE(rv)) {
    491             break;
    492         }
    493         /* PM info */
    494         first_port = pPort[pmid];
    495 
    496         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port);
    497         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 
    498         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2);
    499         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3);
    500 
    501         found = 0;
    502         for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 
    503             blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 
    504             if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_CLPORT){
    505                 found = 1;
    506                 break;
    507             }
    508         }
    509 
    510         if (!found) {
    511             rv = SOC_E_INTERNAL;
    512             break;
    513         } 
    514 
    515         pm_info.type         = portmodDispatchTypePm4x25;
    516 
    517         /* Init user_acc for phymod access struct */
    518         rv = portmod_default_user_access_t_init(unit,
    519                                                 &(pm4x25_th_user_acc[unit][pmid]));
    520         if (PORTMOD_FAILURE(rv)) {
    521             break;
    522         }
    523 
    524         PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x25_th_user_acc[unit][pmid])));
    525         PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_CLR((&(pm4x25_th_user_acc[unit][pmid])));
    526         pm4x25_th_user_acc[unit][pmid].unit = unit;
    527         pm4x25_th_user_acc[unit][pmid].blk_id = blk; 
    528         pm4x25_th_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex");
    529         if (pm4x25_th_user_acc[unit][pmid].mutex == NULL) {
    530             rv = SOC_E_MEMORY;
    531             break;
    532         }
    533 
    534         /* Specific info for PM4x25 */
    535         rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x25.access);
    536         if (PORTMOD_FAILURE(rv)) {
    537             break;
    538         }
    539 
    540         pm_info.pm_specific_info.pm4x25.access.user_acc =
    541             &(pm4x25_th_user_acc[unit][pmid]);
    542         pm_info.pm_specific_info.pm4x25.access.addr     = pAddr[pmid];
    543         pm_info.pm_specific_info.pm4x25.access.bus      = NULL; /* Use default bus */
    544 
    545         rv = soc_physim_check_sim(unit, phymodDispatchTypeTscf, 
    546                                   &(pm_info.pm_specific_info.pm4x25.access),
    547                                   0, &is_sim);
    548 
    549         if (PORTMOD_FAILURE(rv)) {
    550             break;
    551         }
    552 
    553         if (is_sim) {
    554             pm_info.pm_specific_info.pm4x25.access.bus->bus_capabilities |= 
    555                 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL);
    556 
    557             /* Firmward loader : Don't allow FW load on sim enviroment */
    558             pm_info.pm_specific_info.pm4x25.fw_load_method =
    559                 phymodFirmwareLoadMethodNone;
    560         } else {
    561             pm_info.pm_specific_info.pm4x25.fw_load_method = 
    562                 soc_property_suffix_num_get(unit, pmid, 
    563                                             spn_LOAD_FIRMWARE, "quad", 
    564                                             phymodFirmwareLoadMethodExternal);
    565             pm_info.pm_specific_info.pm4x25.fw_load_method &= 0xff;
    566         }
    567 
    568         /* Use default external loader if NULL */
    569         pm_info.pm_specific_info.pm4x25.external_fw_loader = NULL;
    570 
    571         /* Polarity */
    572         rv = phymod_polarity_t_init (&(pm_info.pm_specific_info.pm4x25.polarity));
    573         if (PORTMOD_FAILURE(rv)) {
    574             break;
    575         }
    576 
    577         for (lane = 0; lane < SOC_PM4X25_NUM_LANES; lane++) {
    578             phy = first_port+lane;
    579             logical_port = SOC_INFO(unit).port_p2l_mapping[phy];
    580 
    581             _soc_th_portctrl_pm_port_polarity_get
    582                 (unit, logical_port, phy, lane, &tx_polarity, &rx_polarity);
    583 
    584             pm_info.pm_specific_info.pm4x25.polarity.rx_polarity |= rx_polarity;
    585             pm_info.pm_specific_info.pm4x25.polarity.tx_polarity |= tx_polarity;
    586 
    587             if (SOC_INFO(unit).port_num_lanes[logical_port] >= SOC_PM4X25_NUM_LANES) break;
    588         }
    589 
    590         /* Lane map */
    591         rv = phymod_lane_map_t_init
    592             (&(pm_info.pm_specific_info.pm4x25.lane_map));
    593         if (PORTMOD_FAILURE(rv)) {
    594             break;
    595         }
    596 
    597         logical_port = SOC_INFO(unit).port_p2l_mapping[first_port];
    598         core_cnt = 1; 
    599 
    600         for (core_num = 0; core_num < core_cnt; core_num++) {
    601             _soc_th_portctrl_pm_port_lanemap_get
    602                 (unit, logical_port, first_port, core_num, &txlane_map, &rxlane_map);
    603 
    604             /* possible internal swap to be added */
    605             
    606             pm_info.pm_specific_info.pm4x25.lane_map.num_of_lanes =
    607                 SOC_PM4X25_NUM_LANES;
    608    
    609             pm_info.pm_specific_info.pm4x25.core_num = pCoreNum? pCoreNum[pmid] : pmid;
    610             pm_info.pm_specific_info.pm4x25.core_num_int = 0;
    611             pm_info.pm_specific_info.pm4x25.rescal = -1;
    612  
    613             for(lane=0 ; lane<SOC_PM4X25_NUM_LANES; lane++) {
    614                 pm_info.pm_specific_info.pm4x25.lane_map.lane_map_tx[lane] =  
    615                     (txlane_map >> (lane * SOC_PM4X25_NUM_LANES)) &
    616                     SOC_PM4X25_LANE_MASK;
    617                 pm_info.pm_specific_info.pm4x25.lane_map.lane_map_rx[lane] =  
    618                     (rxlane_map >> (lane * SOC_PM4X25_NUM_LANES)) &
    619                     SOC_PM4X25_LANE_MASK;
    620             }
    621         }
    622 
    623         ref_clk_prop = soc_property_port_get(unit, first_port,
    624                             spn_XGXS_LCPLL_XTAL_REFCLK, 156);
    625 
    626         if ((ref_clk_prop == 156) ||( ref_clk_prop == 1)){
    627             pm_info.pm_specific_info.pm4x25.ref_clk = phymodRefClk156Mhz;
    628         }
    629         else if (ref_clk_prop == 125){     
    630             pm_info.pm_specific_info.pm4x25.ref_clk = phymodRefClk125Mhz;
    631         }
    632         else {
    633             LOG_ERROR(BSL_LS_SOC_PORT,
    634                     (BSL_META_UP(unit, first_port,
    635                               "ERROR: This %d MHz clk freq is not supported. Only 156 MHz and 125 MHz.\n"),ref_clk_prop));
    636             return SOC_E_PARAM ;
    637         }
    638 
    639         /* Add PM to PortMod */
    640         rv = portmod_port_macro_add(unit, &pm_info);
    641     }
    642 
    643     if (PORTMOD_FAILURE(rv)) {
    644         for (pmid=0; pmid < num_of_instances; pmid++) {
    645             if (pm4x25_th_user_acc[unit][pmid].mutex) {
    646                 sal_mutex_destroy(pm4x25_th_user_acc[unit][pmid].mutex);
    647                 pm4x25_th_user_acc[unit][pmid].mutex = NULL;
    648             }
    649         }
    650     }
    651 
    652     return rv;
    653 #else /* PORTMOD_PM4X25_SUPPORT */
    654     return SOC_E_UNAVAIL;
    655 #endif /* PORTMOD_PM4X25_SUPPORT */
    656 }
    657 
    658 /*
    659  * Function:
    660  *      soc_th_portctrl_pm_portmod_init
    661  * Purpose:
    662  *      Initialize PortMod and PortMacro for Tomahawk
    663  *      Add port macros (PM) to the unit's PortMod Manager (PMM).
    664  * Parameters:
    665  *      unit             - (IN) Unit number.
    666  * Returns:
    667  *      SOC_E_XXX
    668  */
    669 int
    670 soc_th_portctrl_pm_portmod_init(int unit)
    671 {
    672     int rv = SOC_E_NONE, pms_arr_len = 0, count, max_phys= 0;
    673     portmod_pm_instances_t *pm_types = NULL;
    674 
    675     /* Call PortMod library initialization */
    676     SOC_IF_ERROR_RETURN(
    677         _soc_th_portctrl_pm_init(unit, &max_phys,
    678                                  &pm_types, &pms_arr_len));
    679     if (pms_arr_len == 0) {
    680         return SOC_E_UNAVAIL;
    681     }
    682 
    683     /*
    684      * If portmod was create - destroy and create again
    685      * Better way would be to create once and leave it.
    686      */
    687     if (SOC_E_NONE == soc_esw_portctrl_init_check(unit)) {
    688         SOC_IF_ERROR_RETURN(portmod_destroy(unit));
    689     }
    690 
    691     SOC_IF_ERROR_RETURN
    692         (portmod_create(unit, 0, SOC_MAX_NUM_PORTS, max_phys,
    693                         pms_arr_len, pm_types));
    694 
    695     for (count = 0; SOC_SUCCESS(rv) && (count < pms_arr_len); count++) {
    696 #ifdef PORTMOD_PM4X10_SUPPORT
    697         if (pm_types[count].type == portmodDispatchTypePm4x10) {
    698             rv = _soc_th_portctrl_pm4x10_portmod_init
    699                 (unit, pm_types[count].instances);
    700         } else 
    701 #endif /* PORTMOD_PM4X10_SUPPORT  */
    702 #ifdef PORTMOD_PM4X25_SUPPORT
    703         if (pm_types[count].type == portmodDispatchTypePm4x25) {
    704             rv = _soc_th_portctrl_pm4x25_portmod_init
    705                 (unit, pm_types[count].instances);
    706         } else
    707 #endif /* PORTMOD_PM4X25_SUPPORT  */
    708         {
    709             rv = SOC_E_INTERNAL;
    710         }
    711     }
    712 
    713     return rv;
    714 }
    715 
    716 /*
    717  * Function:
    718  *      soc_th_portctrl_pm_portmod_deinit
    719  * Purpose:
    720  *      Deinitialize PortMod and PortMacro for Tomahawk.
    721  *      Free pm user access data.
    722  * Parameters:
    723  *      unit      - (IN) Unit number.
    724  * Returns:
    725  *      SOC_E_NONE
    726  */
    727 int
    728 soc_th_portctrl_pm_portmod_deinit(int unit)
    729 {
    730     if (SOC_E_INIT == soc_esw_portctrl_init_check(unit)) {
    731         return SOC_E_NONE;
    732     }
    733 
    734     /* Free PMs structures */
    735 #ifdef PORTMOD_PM4X10_SUPPORT
    736     if (pm4x10_th_user_acc[unit] != NULL) {
    737         sal_free(pm4x10_th_user_acc[unit]);
    738         pm4x10_th_user_acc[unit] = NULL;
    739     }
    740 #endif /* PORTMOD_PM4X10_SUPPORT */
    741 
    742 #ifdef PORTMOD_PM4X25_SUPPORT
    743     if (pm4x25_th_user_acc[unit] != NULL) {
    744         sal_free(pm4x25_th_user_acc[unit]);
    745         pm4x25_th_user_acc[unit] = NULL;
    746     }
    747 #endif /* PORTMOD_PM4X25_SUPPORT */
    748     return SOC_E_NONE;
    749 }
    750 
    751 int
    752 soc_th_portctrl_pm_port_phyaddr_get(int unit, soc_port_t port)
    753 {
    754     int phy, core_index;
    755     uint32 i, *pAddr = NULL, *pPort = NULL, *pCoreNum = NULL;
    756 
    757     phy = SOC_INFO(unit).port_l2p_mapping[port];
    758 
    759     /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */
    760     core_index = (phy - 1) / SOC_PM4X10_NUM_LANES;
    761 #ifdef PORTMOD_PM4X10_SUPPORT
    762     for (i=0; i<SOC_TH_PM4X10_COUNT; i++) {
    763         if (core_index == _th_pm4x10_core_num[i]) {
    764             SOC_IF_ERROR_RETURN
    765                 (_soc_th_portctrl_device_addr_port_get(unit,
    766                                              portmodDispatchTypePm4x10,
    767                                              &pAddr, &pPort, &pCoreNum));
    768             return pAddr[i];
    769         }
    770     }
    771 #endif /* PORTMOD_PM4X10_SUPPORT */
    772 
    773 #ifdef PORTMOD_PM4X25_SUPPORT
    774     /* When port dones't find PM4x10, find PM4x25 again. */
    775     for (i=0; i<SOC_TH_PM4X25_COUNT; i++) {
    776         if (core_index == _th_pm4x25_core_num[i]) {
    777             SOC_IF_ERROR_RETURN
    778                 (_soc_th_portctrl_device_addr_port_get(unit,
    779                                              portmodDispatchTypePm4x25,
    780                                              &pAddr, &pPort, &pCoreNum));
    781             return pAddr[i];
    782         }
    783     }
    784 #endif /* PORTMOD_PM4X25_SUPPORT */
    785 
    786     return -1;
    787 }
    788 
    789 #endif /* BCM_TOMAHAWK_SUPPORT */