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


      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/bondoptions.h>
     15 #include <soc/mem.h>
     16 #include <soc/esw/portctrl.h>
     17 #include <shared/bsl.h>
     18 #include <soc/phy/phymod_sim.h>
     19 #include <soc/portmod/portmod.h>
     20 #include <soc/trident3.h>
     21 
     22 #ifdef BCM_TRIDENT3_SUPPORT
     23 
     24 #define SOC_TD3_PM4X10_COUNT         1
     25 static uint32_t _td3_pm4x10_addr[SOC_TD3_PM4X10_COUNT] = { 0x1c1 };
     26 
     27 #define SOC_TD3_PM4X25_COUNT  32
     28 #define SOC_TD3_MAX_PHYS      137  /* 32*4 CLMAC's + 4 XLMAC */
     29 
     30 static uint32_t _td3_pm4x25_addr[SOC_TD3_PM4X25_COUNT] = {
     31     0x81,  0x85,  0x89,  0x8D,
     32     0x91,  0x95,  0xA1,  0xA5,
     33     0xA9,  0xAD,  0xc1,  0xC5,
     34     0xC9,  0xCD,  0xD1,  0xD5,
     35     0xE1,  0xE5,  0xE9,  0xED,
     36     0xF1,  0xF5,  0x181, 0x185,
     37     0x189, 0x18D, 0x1A1, 0x1A5,
     38     0x1A9, 0x1AD, 0x1B1, 0x1B5
     39 };
     40 
     41 
     42 static portmod_pm_instances_t td3_pm_types[] = {
     43 #ifdef PORTMOD_PM4X25_SUPPORT
     44         {portmodDispatchTypePm4x25,  SOC_TD3_PM4X25_COUNT},
     45 #endif
     46 #ifdef PORTMOD_PM4X10_SUPPORT
     47         {portmodDispatchTypePm4x10,  SOC_TD3_PM4X10_COUNT},
     48 #endif
     49 };
     50 
     51 #ifdef PORTMOD_PM4X25_SUPPORT
     52 static portmod_default_user_access_t *pm4x25_td3_user_acc[SOC_MAX_NUM_DEVICES];
     53 #endif /* PORTMOD_PM4X25_SUPPORT */
     54 
     55 #ifdef PORTMOD_PM4X10_SUPPORT
     56 static portmod_default_user_access_t *pm4x10_td3_user_acc[SOC_MAX_NUM_DEVICES];
     57 #endif /* PORTMOD_PM4X25_SUPPORT */
     58 
     59 
     60 
     61 /*
     62  * Polarity get looks for physical port based config first. This will enable
     63  * the user to define the polarity for all ports weather mapped to logical 
     64  * port or not.
     65  *
     66  * For legacy compatibility - we still look for the logical port
     67  * config setup.
     68  */
     69 STATIC void
     70 td3_pm_port_polarity_get (int unit, int logical_port, int physical_port, 
     71                           int lane, uint32 *tx_pol, uint32* rx_pol)
     72 {
     73     uint32 rx_polarity, tx_polarity;
     74 
     75     rx_polarity = soc_property_phy_get(unit, physical_port, 0, 0, lane,
     76                          spn_PHY_CHAIN_RX_POLARITY_FLIP_PHYSICAL, 0x0);
     77     *rx_pol = (rx_polarity & 0x1) << lane;
     78 
     79     tx_polarity = soc_property_phy_get(unit, physical_port, 0, 0, lane,
     80                          spn_PHY_CHAIN_TX_POLARITY_FLIP_PHYSICAL, 0x0);
     81     *tx_pol = (tx_polarity & 0x1) << lane;
     82 }
     83 
     84 /*
     85  * lanemap get looks for physical port based config first. This will enable
     86  * the user to define the lanemap for all ports weather mapped to logical 
     87  * port or not.
     88  *
     89  * For legacy compatibility - we still look for the logical port
     90  * config setup.
     91  */
     92 STATIC 
     93 void td3_pm_port_lanemap_get (int unit, int logical_port, int physical_port, 
     94                            uint32 *txlane_map, uint32* rxlane_map)       
     95 {
     96     *rxlane_map = soc_property_phy_get(unit, physical_port, 0, 0, 0,
     97                         spn_PHY_CHAIN_RX_LANE_MAP_PHYSICAL, 0x3210);
     98 
     99     *txlane_map = soc_property_phy_get(unit, physical_port, 0, 0, 0,
    100                         spn_PHY_CHAIN_TX_LANE_MAP_PHYSICAL, 0x3210);
    101 }
    102 
    103 
    104 STATIC int
    105 _soc_td3_portctrl_pm4x25_portmod_init(int unit, int second_mgmt_port)
    106 {
    107 #ifdef PORTMOD_PM4X25_SUPPORT
    108     int rv = SOC_E_NONE;
    109     portmod_pm_create_info_t pm_create_info;
    110     int pmid = 0, blk, is_sim, found, logical_port;
    111     int first_port, idx, mode;
    112     uint32 pm_mask = 0xFFFFFFFF;
    113 
    114     /* Allocate user access for all PMs */
    115     SOC_IF_ERROR_RETURN (soc_esw_portctrl_pm_user_access_alloc(unit, 
    116                   SOC_TD3_PM4X25_COUNT, &pm4x25_td3_user_acc[unit]));
    117 
    118     /*
    119      * in 2T SKU, the following PM's are removed between PM0-PM31
    120      * PM2, PM4, PM6, ---- PM9, PM11, PM13, 
    121      * PM18, PM20, PM22, ---  PM25, PM27, PM29,
    122      * These PM's correspond to the bit mask (cleared bits) below.
    123      */
    124     if (soc_feature(unit, soc_feature_td3_reduced_pm)) {
    125         pm_mask = 0xD5AFD5AF;
    126     }
    127 
    128     for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < SOC_TD3_PM4X25_COUNT); pmid++) {
    129 
    130         if (!((0x01 << pmid) & pm_mask)) {
    131             continue;
    132         }
    133 
    134         rv = portmod_pm_create_info_t_init(unit, &pm_create_info);
    135         if (PORTMOD_FAILURE(rv)) {
    136             break;
    137         }
    138 
    139         pm_create_info.type         = portmodDispatchTypePm4x25;
    140 
    141         /* 1 based port number */
    142         first_port = 1 + (pmid << 2);
    143 
    144         SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port);
    145         SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port+1);
    146         SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port+2);
    147         SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port+3);
    148 
    149         /* Identify the block for this particular port */
    150         found = 0;
    151 
    152         for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){
    153             blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk;
    154             if (SOC_BLOCK_INFO(unit, blk).type ==
    155                 (soc_feature(unit, soc_feature_clport_gen2) ? SOC_BLK_CLG2PORT : SOC_BLK_CLPORT)){
    156                 found = 1;
    157                 break;
    158             }
    159         }
    160 
    161         if (!found) {
    162             rv = SOC_E_INTERNAL;
    163             break;
    164         }
    165 
    166 
    167         /* Init user_acc for phymod access struct */
    168         rv = portmod_default_user_access_t_init(unit,
    169                                                 &(pm4x25_td3_user_acc[unit][pmid]));
    170         if (PORTMOD_FAILURE(rv)) {
    171             break;
    172         }
    173 
    174         PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x25_td3_user_acc[unit][pmid])));
    175         PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_CLR((&(pm4x25_td3_user_acc[unit][pmid])));
    176         pm4x25_td3_user_acc[unit][pmid].unit = unit;
    177         pm4x25_td3_user_acc[unit][pmid].blk_id = blk;
    178         pm4x25_td3_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex");
    179 
    180         if (pm4x25_td3_user_acc[unit][pmid].mutex == NULL) {
    181             rv = SOC_E_MEMORY;
    182             break;
    183         }
    184 
    185         /* Specific info for PM4x25 */
    186         rv = phymod_access_t_init(&pm_create_info.pm_specific_info.pm4x25.access);
    187         if (PORTMOD_FAILURE(rv)) {
    188             break;
    189         }
    190 
    191         pm_create_info.pm_specific_info.pm4x25.access.user_acc = &(pm4x25_td3_user_acc[unit][pmid]);
    192         pm_create_info.pm_specific_info.pm4x25.access.addr     = _td3_pm4x25_addr[pmid];
    193         pm_create_info.pm_specific_info.pm4x25.access.bus      = NULL; /* Use default bus */
    194         pm_create_info.pm_specific_info.pm4x25.rescal          = -1;
    195 
    196         rv = soc_physim_check_sim(unit, phymodDispatchTypeTscf,
    197                                   &(pm_create_info.pm_specific_info.pm4x25.access),
    198                                   0, &is_sim);
    199 
    200         if (PORTMOD_FAILURE(rv)) {
    201             break;
    202         }
    203 
    204         if (is_sim) {
    205             /* Firmward loader : Don't allow FW load on sim enviroment */
    206             pm_create_info.pm_specific_info.pm4x25.fw_load_method =
    207                 phymodFirmwareLoadMethodNone;
    208 
    209             PHYMOD_ACC_F_CLAUSE45_SET(&pm_create_info.pm_specific_info.pm4x25.access);
    210         }
    211 
    212         /* Use default external loader if NULL */
    213         pm_create_info.pm_specific_info.pm4x25.external_fw_loader = NULL;
    214 
    215         logical_port = SOC_INFO(unit).port_p2l_mapping[first_port];
    216 
    217         pm_create_info.pm_specific_info.pm4x25.core_num = pmid; 
    218         pm_create_info.pm_specific_info.pm4x25.core_num_int = 0;
    219 
    220         /* Figure out the port mode */
    221         SOC_IF_ERROR_RETURN(soc_td3_port_mode_get(unit, logical_port, &mode));
    222         if (mode == portmodPortModeTri012 || mode == portmodPortModeTri023) {
    223             pm_create_info.pm_specific_info.pm4x25.port_mode_aux_info = portmodModeInfoThreePorts;
    224         }
    225 
    226         /* Add PM to PortMod */
    227         rv = portmod_port_macro_add(unit, &pm_create_info);
    228     }
    229 
    230     if (PORTMOD_FAILURE(rv)) {
    231         for (pmid=0; pmid < SOC_TD3_PM4X25_COUNT; pmid++) {
    232             if (pm4x25_td3_user_acc[unit][pmid].mutex) {
    233                 sal_mutex_destroy(pm4x25_td3_user_acc[unit][pmid].mutex);
    234                 pm4x25_td3_user_acc[unit][pmid].mutex = NULL;
    235             }
    236         }
    237     }
    238 
    239     return rv;
    240 #else /* PORTMOD_PM4X25_SUPPORT */
    241     return SOC_E_UNAVAIL;
    242 #endif /* PORTMOD_PM4X25_SUPPORT */
    243 }
    244 
    245 #define TRIDENT3_FIRST_MGMT_PHYSICAL_PORT_NUM   129
    246 #define TRIDENT3_SECOND_MGMT_PHYSICAL_PORT_NUM  131
    247 STATIC int
    248 _soc_td3_portctrl_pm4x10_portmod_init(int unit, int second_mgmt_port)
    249 {
    250 #if defined PORTMOD_PM4X10_SUPPORT && defined BCM_56870_A0
    251     int rv = SOC_E_NONE;
    252     portmod_pm_create_info_t pm_create_info;
    253     int pmid = 0, blk, is_sim, found;
    254     int idx, first_port;
    255     int port_num_lanes = 0;
    256     soc_info_t *si;
    257 
    258     si = &SOC_INFO(unit);
    259     /* Allocate user access for all PMs */
    260     SOC_IF_ERROR_RETURN (soc_esw_portctrl_pm_user_access_alloc(unit, 
    261                   SOC_TD3_PM4X10_COUNT, &pm4x10_td3_user_acc[unit]));
    262 
    263     for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < SOC_TD3_PM4X10_COUNT); pmid++) {
    264 
    265         rv = portmod_pm_create_info_t_init(unit, &pm_create_info);
    266         if (PORTMOD_FAILURE(rv)) {
    267             break;
    268         }
    269 
    270         pm_create_info.type         = portmodDispatchTypePm4x10;
    271         first_port = TRIDENT3_FIRST_MGMT_PHYSICAL_PORT_NUM;
    272         SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port); /* first mgmt port */
    273         SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port + 1); /* SW Workaround: Need to add.
    274                                                                    the dummy port so that lane_index
    275                                                                    is incremented to 2 for the second
    276                                                                    management port to detect ext PHY */
    277 
    278         if (second_mgmt_port) {
    279              SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port + 2);
    280             /* Second mgmt reuse physical port number 128 */
    281             port_num_lanes = si->port_num_lanes[si->port_p2l_mapping[128]];
    282             if (port_num_lanes == 2) {
    283                  SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port + 3);
    284             }
    285         }
    286         /* Check if mgmt ports is configured as 4 lanes */
    287         port_num_lanes = si->port_num_lanes[si->port_p2l_mapping[TRIDENT3_FIRST_MGMT_PHYSICAL_PORT_NUM]];
    288         if (port_num_lanes == 4) {
    289             SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port + 2);
    290             SOC_PBMP_PORT_ADD(pm_create_info.phys, first_port + 3);
    291         }
    292 
    293         /* Identify the block for this particular port */
    294         found = 0;
    295 
    296         for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){
    297             blk = SOC_PORT_IDX_INFO(unit, TRIDENT3_FIRST_MGMT_PHYSICAL_PORT_NUM, idx).blk;
    298             if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT){
    299                 found = 1;
    300                 break;
    301             }
    302         }
    303 
    304         if (!found) {
    305             rv = SOC_E_INTERNAL;
    306             break;
    307         }
    308 
    309 
    310         /* Init user_acc for phymod access struct */
    311         rv = portmod_default_user_access_t_init(unit,
    312                                                 &(pm4x10_td3_user_acc[unit][pmid]));
    313         if (PORTMOD_FAILURE(rv)) {
    314             break;
    315         }
    316 
    317         PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x10_td3_user_acc[unit][pmid])));
    318         PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_CLR((&(pm4x10_td3_user_acc[unit][pmid])));
    319 
    320         pm4x10_td3_user_acc[unit][pmid].unit = unit;
    321         pm4x10_td3_user_acc[unit][pmid].blk_id = blk;
    322         pm4x10_td3_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex");
    323 
    324         if (pm4x10_td3_user_acc[unit][pmid].mutex == NULL) {
    325             rv = SOC_E_MEMORY;
    326             break;
    327         }
    328 
    329         /* Specific info for PM4x10 */
    330         rv = phymod_access_t_init(&pm_create_info.pm_specific_info.pm4x10.access);
    331         if (PORTMOD_FAILURE(rv)) {
    332             break;
    333         }
    334 
    335         pm_create_info.pm_specific_info.pm4x10.access.user_acc = &(pm4x10_td3_user_acc[unit][pmid]);
    336         pm_create_info.pm_specific_info.pm4x10.access.addr     = _td3_pm4x10_addr[pmid];
    337         pm_create_info.pm_specific_info.pm4x10.access.bus      = NULL; /* Use default bus */
    338         pm_create_info.pm_specific_info.pm4x10.rescal          = -1;
    339 
    340         rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce16,
    341                                   &(pm_create_info.pm_specific_info.pm4x10.access),
    342                                   0, &is_sim);
    343 
    344         if (PORTMOD_FAILURE(rv)) {
    345             break;
    346         }
    347 
    348         if (is_sim) {
    349             /* Firmward loader : Don't allow FW load on sim enviroment */
    350             pm_create_info.pm_specific_info.pm4x10.fw_load_method =
    351                 phymodFirmwareLoadMethodNone;
    352 
    353             /* TSCE sim supports CL45 mode to read/write registers. */
    354             PHYMOD_ACC_F_CLAUSE45_SET(&pm_create_info.pm_specific_info.pm4x10.access);
    355         }
    356 
    357         /* Use default external loader if NULL */
    358         pm_create_info.pm_specific_info.pm4x10.external_fw_loader = NULL;
    359 
    360         pm_create_info.pm_specific_info.pm4x10.core_num = pmid; 
    361         pm_create_info.pm_specific_info.pm4x10.core_num_int = 0;
    362 
    363         /*
    364          * Set port mode as dual-port mode for all speed modes(XFI/RXAUI/XAUI),
    365          * it is WAR for shim issue on Merlin16 MGMT port
    366          */
    367         pm_create_info.pm_specific_info.pm4x10.port_mode_aux_info
    368                 = portmodModeInfoTwoDualModePorts;
    369         pm_create_info.pm_specific_info.pm4x10.portmod_phy_external_reset
    370              = soc_esw_portctrl_reset_tsc3_cb;
    371 
    372         /* Add PM to PortMod */
    373         rv = portmod_port_macro_add(unit, &pm_create_info);
    374     }
    375 
    376     if (PORTMOD_FAILURE(rv)) {
    377         for (pmid=0; pmid < SOC_TD3_PM4X10_COUNT; pmid++) {
    378             if (pm4x10_td3_user_acc[unit][pmid].mutex) {
    379                 sal_mutex_destroy(pm4x10_td3_user_acc[unit][pmid].mutex);
    380                 pm4x10_td3_user_acc[unit][pmid].mutex = NULL;
    381             }
    382         }
    383     }
    384 
    385     return rv;
    386 #else /* PORTMOD_PM4X10_SUPPORT */
    387     return SOC_E_UNAVAIL;
    388 #endif /* PORTMOD_PM4X10_SUPPORT */
    389 }
    390 
    391 /*
    392  * Function:
    393  *      soc_td3_portctrl_pm_portmod_init
    394  * Purpose:
    395  *      Initialize PortMod and PortMacro for Trident2Plus
    396  *      Add port macros (PM) to the unit's PortMod Manager (PMM).
    397  * Parameters:
    398  *      unit             - (IN) Unit number.
    399  * Returns:
    400  *      SOC_E_XXX
    401  */
    402 int
    403 soc_td3_portctrl_pm_portmod_init(int unit)
    404 {
    405     int    rv = SOC_E_NONE;
    406     uint32 flags = 0, mgmt_port_count = 0;
    407 
    408     /*
    409      * If portmod was create - destroy and create again
    410      * Better way would be to create once and leave it.
    411      */
    412     if (SOC_E_NONE == soc_esw_portctrl_init_check(unit)) {
    413         SOC_IF_ERROR_RETURN(portmod_destroy(unit));
    414     }
    415 
    416     PORTMOD_CREATE_F_PM_NULL_SET(flags);
    417 
    418     SOC_IF_ERROR_RETURN
    419         (portmod_create(unit, flags, SOC_MAX_NUM_PORTS, SOC_TD3_MAX_PHYS, 
    420                          sizeof(td3_pm_types)/sizeof(portmod_pm_instances_t), td3_pm_types));
    421 
    422     SOC_PBMP_COUNT(SOC_INFO(unit).management_pbm, mgmt_port_count);
    423 
    424     rv = _soc_td3_portctrl_pm4x25_portmod_init (unit, (mgmt_port_count == 2) ? 1 : 0);
    425     if (rv) return (rv);
    426 
    427     return(_soc_td3_portctrl_pm4x10_portmod_init (unit, (mgmt_port_count == 2) ? 1 : 0));
    428 }
    429 
    430 /*
    431  * Function:
    432  *      soc_td3_portctrl_pm_portmod_deinit
    433  * Purpose:
    434  *      Deinitialize PortMod and PortMacro for Trident2Plus.
    435  *      Free pm user access data.
    436  * Parameters:
    437  *      unit      - (IN) Unit number.
    438  * Returns:
    439  *      SOC_E_NONE
    440  */
    441 int
    442 soc_td3_portctrl_pm_portmod_deinit(int unit)
    443 {
    444     if (SOC_E_INIT == soc_esw_portctrl_init_check(unit)) {
    445         return SOC_E_NONE;
    446     }
    447 
    448     /* Free PMs structures */
    449 #ifdef PORTMOD_PM4X25_SUPPORT
    450     if (pm4x25_td3_user_acc[unit] != NULL) {
    451         sal_free(pm4x25_td3_user_acc[unit]);
    452         pm4x25_td3_user_acc[unit] = NULL;
    453     }
    454 #endif /* PORTMOD_PM4X25_SUPPORT */
    455 
    456 #ifdef PORTMOD_PM4X10_SUPPORT
    457     if (pm4x10_td3_user_acc[unit] != NULL) {
    458         sal_free(pm4x10_td3_user_acc[unit]);
    459         pm4x10_td3_user_acc[unit] = NULL;
    460     }
    461 #endif /* PORTMOD_PM4X10_SUPPORT */
    462 
    463     SOC_IF_ERROR_RETURN(portmod_destroy(unit));
    464 
    465     return SOC_E_NONE;
    466 }
    467 
    468 int
    469 soc_td3_portctrl_pm_port_config_get(int unit, soc_port_t port, void *port_config)
    470 {
    471 #ifdef PORTMOD_PM4X25_SUPPORT
    472     int rv = SOC_E_NONE;
    473     int pmid = 0, lane, phy, phy_port, logical_port, port_mode;
    474     int first_port = 0, core_num, core_count = 0, core_index, is_sim, type;
    475     uint32 txlane_map, rxlane_map, i;
    476     uint32 tx_polarity, rx_polarity;
    477     uint32 mgmt_port_count;
    478     portmod_port_init_config_t *port_config_info;
    479     phymod_firmware_load_method_t fw_load_method;
    480     phymod_polarity_t polarity; /**< Lanes Polarity */
    481     phymod_lane_map_t lane_map;
    482 
    483     port_config_info = (portmod_port_init_config_t *)port_config;
    484     SOC_IF_ERROR_RETURN(soc_td3_port_mode_get(unit, port, &port_mode));
    485     if (port_mode == portmodPortModeTri012 || port_mode == portmodPortModeTri023) {
    486         port_config_info->port_mode_aux_info = portmodModeInfoThreePorts;
    487     }
    488 
    489     phy = SOC_INFO(unit).port_l2p_mapping[port];
    490 
    491     /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */
    492     core_num = (phy - 1) / SOC_PM4X25_NUM_LANES;
    493 
    494     for (i=0; i<SOC_TD3_PM4X25_COUNT; i++) {
    495         if (core_num == i) {
    496             type   = portmodDispatchTypePm4x25;
    497             pmid = i;
    498             first_port = 1 + (pmid << 2);
    499             core_count = 1;
    500             break;
    501         }
    502     }
    503 
    504     /* When port doesn't find PM4x25, find PM4x10 again. */
    505     SOC_PBMP_COUNT(SOC_INFO(unit).management_pbm, mgmt_port_count);
    506 
    507     if ((i == SOC_TD3_PM4X25_COUNT) ||
    508         ((mgmt_port_count == 2) && (phy == 128))) {
    509         type = portmodDispatchTypePm4x10;
    510         pmid = 0;
    511         core_count = 1;
    512         first_port = 129;
    513     }
    514 
    515     for (core_index = 0; core_index < core_count; core_index++) {
    516         fw_load_method = phymodFirmwareLoadMethodExternal;
    517 
    518         soc_physim_enable_get(unit, &is_sim);
    519 
    520         if (is_sim) {
    521             /* Firmward loader : Don't allow FW load on sim enviroment */
    522             fw_load_method = phymodFirmwareLoadMethodNone;
    523         } else {
    524             fw_load_method = soc_property_suffix_num_get(unit, pmid,
    525                                             spn_LOAD_FIRMWARE, "quad",
    526                                             phymodFirmwareLoadMethodExternal);
    527             fw_load_method &= 0xff;
    528         }
    529 
    530         rv = phymod_polarity_t_init(&polarity);
    531         if (PORTMOD_FAILURE(rv)) {
    532             break;
    533         }
    534 
    535         /* Polarity */
    536         for (lane = 0; lane < SOC_PM4X25_NUM_LANES; lane++) {
    537             phy_port = first_port + lane + (core_index*4);
    538             logical_port = SOC_INFO(unit).port_p2l_mapping[phy_port];
    539         
    540             td3_pm_port_polarity_get (unit, logical_port, phy_port, lane,
    541                                       &tx_polarity, &rx_polarity);
    542 
    543             polarity.rx_polarity |= rx_polarity;
    544             polarity.tx_polarity |= tx_polarity;
    545         }
    546 
    547         /* Lane map */
    548         rv = phymod_lane_map_t_init(&lane_map);
    549         if (PORTMOD_FAILURE(rv)) {
    550             break;
    551         }
    552 
    553         phy_port = first_port + (core_index*4);
    554         logical_port = SOC_INFO(unit).port_p2l_mapping[phy_port];
    555 
    556         td3_pm_port_lanemap_get (unit, logical_port, phy_port,
    557                                  &txlane_map, &rxlane_map);
    558 
    559         lane_map.num_of_lanes = (type == portmodDispatchTypePm4x25) ?
    560                                  SOC_PM4X25_NUM_LANES : SOC_PM4X10_NUM_LANES;
    561 
    562         for(lane = 0 ; lane < lane_map.num_of_lanes; lane++) {
    563             lane_map.lane_map_tx[lane] =
    564                 (txlane_map >> (lane * lane_map.num_of_lanes)) &
    565                 SOC_PM4X25_LANE_MASK;
    566             lane_map.lane_map_rx[lane] =
    567                 (rxlane_map >> (lane * lane_map.num_of_lanes)) &
    568                 SOC_PM4X25_LANE_MASK;
    569         }
    570 
    571         sal_memcpy(&port_config_info->fw_load_method[core_index], &fw_load_method,
    572                     sizeof(phymod_firmware_load_method_t));
    573         port_config_info->fw_load_method_overwrite = 1;
    574         sal_memcpy(&port_config_info->polarity[core_index], &polarity,
    575                     sizeof(phymod_polarity_t));
    576         port_config_info->polarity_overwrite = 1;
    577         sal_memcpy(&port_config_info->lane_map[core_index], &lane_map,
    578                     sizeof(phymod_lane_map_t));
    579         port_config_info->lane_map_overwrite = 1;
    580     }
    581 
    582     return rv;
    583 #else /* PORTMOD_PM4X25_SUPPORT */
    584     return SOC_E_UNAVAIL;
    585 #endif /* PORTMOD_PM4X25_SUPPORT */
    586 }
    587 
    588 int
    589 soc_td3_portctrl_pm_port_phyaddr_get(int unit, soc_port_t port)
    590 {
    591     int phy, core_index;
    592     uint32 pmid;
    593 
    594     phy = SOC_INFO(unit).port_l2p_mapping[port];
    595 
    596     /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */
    597     core_index = (phy - 1) / SOC_PM4X25_NUM_LANES;
    598 
    599 #ifdef PORTMOD_PM4X25_SUPPORT
    600     /* When port dones't find PM4x10, find PM4x25 again. */
    601     for (pmid=0; pmid<SOC_TD3_PM4X25_COUNT; pmid++) {
    602         if (core_index == pmid) {
    603             return _td3_pm4x25_addr[pmid];
    604         }
    605     }
    606 #endif /* PORTMOD_PM4X25_SUPPORT */
    607 
    608 #ifdef PORTMOD_PM4X10_SUPPORT
    609     for (pmid=0; pmid<SOC_TD3_PM4X10_COUNT; pmid++) {
    610         if (core_index == (31+pmid)) {
    611             return _td3_pm4x10_addr[pmid];
    612         }
    613     }
    614 #endif /* PORTMOD_PM4X10_SUPPORT */
    615     return -1;
    616 }
    617 
    618 #define _TD3_PHY_PORT_MNG0              129
    619 int
    620 soc_td3_portctrl_pm_type_get(int unit, soc_port_t phy_port, int* pm_type)
    621 {
    622     *pm_type = -1;
    623 
    624     if (phy_port >= 1 && phy_port <= 128) {
    625 #ifdef PORTMOD_PM4X25_SUPPORT
    626         *pm_type = portmodDispatchTypePm4x25;
    627         return (SOC_E_NONE);
    628 #endif
    629     } else if (phy_port == _TD3_PHY_PORT_MNG0) {
    630 #ifdef PORTMOD_PM4X10_SUPPORT
    631         *pm_type = portmodDispatchTypePm4x10;
    632         return (SOC_E_NONE);
    633 #endif
    634     } else {
    635         return(SOC_E_PARAM);
    636     }
    637 
    638     return SOC_E_UNAVAIL;
    639 }
    640 
    641 soc_portctrl_functions_t soc_td3_portctrl_func = {
    642     soc_td3_portctrl_pm_portmod_init,
    643     soc_td3_portctrl_pm_portmod_deinit,
    644     soc_td3_portctrl_pm_port_config_get,
    645     soc_td3_portctrl_pm_port_phyaddr_get,
    646     NULL,
    647     soc_td3_portctrl_pm_type_get,
    648     NULL,
    649     NULL
    650 };
    651 
    652 #endif /* BCM_TRIDENT3_SUPPORT */