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


      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/td2_td2p.h>
     18 #include <shared/bsl.h>
     19 #include <soc/phy/phymod_sim.h>
     20 #include <soc/portmod/portmod.h>
     21 
     22 #ifdef BCM_TRIDENT2PLUS_SUPPORT
     23 #ifdef PORTMOD_PM4X10TD_SUPPORT
     24 #define SOC_TD2P_PM4X10_COUNT         8
     25 
     26 #define SOC_TD2P_PM4X10_PORT_1        13
     27 #define SOC_TD2P_PM4X10_PORT_2        17
     28 #define SOC_TD2P_PM4X10_PORT_3        45
     29 #define SOC_TD2P_PM4X10_PORT_4        49
     30 #define SOC_TD2P_PM4X10_PORT_5        77
     31 #define SOC_TD2P_PM4X10_PORT_6        81
     32 #define SOC_TD2P_PM4X10_PORT_7        109
     33 #define SOC_TD2P_PM4X10_PORT_8        113
     34 
     35 static uint32_t _td2p_pm4x10_addr[SOC_TD2P_PM4X10_COUNT] = {
     36     0x8D, 0x91, 0xC1, 0xC5, 0xED, 0xF1, 0x1A1, 0x1A5};
     37 
     38 static uint32_t _td2p_pm4x10_core_num[SOC_TD2P_PM4X10_COUNT] = {
     39     3, 4, 11, 12, 19, 20, 27, 28};
     40 
     41 static uint32_t _td2p_pm4x10_port[SOC_TD2P_PM4X10_COUNT] = {
     42     SOC_TD2P_PM4X10_PORT_1,
     43     SOC_TD2P_PM4X10_PORT_2,
     44     SOC_TD2P_PM4X10_PORT_3,
     45     SOC_TD2P_PM4X10_PORT_4,
     46     SOC_TD2P_PM4X10_PORT_5,
     47     SOC_TD2P_PM4X10_PORT_6,
     48     SOC_TD2P_PM4X10_PORT_7,
     49     SOC_TD2P_PM4X10_PORT_8
     50 };
     51 #endif
     52 #ifdef PORTMOD_PM12X10_SUPPORT
     53 #define SOC_TD2P_PM12X10_COUNT         8
     54 
     55 #define SOC_TD2P_PM12X10_PORT_1        1
     56 #define SOC_TD2P_PM12X10_PORT_2        21
     57 #define SOC_TD2P_PM12X10_PORT_3        33
     58 #define SOC_TD2P_PM12X10_PORT_4        53
     59 #define SOC_TD2P_PM12X10_PORT_5        65
     60 #define SOC_TD2P_PM12X10_PORT_6        85
     61 #define SOC_TD2P_PM12X10_PORT_7        97
     62 #define SOC_TD2P_PM12X10_PORT_8        117
     63 
     64 static uint32_t _td2p_pm12x10_addr[SOC_TD2P_PM12X10_COUNT*SOC_PM12X10_PM4X10_COUNT] = {
     65     0x81,  0x85,  0x89,           /* PM12X10 Inst 1, Core 0-2 */
     66     0xA1,  0xA5,  0xA9,           /* PM12X10 Inst 2, Core 2-0 */
     67     0xAD,  0xB1,  0xB5,           /* PM12X10 Inst 3, Core 0-2 */
     68     0xC9,  0xCD,  0xD1,           /* PM12X10 Inst 4, Core 2-0 */
     69     0xE1,  0xE5,  0xE9,           /* PM12X10 Inst 5, Core 0-2 */
     70     0x181, 0x185, 0x189,          /* PM12X10 Inst 6, Core 2-0 */
     71     0x18D, 0x191, 0x195,          /* PM12X10 Inst 7, Core 0-2 */
     72     0x1A9, 0x1AD, 0x1B1};         /* PM12X10 Inst 8, Core 2-0 */
     73 
     74 static uint32_t _td2p_pm12x10_core_num[SOC_TD2P_PM12X10_COUNT*SOC_PM12X10_PM4X10_COUNT] = {
     75     0, 1, 2, 5, 6, 7, 8, 9, 10, 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 29, 30, 31};
     76 
     77 static uint32_t _td2p_pm12x10_port[SOC_TD2P_PM12X10_COUNT] = {
     78     SOC_TD2P_PM12X10_PORT_1,
     79     SOC_TD2P_PM12X10_PORT_2,
     80     SOC_TD2P_PM12X10_PORT_3,
     81     SOC_TD2P_PM12X10_PORT_4,
     82     SOC_TD2P_PM12X10_PORT_5,
     83     SOC_TD2P_PM12X10_PORT_6,
     84     SOC_TD2P_PM12X10_PORT_7,
     85     SOC_TD2P_PM12X10_PORT_8
     86 };
     87 #endif
     88 
     89 static portmod_pm_instances_t td2p_pm_types[] = {
     90 #ifdef PORTMOD_PM4X10TD_SUPPORT
     91     {portmodDispatchTypePm4x10td,  SOC_TD2P_PM4X10_COUNT}, 
     92 #endif
     93 #ifdef PORTMOD_PM12X10_SUPPORT
     94     {portmodDispatchTypePm12x10, SOC_TD2P_PM12X10_COUNT},
     95 #endif
     96 };
     97 
     98 #define SOC_TD2P_MAX_PHYS              160   /* 128 XLMACS, 32 CLMAC's */
     99 
    100 #define SOC_TD2P_NIB_SWAP(data) \
    101             (((data & 0x0f) << 12) | ((data & 0xf0) << 4 ) |  \
    102             ((data >> 4) & 0xf0)  | ((data >>12) & 0xf))
    103 #define SOC_TD2P_NIB_TRX(data)  \
    104             ((0x3-(data&0x0f)) | (0x30-(data&0xf0)) | \
    105             (0x300-(data&0xf00)) | (0x3000-(data&0xf000)))
    106 
    107 #ifdef PORTMOD_PM4X10TD_SUPPORT
    108 static portmod_default_user_access_t *pm4x10_td2p_user_acc[SOC_MAX_NUM_DEVICES];
    109 #endif /* PORTMOD_PM4X10TD_SUPPORT */
    110 
    111 #ifdef PORTMOD_PM12X10_SUPPORT
    112 static portmod_default_user_access_t *pm12x10_td2p_user_acc[SOC_MAX_NUM_DEVICES];
    113 static portmod_default_user_access_t *pm12_4x10_td2p_user_acc[SOC_MAX_NUM_DEVICES];
    114 static portmod_default_user_access_t *pm12_4x25_td2p_user_acc[SOC_MAX_NUM_DEVICES];
    115 #endif /* PORTMOD_PM12X10_SUPPORT */
    116 
    117 #ifdef PORTMOD_PM4X25_SUPPORT
    118 static portmod_default_user_access_t *pm4x25_td2p_user_acc[SOC_MAX_NUM_DEVICES];
    119 #endif /* PORTMOD_PM4X25_SUPPORT */
    120 
    121 
    122 soc_portctrl_functions_t soc_td2p_portctrl_func = {
    123     soc_td2p_portctrl_pm_portmod_init,
    124     soc_td2p_portctrl_pm_portmod_deinit,
    125     soc_td2p_portctrl_pm_port_config_get,
    126     soc_td2p_portctrl_pm_port_phyaddr_get,
    127     NULL,
    128     soc_td2p_portctrl_pm_type_get,
    129     NULL,
    130     NULL
    131 };
    132 
    133 STATIC int
    134 _soc_td2p_portctrl_pm_init(int unit, int *max_phys,
    135                            portmod_pm_instances_t **pm_types,
    136                            int *pms_arr_len)
    137 {
    138     *max_phys = SOC_TD2P_MAX_PHYS;
    139     *pm_types = td2p_pm_types;
    140     *pms_arr_len = sizeof(td2p_pm_types)/sizeof(portmod_pm_instances_t);
    141     return SOC_E_NONE;
    142 }
    143 
    144 STATIC int
    145 _soc_td2p_portctrl_device_addr_port_get(int unit, int pm_type,
    146                                         uint32_t **addr,
    147                                         uint32_t **port,
    148                                         uint32_t **core_num)
    149 {
    150     *addr     = NULL;
    151     *port     = NULL;
    152     *core_num = NULL;
    153 #ifdef PORTMOD_PM4X10TD_SUPPORT
    154     if (pm_type == portmodDispatchTypePm4x10td) {
    155         *addr = _td2p_pm4x10_addr;
    156         *port = _td2p_pm4x10_port;
    157         *core_num = _td2p_pm4x10_core_num;
    158     } else
    159 #endif
    160 #ifdef PORTMOD_PM12X10_SUPPORT
    161     if (pm_type == portmodDispatchTypePm12x10){
    162         *addr = _td2p_pm12x10_addr;
    163         *port = _td2p_pm12x10_port;
    164         *core_num = _td2p_pm12x10_core_num;
    165     }
    166 #endif
    167 
    168     return SOC_E_NONE;
    169 }
    170 
    171 STATIC int
    172 _soc_td2p_portctrl_pm_user_acc_flag_set(int unit,
    173                     portmod_default_user_access_t* pm_user_access)
    174 {
    175     PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_SET((pm_user_access));
    176     return SOC_E_NONE;
    177 }
    178 
    179 STATIC int
    180 _soc_td2p_portctrl_is_chip_bonding_swap(int unit, int pm_inst,
    181                     int core_num, int type, int is_tx)
    182 {
    183 #ifdef PORTMOD_PM12X10_SUPPORT
    184     int is_pm12x10 = (type == portmodDispatchTypePm12x10) ? 1: 0;
    185     /* 
    186      * PM4X10 :  ODD  Inst: Rx Flip
    187      * PM4X10 :  EVEN Inst: Tx Flip
    188      * PM12x10:  ODD  Inst: Core 0,2 Rx Flip, Core 1 Tx Flip
    189      * PM12x10:  EVEN Inst: Core 0,2 Tx Flip, Core 1 Rx Flip
    190      */
    191     return is_tx ?
    192         (is_pm12x10? ((pm_inst&1)? !(core_num&1):  (core_num&1)) : !(pm_inst&1)) :
    193         (is_pm12x10? ((pm_inst&1)?  (core_num&1): !(core_num&1)) :  (pm_inst&1));
    194 #endif /* PORTMOD_PM12X10_SUPPORT */
    195     return (0);
    196 }
    197 
    198 /*
    199  * Polarity get looks for physical port based config first. This will enable
    200  * the user to define the polarity for all ports weather mapped to logical 
    201  * port or not.
    202  *
    203  * For legacy compatibility - we still look for the logical port
    204  * config setup.
    205  */
    206 STATIC 
    207 void _pm_port_polarity_get (int unit, int logical_port, int physical_port, int lane,
    208                             int core_num,uint32 *tx_pol, uint32* rx_pol)       
    209 {
    210     uint32 rx_polarity, tx_polarity, num_lanes=1;
    211 
    212     if (logical_port != -1) {
    213         num_lanes = SOC_INFO(unit).port_num_lanes[logical_port];
    214     }
    215 
    216     rx_polarity = soc_property_phy_get (unit, physical_port, 0, 0, lane, 
    217                                         spn_PHY_CHAIN_RX_POLARITY_FLIP_PHYSICAL, 0xFFFFFFFF);
    218     if (rx_polarity == 0xFFFFFFFF) { 
    219         rx_polarity = soc_property_port_get(unit, logical_port, 
    220                             spn_PHY_XAUI_RX_POLARITY_FLIP, 0);
    221         *rx_pol = (num_lanes == 1) ? ((rx_polarity & 0x1) << lane): rx_polarity;
    222         if (logical_port != -1) {
    223             if (IS_C_PORT(unit, logical_port)) {
    224                 *rx_pol =  ((rx_polarity >> (core_num * SOC_PM4X10_NUM_LANES)) & 0xf);
    225             }
    226         }
    227     } else {
    228         *rx_pol = (rx_polarity & 0x1) << lane; 
    229         /* *rx_pol = (num_lanes == 1) ? ((rx_polarity & 0x1) << lane): rx_polarity;*/
    230     }
    231 
    232     tx_polarity = soc_property_phy_get (unit, physical_port, 0, 0, lane, 
    233                                         spn_PHY_CHAIN_TX_POLARITY_FLIP_PHYSICAL, 0xFFFFFFFF);
    234     if (tx_polarity == 0xFFFFFFFF) {
    235         tx_polarity =  soc_property_port_get(unit, logical_port, 
    236                           spn_PHY_XAUI_TX_POLARITY_FLIP, 0);
    237         *tx_pol = (num_lanes == 1) ? ((tx_polarity & 0x1) << lane) : tx_polarity;
    238         if (logical_port != -1) {
    239             if (IS_C_PORT(unit, logical_port)) {
    240                 *tx_pol =  ((tx_polarity >> (core_num * SOC_PM4X10_NUM_LANES)) & 0xf);
    241             }
    242         }
    243     } else {
    244         *tx_pol = (tx_polarity & 0x1) << lane;
    245         /* *tx_pol = (num_lanes == 1) ? ((tx_polarity & 0x1) << lane) : tx_polarity;*/
    246     }
    247 } 
    248 
    249 /*
    250  * lanemap get looks for physical port based config first. This will enable
    251  * the user to define the lanemap for all ports weather mapped to logical 
    252  * port or not.
    253  *
    254  * For legacy compatibility - we still look for the logical port
    255  * config setup.
    256  */
    257 STATIC 
    258 void _pm_port_lanemap_get (int unit, int logical_port, int physical_port, int core_num, 
    259                            uint32 *txlane_map, uint32* rxlane_map)       
    260 {
    261 
    262     *rxlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 
    263                                         spn_PHY_CHAIN_RX_LANE_MAP_PHYSICAL, 0xFFFFFFFF);
    264 
    265     if (*rxlane_map == 0xFFFFFFFF) {
    266         *rxlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 
    267                                         spn_PHY_RX_LANE_MAP, 0xFFFFFFFF);
    268     }
    269     if (*rxlane_map == 0xFFFFFFFF) {
    270         *rxlane_map = soc_property_port_suffix_num_get(unit, logical_port, core_num,
    271                                                  spn_XGXS_RX_LANE_MAP,
    272                                                  "core", 0x3210);
    273     }
    274 
    275     *txlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 
    276                                         spn_PHY_CHAIN_TX_LANE_MAP_PHYSICAL, 0xFFFFFFFF);
    277 
    278     if (*txlane_map == 0xFFFFFFFF)  {
    279         *txlane_map = soc_property_phy_get (unit, physical_port, 0, 0, 0, 
    280                                         spn_PHY_TX_LANE_MAP, 0xFFFFFFFF);
    281     }
    282     if (*txlane_map == 0xFFFFFFFF) {
    283         *txlane_map = soc_property_port_suffix_num_get(unit, logical_port, core_num,
    284                                                  spn_XGXS_TX_LANE_MAP,
    285                                                  "core", 0x3210);
    286     }
    287 }
    288 
    289 STATIC int
    290 _soc_td2p_portctrl_pm4x10_portmod_init(int unit, int num_of_instances) 
    291 {
    292 #ifdef PORTMOD_PM4X10TD_SUPPORT
    293     int rv = SOC_E_NONE;
    294     portmod_pm_create_info_t pm_info;
    295     int pmid = 0, blk, is_sim, found, logical_port;
    296     int first_port, idx, core_num, core_cnt;
    297     uint32 *pAddr, *pPort, *pCoreNum;
    298     int mode;
    299 
    300     SOC_IF_ERROR_RETURN
    301         (_soc_td2p_portctrl_device_addr_port_get(unit,
    302                                                  portmodDispatchTypePm4x10td,
    303                                                  &pAddr, &pPort, &pCoreNum));
    304     if (!pAddr || !pPort) {
    305         return SOC_E_INTERNAL;
    306     }
    307 
    308     /* Allocate PMs */
    309     SOC_IF_ERROR_RETURN
    310         (soc_esw_portctrl_pm_user_access_alloc(unit,
    311                                            num_of_instances,
    312                                            &pm4x10_td2p_user_acc[unit]));
    313 
    314     for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) {
    315 
    316         rv = portmod_pm_create_info_t_init(unit, &pm_info);
    317         if (PORTMOD_FAILURE(rv)) {
    318             break;
    319         }
    320         /* PM info */
    321         first_port = pPort[pmid];
    322 
    323         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port);
    324         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1);
    325         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2);
    326         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3);
    327 
    328         found = 0;
    329         for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){
    330             blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk;
    331             if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT){
    332                 found = 1;
    333                 break;
    334             }
    335         }
    336 
    337         if (!found) {
    338             rv = SOC_E_INTERNAL;
    339             break;
    340         } 
    341 
    342         pm_info.type         = portmodDispatchTypePm4x10td;
    343 
    344         /* Init user_acc for phymod access struct */
    345         rv = portmod_default_user_access_t_init(unit,
    346                                                 &(pm4x10_td2p_user_acc[unit][pmid]));
    347         if (PORTMOD_FAILURE(rv)) {
    348             break;
    349         }
    350 
    351         SOC_IF_ERROR_RETURN(
    352             _soc_td2p_portctrl_pm_user_acc_flag_set(unit,
    353                 &(pm4x10_td2p_user_acc[unit][pmid])));
    354 
    355         pm4x10_td2p_user_acc[unit][pmid].unit = unit;
    356         pm4x10_td2p_user_acc[unit][pmid].blk_id = blk; 
    357         pm4x10_td2p_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex");
    358         if (pm4x10_td2p_user_acc[unit][pmid].mutex == NULL) {
    359             rv = SOC_E_MEMORY;
    360             break;
    361         }
    362 
    363         /* Specific info for PM4x10 */
    364         rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x10.access);
    365         if (PORTMOD_FAILURE(rv)) {
    366             break;
    367         }
    368 
    369         pm_info.pm_specific_info.pm4x10.access.user_acc =
    370             &(pm4x10_td2p_user_acc[unit][pmid]);
    371         pm_info.pm_specific_info.pm4x10.access.addr     = pAddr[pmid];
    372         pm_info.pm_specific_info.pm4x10.access.bus      = NULL; /* Use default bus */
    373 
    374         rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce,
    375                                   &(pm_info.pm_specific_info.pm4x10.access),
    376                                   0, &is_sim);
    377         if (PORTMOD_FAILURE(rv)) {
    378             break;
    379         }
    380 
    381         if (is_sim) {
    382             pm_info.pm_specific_info.pm4x10.access.bus->bus_capabilities |=
    383                 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL);
    384 
    385             /* Firmward loader : Don't allow FW load on sim enviroment */
    386             pm_info.pm_specific_info.pm4x10.fw_load_method =
    387                 phymodFirmwareLoadMethodNone;
    388         }
    389 
    390         /* Use default external loader if NULL */
    391         pm_info.pm_specific_info.pm4x10.external_fw_loader = NULL;
    392 
    393         logical_port = SOC_INFO(unit).port_p2l_mapping[first_port];
    394         core_cnt = 1; 
    395 
    396         for (core_num = 0; core_num < core_cnt; core_num++) {
    397             pm_info.pm_specific_info.pm4x10.core_num = pCoreNum? pCoreNum[pmid] : pmid;
    398             pm_info.pm_specific_info.pm4x10.core_num_int = 0;
    399             pm_info.pm_specific_info.pm4x10.rescal = -1;
    400         }
    401 
    402         pm_info.pm_specific_info.pm4x10.portmod_phy_external_reset
    403             = soc_esw_portctrl_reset_tsc3_cb;
    404 
    405         SOC_IF_ERROR_RETURN(soc_td2p_port_mode_get(unit, logical_port, &mode));
    406         if (mode == portmodPortModeTri012 || mode == portmodPortModeTri023) {
    407             pm_info.pm_specific_info.pm4x10.port_mode_aux_info = portmodModeInfoThreePorts;
    408         }
    409         /* Add PM to PortMod */
    410         rv = portmod_port_macro_add(unit, &pm_info);
    411     }
    412 
    413     if (PORTMOD_FAILURE(rv)) {
    414         for (pmid=0; pmid < num_of_instances; pmid++) {
    415             if (pm4x10_td2p_user_acc[unit][pmid].mutex) {
    416                 sal_mutex_destroy(pm4x10_td2p_user_acc[unit][pmid].mutex);
    417                 pm4x10_td2p_user_acc[unit][pmid].mutex = NULL;
    418             }
    419         }
    420     }
    421 
    422     return rv;
    423 #else /* PORTMOD_PM4X10TD_SUPPORT */
    424     return SOC_E_UNAVAIL;
    425 #endif /* PORTMOD_PM4X10TD_SUPPORT */
    426 }
    427 
    428 STATIC int
    429 _soc_td2p_portctrl_pm4x25_portmod_init(int unit, int num_of_instances) 
    430 {
    431 #ifdef PORTMOD_PM4X25_SUPPORT
    432     int rv = SOC_E_NONE;
    433     portmod_pm_create_info_t pm_info;
    434     int pmid = 0, blk, is_sim, lane, phy, found, logical_port;
    435     int first_port, idx, ref_clk_prop, core_num, core_cnt;
    436     uint32 txlane_map, rxlane_map, *pAddr, *pPort,*pCoreNum;
    437     int bonding_swap_tx, bonding_swap_rx ; /*TEMP */
    438     uint32 tx_polarity, rx_polarity;
    439     
    440     SOC_IF_ERROR_RETURN
    441         (_soc_td2p_portctrl_device_addr_port_get(unit,
    442                                                  portmodDispatchTypePm4x25,
    443                                                  &pAddr, &pPort,&pCoreNum));
    444     if (!pAddr || !pPort) {
    445         return SOC_E_INTERNAL;
    446     }
    447 
    448     /* Allocate PMs */
    449     SOC_IF_ERROR_RETURN
    450         (soc_esw_portctrl_pm_user_access_alloc(unit,
    451                                            num_of_instances,
    452                                            &pm4x25_td2p_user_acc[unit]));
    453 
    454     for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) {
    455 
    456         rv = portmod_pm_create_info_t_init(unit, &pm_info);
    457         if (PORTMOD_FAILURE(rv)) {
    458             break;
    459         }
    460         /* PM info */
    461         first_port = pPort[pmid];
    462 
    463         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port);
    464         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 
    465         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2);
    466         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3);
    467 
    468         found = 0;
    469         for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 
    470             blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 
    471             if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_CLPORT){
    472                 found = 1;
    473                 break;
    474             }
    475         }
    476 
    477         if (!found) {
    478             rv = SOC_E_INTERNAL;
    479             break;
    480         } 
    481 
    482         pm_info.type         = portmodDispatchTypePm4x25;
    483 
    484         /* Init user_acc for phymod access struct */
    485         rv = portmod_default_user_access_t_init(unit,
    486                                                 &(pm4x25_td2p_user_acc[unit][pmid]));
    487         if (PORTMOD_FAILURE(rv)) {
    488             break;
    489         }
    490 
    491         PORTMOD_USER_ACCESS_FW_LOAD_REVERSE_SET((&(pm4x25_td2p_user_acc[unit][pmid])));
    492         PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_CLR((&(pm4x25_td2p_user_acc[unit][pmid])));
    493         pm4x25_td2p_user_acc[unit][pmid].unit = unit;
    494         pm4x25_td2p_user_acc[unit][pmid].blk_id = blk; 
    495         pm4x25_td2p_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex");
    496         if (pm4x25_td2p_user_acc[unit][pmid].mutex == NULL) {
    497             rv = SOC_E_MEMORY;
    498             break;
    499         }
    500 
    501         /* Specific info for PM4x25 */
    502         rv = phymod_access_t_init(&pm_info.pm_specific_info.pm4x25.access);
    503         if (PORTMOD_FAILURE(rv)) {
    504             break;
    505         }
    506 
    507         pm_info.pm_specific_info.pm4x25.access.user_acc =
    508             &(pm4x25_td2p_user_acc[unit][pmid]);
    509         pm_info.pm_specific_info.pm4x25.access.addr     = pAddr[pmid];
    510         pm_info.pm_specific_info.pm4x25.access.bus      = NULL; /* Use default bus */
    511 
    512         rv = soc_physim_check_sim(unit, phymodDispatchTypeTscf, 
    513                                   &(pm_info.pm_specific_info.pm4x25.access),
    514                                   0, &is_sim);
    515 
    516         if (PORTMOD_FAILURE(rv)) {
    517             break;
    518         }
    519 
    520         if (is_sim) {
    521             pm_info.pm_specific_info.pm4x25.access.bus->bus_capabilities |= 
    522                 (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL);
    523 
    524             /* Firmward loader : Don't allow FW load on sim enviroment */
    525             pm_info.pm_specific_info.pm4x25.fw_load_method =
    526                 phymodFirmwareLoadMethodNone;
    527         } else {
    528             pm_info.pm_specific_info.pm4x25.fw_load_method = 
    529                 soc_property_suffix_num_get(unit, pmid, 
    530                                             spn_LOAD_FIRMWARE, "quad", 
    531                                             phymodFirmwareLoadMethodExternal);
    532             pm_info.pm_specific_info.pm4x25.fw_load_method &= 0xff;
    533         }
    534 
    535         /* Use default external loader if NULL */
    536         pm_info.pm_specific_info.pm4x25.external_fw_loader = NULL;
    537 
    538         /* Polarity */
    539         rv = phymod_polarity_t_init (&(pm_info.pm_specific_info.pm4x25.polarity));
    540         if (PORTMOD_FAILURE(rv)) {
    541             break;
    542         }
    543 
    544         for (lane = 0; lane < SOC_PM4X25_NUM_LANES; lane++) {
    545             phy = first_port+lane;
    546             logical_port = SOC_INFO(unit).port_p2l_mapping[phy];
    547 
    548             _pm_port_polarity_get (unit, logical_port, phy, lane,0, &tx_polarity, &rx_polarity);       
    549 
    550             pm_info.pm_specific_info.pm4x25.polarity.rx_polarity |= rx_polarity;
    551             pm_info.pm_specific_info.pm4x25.polarity.tx_polarity |= tx_polarity;
    552 
    553             if (SOC_INFO(unit).port_num_lanes[logical_port] >= SOC_PM4X25_NUM_LANES) break; 
    554         }
    555 
    556         /* Lane map */
    557         rv = phymod_lane_map_t_init
    558             (&(pm_info.pm_specific_info.pm4x25.lane_map));
    559         if (PORTMOD_FAILURE(rv)) {
    560             break;
    561         }
    562 
    563         logical_port = SOC_INFO(unit).port_p2l_mapping[first_port];
    564         core_cnt = 1; 
    565 
    566         for (core_num = 0; core_num < core_cnt; core_num++) {
    567             _pm_port_lanemap_get (unit, logical_port, first_port, core_num, &txlane_map, &rxlane_map);       
    568 
    569             bonding_swap_tx = _soc_td2p_portctrl_is_chip_bonding_swap(unit, pmid, core_num, portmodDispatchTypePm4x25, 1) ;
    570             txlane_map = bonding_swap_tx ?
    571                              SOC_TD2P_NIB_SWAP(txlane_map) : txlane_map;
    572             
    573             bonding_swap_rx = _soc_td2p_portctrl_is_chip_bonding_swap(unit, pmid, core_num, portmodDispatchTypePm4x25, 0) ;
    574             rxlane_map = bonding_swap_rx ?
    575                              SOC_TD2P_NIB_SWAP(rxlane_map) : rxlane_map;
    576 
    577             pm_info.pm_specific_info.pm4x25.lane_map.num_of_lanes =
    578                 SOC_PM4X25_NUM_LANES;
    579    
    580             pm_info.pm_specific_info.pm4x25.core_num = pCoreNum? pCoreNum[pmid] : pmid;
    581             pm_info.pm_specific_info.pm4x25.core_num_int = 0;
    582             pm_info.pm_specific_info.pm4x25.rescal = -1;
    583  
    584             for(lane=0 ; lane<SOC_PM4X25_NUM_LANES; lane++) {
    585                 pm_info.pm_specific_info.pm4x25.lane_map.lane_map_tx[lane] =  
    586                     (txlane_map >> (lane * SOC_PM4X25_NUM_LANES)) &
    587                     SOC_PM4X25_LANE_MASK;
    588                 pm_info.pm_specific_info.pm4x25.lane_map.lane_map_rx[lane] =  
    589                     (rxlane_map >> (lane * SOC_PM4X25_NUM_LANES)) &
    590                     SOC_PM4X25_LANE_MASK;
    591             }
    592         }
    593 
    594         ref_clk_prop = soc_property_port_get(unit, first_port,
    595                             spn_XGXS_LCPLL_XTAL_REFCLK, 156);
    596 
    597 	    if ((ref_clk_prop == 156) ||( ref_clk_prop == 1)){
    598             pm_info.pm_specific_info.pm4x25.ref_clk = phymodRefClk156Mhz;
    599         }
    600         else if (ref_clk_prop == 125){     
    601             pm_info.pm_specific_info.pm4x25.ref_clk = phymodRefClk125Mhz;
    602         }
    603         else {
    604             LOG_ERROR(BSL_LS_SOC_PORT,
    605                     (BSL_META_UP(unit, first_port,
    606                               "ERROR: This %d MHz clk freq is not supported. Only 156 MHz and 125 MHz.\n"),ref_clk_prop));
    607             return SOC_E_PARAM ;
    608 
    609         }
    610         /* Add PM to PortMod */
    611         rv = portmod_port_macro_add(unit, &pm_info);
    612     }
    613 
    614     if (PORTMOD_FAILURE(rv)) {
    615         for (pmid=0; pmid < num_of_instances; pmid++) {
    616             if (pm4x25_td2p_user_acc[unit][pmid].mutex) {
    617                 sal_mutex_destroy(pm4x25_td2p_user_acc[unit][pmid].mutex);
    618                 pm4x25_td2p_user_acc[unit][pmid].mutex = NULL;
    619             }
    620         }
    621     }
    622 
    623     return rv;
    624 #else /* PORTMOD_PM4X25_SUPPORT */
    625     return SOC_E_UNAVAIL;
    626 #endif /* PORTMOD_PM4X25_SUPPORT */
    627 }
    628 
    629 
    630 STATIC int
    631 _soc_td2p_portctrl_pm12x10_portmod_init(int unit, int num_of_instances) 
    632 {
    633 #if defined(PORTMOD_PM12X10_SUPPORT)
    634     int rv = SOC_E_NONE;
    635     portmod_pm_create_info_t  pm_info;
    636     portmod_pm4x10_create_info_t *pm4x10_info;
    637     portmod_pm4x25_create_info_t *pm4x25_info;
    638     int pmid = 0, blk, is_sim, phy, found, logical_port;
    639     int first_port, idx, core_num=0;
    640     uint32 *pAddr, *pPort, *pCoreNum;
    641     int mode;
    642 
    643     SOC_IF_ERROR_RETURN
    644         (_soc_td2p_portctrl_device_addr_port_get(unit,
    645                                                  portmodDispatchTypePm12x10,
    646                                                  &pAddr, &pPort, &pCoreNum)); 
    647     if (!pAddr || !pPort) {
    648         return SOC_E_INTERNAL;
    649     }
    650 
    651     SOC_IF_ERROR_RETURN
    652         (soc_esw_portctrl_pm_user_access_alloc(unit,
    653                                            num_of_instances,
    654                                            &pm12x10_td2p_user_acc[unit]));
    655 
    656     SOC_IF_ERROR_RETURN
    657         (soc_esw_portctrl_pm_user_access_alloc(unit,
    658                                            num_of_instances*SOC_PM12X10_PM4X10_COUNT,
    659                                            &pm12_4x10_td2p_user_acc[unit]));
    660 
    661     SOC_IF_ERROR_RETURN
    662         (soc_esw_portctrl_pm_user_access_alloc(unit,
    663                                            num_of_instances,
    664                                            &pm12_4x25_td2p_user_acc[unit]));
    665 
    666 
    667     /* Register PM12x10 */
    668     for (pmid = 0; PORTMOD_SUCCESS(rv) && (pmid < num_of_instances); pmid++) {
    669         int core_idx, core_blk;
    670 
    671         rv = portmod_pm_create_info_t_init(unit, &pm_info);
    672         if (PORTMOD_FAILURE(rv)) {
    673             break;
    674         }
    675 
    676         pm_info.pm_specific_info.pm12x10.refclk_source = 0;
    677 
    678         /* PM info */
    679         first_port = pPort[pmid];
    680 
    681         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port);
    682         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+1); 
    683         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+2);
    684         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+3);
    685         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+4);
    686         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+5); 
    687         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+6);
    688         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+7);
    689         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+8);
    690         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+9); 
    691         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+10);
    692         PORTMOD_PBMP_PORT_ADD(pm_info.phys, first_port+11);
    693 
    694         found = 0;
    695         for(idx = 0; idx < SOC_DRIVER(unit)->port_num_blktype; idx++){ 
    696             blk = SOC_PORT_IDX_INFO(unit, first_port, idx).blk; 
    697             if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT){
    698                 found = 1;
    699                 break;
    700             }
    701         }
    702 
    703         if (!found) {
    704              rv = SOC_E_INTERNAL;
    705              break;
    706         } 
    707         pm_info.type         = portmodDispatchTypePm12x10;
    708 
    709 
    710         /* init user_acc for phymod access struct */
    711         rv = portmod_default_user_access_t_init(unit,
    712                                                 &(pm12x10_td2p_user_acc[unit][pmid]));
    713         if (PORTMOD_FAILURE(rv)) {
    714             break;
    715         }
    716 
    717         PORTMOD_USER_ACCESS_REG_VAL_OFFSET_ZERO_SET((&(pm12x10_td2p_user_acc[unit][pmid])));
    718         pm12x10_td2p_user_acc[unit][pmid].unit = unit;
    719         pm12x10_td2p_user_acc[unit][pmid].blk_id = blk; 
    720         pm12x10_td2p_user_acc[unit][pmid].mutex = sal_mutex_create("core mutex");
    721         if (pm12x10_td2p_user_acc[unit][pmid].mutex == NULL) {
    722             rv = SOC_E_MEMORY;
    723             break;
    724         }
    725 
    726         for (core_num = 0;
    727              PORTMOD_SUCCESS(rv) && (core_num < SOC_PM12X10_PM4X10_COUNT);
    728              core_num++) {
    729 
    730             /* PM4X10 INFO UPDATE */
    731             pm4x10_info = &pm_info.pm_specific_info.pm12x10.pm4x10_infos[core_num];
    732 
    733             /* Specific info for PM12x10 */
    734             rv = phymod_access_t_init(&pm4x10_info->access);
    735             if (PORTMOD_FAILURE(rv)) {
    736                 break;
    737             }
    738             pm12_4x10_td2p_user_acc[unit][(pmid*3)+core_num] = pm12x10_td2p_user_acc[unit][pmid];
    739 
    740             found = 0;
    741             for(core_idx = 0; core_idx < SOC_DRIVER(unit)->port_num_blktype; core_idx++){
    742                 core_blk = SOC_PORT_IDX_INFO(unit, (first_port+(4*core_num)), core_idx).blk;
    743                 if (SOC_BLOCK_INFO(unit, core_blk).type == SOC_BLK_XLPORT){
    744                     found = 1;
    745                     break;
    746                 }
    747             }
    748 
    749             if (!found) {
    750                 /* Internal Error */
    751                 break;
    752             }
    753 
    754             pm12_4x10_td2p_user_acc[unit][(pmid*3)+core_num].blk_id = core_blk; 
    755             pm4x10_info->access.user_acc = &(pm12_4x10_td2p_user_acc[unit][(pmid*3)+core_num]);
    756             pm4x10_info->access.addr     = pAddr[(pmid*3) + core_num]; 
    757             pm4x10_info->access.bus      = NULL;
    758             pm4x10_info->core_num        = pCoreNum? pCoreNum[(pmid*3)+core_num] : ((pmid*3)+core_num);
    759             pm4x10_info->core_num_int    = core_num;
    760             pm4x10_info->rescal          = -1;
    761 
    762             rv = soc_physim_check_sim(unit, phymodDispatchTypeTsce, 
    763                                       &(pm4x10_info->access), 0, &is_sim);
    764             if (PORTMOD_FAILURE(rv)) {
    765                 break;
    766             }
    767 
    768             if (is_sim) {
    769                 pm4x10_info->access.bus->bus_capabilities |= 
    770                     (PHYMOD_BUS_CAP_WR_MODIFY | PHYMOD_BUS_CAP_LANE_CTRL);
    771 
    772                 /* Firmward loader : Don't allow FW load on sim enviroment */
    773                 pm4x10_info->fw_load_method = phymodFirmwareLoadMethodNone;
    774             }
    775 
    776             /* Use default external loader */
    777             pm4x10_info->external_fw_loader = NULL; 
    778 
    779             /* Three Port Mode */
    780             {
    781                 phy = first_port+(core_num*4);
    782                 logical_port = SOC_INFO(unit).port_p2l_mapping[phy];
    783 
    784                 SOC_IF_ERROR_RETURN(soc_td2p_port_mode_get(unit, logical_port, &mode));
    785                 if (mode == portmodPortModeTri012 || mode == portmodPortModeTri023) {
    786                     pm4x10_info->port_mode_aux_info = portmodModeInfoThreePorts;
    787                 }
    788             }
    789 
    790         }
    791 
    792         PORTMOD_PM12x10_F_EXTERNAL_TOP_MODE_SET(pm_info.pm_specific_info.pm12x10.flags);
    793         PORTMOD_PM12x10_F_USE_PM_TD_SET(pm_info.pm_specific_info.pm12x10.flags);
    794 
    795         pm_info.pm_specific_info.pm12x10.pm4x10_infos[1].portmod_phy_external_reset =
    796             soc_esw_portctrl_reset_tsc1_cb;
    797         pm_info.pm_specific_info.pm12x10.pm4x10_infos[0].portmod_phy_external_reset = 
    798             (pmid&1)? soc_esw_portctrl_reset_tsc2_cb : soc_esw_portctrl_reset_tsc0_cb;
    799         pm_info.pm_specific_info.pm12x10.pm4x10_infos[2].portmod_phy_external_reset = 
    800             (pmid&1)? soc_esw_portctrl_reset_tsc0_cb : soc_esw_portctrl_reset_tsc2_cb;
    801 
    802 
    803         /* PM4X25 INFO UPDATE */
    804         pm4x25_info = &pm_info.pm_specific_info.pm12x10.pm4x25_info;
    805 
    806         /* Specific info for PM12x10 */
    807         rv = phymod_access_t_init(&pm4x25_info->access);
    808         if (PORTMOD_FAILURE(rv)) {
    809             break;
    810         }
    811         pm12_4x25_td2p_user_acc[unit][pmid] = pm12x10_td2p_user_acc[unit][pmid];
    812         found = 0;
    813         first_port = pPort[pmid];
    814         for(core_idx = 0; core_idx < SOC_DRIVER(unit)->port_num_blktype; core_idx++){
    815             core_blk = SOC_PORT_IDX_INFO(unit, first_port, core_idx).blk;
    816             if (SOC_BLOCK_INFO(unit, core_blk).type == SOC_BLK_CPORT){
    817                 found = 1;
    818                 break;
    819             }
    820         }
    821 
    822         if (!found) {
    823             rv = SOC_E_INTERNAL;
    824             break;
    825         }
    826 
    827         pm12_4x25_td2p_user_acc[unit][pmid].blk_id = core_blk; 
    828         pm4x25_info->lane_map.num_of_lanes    = SOC_PM4X25_NUM_LANES;
    829         pm4x25_info->access.user_acc          = &(pm12_4x25_td2p_user_acc[unit][pmid]);
    830         pm4x25_info->access.addr              = pAddr[pmid]; 
    831         pm4x25_info->access.bus               = NULL;
    832         pm4x25_info->core_num                 = pmid; 
    833         pm4x25_info->external_fw_loader       = NULL; 
    834         pm4x25_info->fw_load_method           = phymodFirmwareLoadMethodNone;
    835         pm4x25_info->rescal                   = -1;
    836 
    837         
    838         rv  = portmod_port_macro_add(unit, &pm_info);
    839     }
    840 
    841     if (PORTMOD_FAILURE(rv)) {
    842         for (pmid=0; pmid < num_of_instances; pmid++)  {
    843             if (pm12x10_td2p_user_acc[unit][pmid].mutex) {
    844                 sal_mutex_destroy(pm12x10_td2p_user_acc[unit][pmid].mutex);
    845                 pm12x10_td2p_user_acc[unit][pmid].mutex = NULL;
    846             }
    847         }
    848     }
    849     return rv; 
    850 #else /* PORTMOD_PM12X10_SUPPORT */
    851     return SOC_E_UNAVAIL;
    852 #endif /* PORTMOD_PM12X10_SUPPORT */
    853 }
    854 
    855 /*
    856  * Function:
    857  *      soc_td2p_portctrl_pm_portmod_init
    858  * Purpose:
    859  *      Initialize PortMod and PortMacro for Trident2Plus
    860  *      Add port macros (PM) to the unit's PortMod Manager (PMM).
    861  * Parameters:
    862  *      unit             - (IN) Unit number.
    863  * Returns:
    864  *      SOC_E_XXX
    865  */
    866 int
    867 soc_td2p_portctrl_pm_portmod_init(int unit)
    868 {
    869     uint32 flags = 0;
    870     int rv = SOC_E_NONE, pms_arr_len = 0, count, max_phys= 0;
    871     portmod_pm_instances_t *pm_types = NULL;
    872 
    873     /* Call PortMod library initialization */
    874     SOC_IF_ERROR_RETURN(
    875         _soc_td2p_portctrl_pm_init(unit, &max_phys,
    876                                    &pm_types, &pms_arr_len));
    877     if (pms_arr_len == 0) {
    878         return SOC_E_UNAVAIL;
    879     }
    880 
    881     /*
    882      * If portmod was create - destroy and create again
    883      * Better way would be to create once and leave it.
    884      */
    885     if (SOC_E_NONE == soc_esw_portctrl_init_check(unit)) {
    886         SOC_IF_ERROR_RETURN(portmod_destroy(unit));
    887     }
    888 
    889     PORTMOD_CREATE_F_PM_NULL_SET(flags);
    890 
    891     SOC_IF_ERROR_RETURN
    892         (portmod_create(unit, flags, SOC_MAX_NUM_PORTS, max_phys,
    893                         pms_arr_len, pm_types));
    894 
    895     for (count = 0; SOC_SUCCESS(rv) && (count < pms_arr_len); count++) {
    896 #ifdef PORTMOD_PM4X10TD_SUPPORT
    897         if (pm_types[count].type == portmodDispatchTypePm4x10td) {
    898             rv = _soc_td2p_portctrl_pm4x10_portmod_init
    899                 (unit, pm_types[count].instances);
    900         } else 
    901 #endif /* PORTMOD_PM4X10TD_SUPPORT  */
    902 #ifdef PORTMOD_PM4X25_SUPPORT
    903         if (pm_types[count].type == portmodDispatchTypePm4x25) {
    904             rv = _soc_td2p_portctrl_pm4x25_portmod_init
    905                 (unit, pm_types[count].instances);
    906         } else
    907 #endif /* PORTMOD_PM4X25_SUPPORT  */
    908 #ifdef PORTMOD_PM12X10_SUPPORT
    909         if (pm_types[count].type == portmodDispatchTypePm12x10) {
    910             rv = _soc_td2p_portctrl_pm12x10_portmod_init
    911                 (unit, pm_types[count].instances);
    912         } else
    913 #endif /* PORTMOD_PM12X10_SUPPORT  */
    914         {
    915             rv = SOC_E_INTERNAL;
    916         }
    917     }
    918 
    919     return rv;
    920 }
    921 
    922 /*
    923  * Function:
    924  *      soc_td2p_portctrl_pm_portmod_deinit
    925  * Purpose:
    926  *      Deinitialize PortMod and PortMacro for Trident2Plus.
    927  *      Free pm user access data.
    928  * Parameters:
    929  *      unit      - (IN) Unit number.
    930  * Returns:
    931  *      SOC_E_NONE
    932  */
    933 int
    934 soc_td2p_portctrl_pm_portmod_deinit(int unit)
    935 {
    936     if (SOC_E_INIT == soc_esw_portctrl_init_check(unit)) {
    937         return SOC_E_NONE;
    938     }
    939 
    940     /* Free PMs structures */
    941 #ifdef PORTMOD_PM4X10TD_SUPPORT
    942     if (pm4x10_td2p_user_acc[unit] != NULL) {
    943         sal_free(pm4x10_td2p_user_acc[unit]);
    944         pm4x10_td2p_user_acc[unit] = NULL;
    945     }
    946 #endif /* PORTMOD_PM4X10TD_SUPPORT */
    947 
    948 #ifdef PORTMOD_PM12X10_SUPPORT
    949     if (pm12x10_td2p_user_acc[unit] != NULL) {
    950         sal_free(pm12x10_td2p_user_acc[unit]);
    951         pm12x10_td2p_user_acc[unit] = NULL;
    952     }
    953 #endif /* PORTMOD_PM12X10_SUPPORT */
    954 
    955 #ifdef PORTMOD_PM4X25_SUPPORT
    956     if (pm4x25_td2p_user_acc[unit] != NULL) {
    957         sal_free(pm4x25_td2p_user_acc[unit]);
    958         pm4x25_td2p_user_acc[unit] = NULL;
    959     }
    960 #endif /* PORTMOD_PM4X25_SUPPORT */
    961 
    962     SOC_IF_ERROR_RETURN(portmod_destroy(unit));
    963 
    964     return SOC_E_NONE;
    965 }
    966 
    967 int
    968 soc_td2p_portctrl_pm_port_config_get(int unit, soc_port_t port, void *port_config)
    969 {
    970 #ifdef PORTMOD_PM4X10TD_SUPPORT
    971     int rv = SOC_E_NONE;
    972     int pmid = 0, lane, phy, phy_port, logical_port, f_logical_port, port_mode;
    973     int first_port, core_num = 0, core_index, is_sim;
    974     int type = portmodDispatchTypeCount;
    975     uint32 txlane_map, rxlane_map, rxlane_map_l, i;
    976     uint32 *pAddr = NULL, *pPort = NULL, *pCoreNum = NULL;
    977     uint32 tx_polarity, rx_polarity;
    978     portmod_port_init_config_t *port_config_info;
    979     phymod_firmware_load_method_t fw_load_method;
    980     phymod_polarity_t polarity; /**< Lanes Polarity */
    981     phymod_lane_map_t lane_map;
    982 
    983     port_config_info = (portmod_port_init_config_t *)port_config;
    984 
    985     SOC_IF_ERROR_RETURN(soc_td2p_port_mode_get(unit, port, &port_mode));
    986     if (port_mode == portmodPortModeTri012 || port_mode == portmodPortModeTri023) {
    987         port_config_info->port_mode_aux_info = portmodModeInfoThreePorts;
    988     }
    989 
    990     phy = SOC_INFO(unit).port_l2p_mapping[port];
    991 
    992     /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */
    993     core_index = (phy - 1) / SOC_PM4X10_NUM_LANES;
    994     for (i=0; i<SOC_TD2P_PM4X10_COUNT; i++) {
    995         if (core_index == _td2p_pm4x10_core_num[i]) {
    996             type = portmodDispatchTypePm4x10td;
    997             SOC_IF_ERROR_RETURN
    998                 (_soc_td2p_portctrl_device_addr_port_get(unit,
    999                                                  portmodDispatchTypePm4x10td,
   1000                                                  &pAddr, &pPort, &pCoreNum));
   1001             pmid = i;
   1002             core_num = 1;
   1003             break;
   1004         }
   1005     }
   1006     /* When port dones't find PM4x10, find PM12x10 again. */
   1007     if (i == SOC_TD2P_PM4X10_COUNT) {
   1008         for (i=0; i<SOC_TD2P_PM12X10_COUNT*SOC_PM12X10_PM4X10_COUNT; i++) {
   1009             if (core_index == _td2p_pm12x10_core_num[i]) {
   1010                 type = portmodDispatchTypePm12x10;
   1011                 SOC_IF_ERROR_RETURN
   1012                     (_soc_td2p_portctrl_device_addr_port_get(unit,
   1013                                                  portmodDispatchTypePm12x10,
   1014                                                  &pAddr, &pPort, &pCoreNum));
   1015                 /* Because one PM12x10 has three cores and one corresponding pmid. */
   1016                 pmid = i / SOC_PM12X10_PM4X10_COUNT;
   1017                 core_num = SOC_PM12X10_PM4X10_COUNT;
   1018                 break;
   1019             }
   1020         }
   1021     }
   1022 
   1023     if (!pAddr || !pPort || type == portmodDispatchTypeCount) {
   1024         return SOC_E_INTERNAL;
   1025     }
   1026 
   1027     /* PM info */
   1028     first_port = pPort[pmid];
   1029 
   1030     for (core_index = 0; core_index < core_num; core_index++) {
   1031         fw_load_method = phymodFirmwareLoadMethodExternal;
   1032 
   1033         soc_physim_enable_get(unit, &is_sim);
   1034 
   1035         if (is_sim) {
   1036             /* Firmward loader : Don't allow FW load on sim enviroment */
   1037             fw_load_method = phymodFirmwareLoadMethodNone;
   1038         } else {
   1039             fw_load_method = soc_property_suffix_num_get(unit, pmid,
   1040                                             spn_LOAD_FIRMWARE, "quad",
   1041                                             phymodFirmwareLoadMethodExternal);
   1042             fw_load_method &= 0xff;
   1043         }
   1044 
   1045         rv = phymod_polarity_t_init(&polarity);
   1046         if (PORTMOD_FAILURE(rv)) {
   1047             break;
   1048         }
   1049 
   1050         f_logical_port = SOC_INFO(unit).port_p2l_mapping[first_port];
   1051 
   1052         /* Polarity */
   1053         for (lane = 0; lane < SOC_PM4X10_NUM_LANES; lane++) {
   1054             phy_port = first_port + lane + (core_index*4);
   1055             logical_port = SOC_INFO(unit).port_p2l_mapping[phy_port];
   1056 
   1057             /* in case of 100G - there is no logical port for core1, core2       */
   1058             /* so if the logical port is -1, check 100G and use core0            */
   1059             /* This could be a 100G port. so mapping is available for core0 only */
   1060             if (core_index && (logical_port == -1)) {
   1061                 if (IS_C_PORT(unit, f_logical_port)) {
   1062                     logical_port = f_logical_port;
   1063                 }
   1064             }
   1065 
   1066             _pm_port_polarity_get(unit, logical_port, phy_port, lane, core_index, &tx_polarity, &rx_polarity);
   1067 
   1068             polarity.rx_polarity |= rx_polarity;
   1069             polarity.tx_polarity |= tx_polarity;
   1070 
   1071         }
   1072 
   1073         /* Lane map */
   1074         rv = phymod_lane_map_t_init(&lane_map);
   1075         if (PORTMOD_FAILURE(rv)) {
   1076             break;
   1077         }
   1078 
   1079         phy_port = first_port + (core_index*4);
   1080         logical_port = SOC_INFO(unit).port_p2l_mapping[phy_port];
   1081 
   1082         if (core_index && (logical_port == -1)) {
   1083             if (IS_C_PORT(unit, f_logical_port)) {
   1084                 logical_port = f_logical_port;
   1085             }
   1086         }
   1087 
   1088         _pm_port_lanemap_get(unit, logical_port, phy_port, core_index, &txlane_map, &rxlane_map);
   1089 
   1090         rxlane_map_l = rxlane_map ;
   1091         /* For TSC-E/F family, both lane_map_rx and lane_map_tx are logic lane base */
   1092         /* TD2/TD2+ xgxs_rx_lane_map is phy-lane base */
   1093         if(SOC_IS_TRIDENT2PLUS(unit)) { /* use TD2 legacy notion system */
   1094             rxlane_map_l = 0 ;
   1095             for (i=0; i<SOC_PM4X10_NUM_LANES; i++) {
   1096                 rxlane_map_l |= i << SOC_PM4X10_NUM_LANES *((rxlane_map >> (i*SOC_PM4X10_NUM_LANES))& SOC_PM4X10_LANE_MASK) ;
   1097             }
   1098         }
   1099 
   1100         if (type == portmodDispatchTypePm12x10) {
   1101             txlane_map = (_soc_td2p_portctrl_is_chip_bonding_swap(unit, pmid, core_index, portmodDispatchTypePm12x10, 1)) ?
   1102                          SOC_TD2P_NIB_TRX(txlane_map) : txlane_map;
   1103             rxlane_map = (_soc_td2p_portctrl_is_chip_bonding_swap(unit, pmid, core_index, portmodDispatchTypePm12x10, 0)) ?
   1104                          SOC_TD2P_NIB_TRX(rxlane_map_l) : rxlane_map_l;
   1105         } else {
   1106             txlane_map = (_soc_td2p_portctrl_is_chip_bonding_swap(unit, pmid, core_index, portmodDispatchTypePm4x10td, 1)) ?
   1107                          SOC_TD2P_NIB_TRX(txlane_map) : txlane_map;
   1108 
   1109             rxlane_map = (_soc_td2p_portctrl_is_chip_bonding_swap(unit, pmid, core_index, portmodDispatchTypePm4x10td, 0)) ?
   1110                          SOC_TD2P_NIB_TRX(rxlane_map_l) : rxlane_map_l;
   1111         }
   1112 
   1113         lane_map.num_of_lanes = SOC_PM4X10_NUM_LANES;
   1114 
   1115         for(lane = 0 ; lane < SOC_PM4X10_NUM_LANES; lane++) {
   1116             lane_map.lane_map_tx[lane] =
   1117                 (txlane_map >> (lane * SOC_PM4X10_NUM_LANES)) &
   1118                 SOC_PM4X10_LANE_MASK;
   1119             lane_map.lane_map_rx[lane] =
   1120                 (rxlane_map >> (lane * SOC_PM4X10_NUM_LANES)) &
   1121                 SOC_PM4X10_LANE_MASK;
   1122         }
   1123 
   1124         sal_memcpy(&port_config_info->fw_load_method[core_index], &fw_load_method,
   1125                     sizeof(phymod_firmware_load_method_t));
   1126         port_config_info->fw_load_method_overwrite = 1;
   1127         sal_memcpy(&port_config_info->polarity[core_index], &polarity,
   1128                     sizeof(phymod_polarity_t));
   1129         port_config_info->polarity_overwrite = 1;
   1130         sal_memcpy(&port_config_info->lane_map[core_index], &lane_map,
   1131                     sizeof(phymod_lane_map_t));
   1132         port_config_info->lane_map_overwrite = 1;
   1133     }
   1134 
   1135     return rv;
   1136 #else /* PORTMOD_PM4X10TD_SUPPORT */
   1137     return SOC_E_UNAVAIL;
   1138 #endif /* PORTMOD_PM4X10TD_SUPPORT */
   1139 }
   1140 
   1141 int
   1142 soc_td2p_portctrl_pm_port_phyaddr_get(int unit, soc_port_t port)
   1143 {
   1144 #if defined(PORTMOD_PM4X10TD_SUPPORT) || defined(PORTMOD_PM12X10_SUPPORT)
   1145     int phy, core_index;
   1146     uint32 i, *pAddr = NULL, *pPort = NULL, *pCoreNum = NULL;
   1147 
   1148     phy = SOC_INFO(unit).port_l2p_mapping[port];
   1149 
   1150     /* Find the port belong to which PM. The port has its own core id, using it to compare PM. */
   1151     core_index = (phy - 1) / SOC_PM4X10_NUM_LANES;
   1152 #ifdef PORTMOD_PM4X10TD_SUPPORT
   1153     for (i=0; i<SOC_TD2P_PM4X10_COUNT; i++) {
   1154         if (core_index == _td2p_pm4x10_core_num[i]) {
   1155             SOC_IF_ERROR_RETURN
   1156                 (_soc_td2p_portctrl_device_addr_port_get(unit,
   1157                                              portmodDispatchTypePm4x10td,
   1158                                              &pAddr, &pPort, &pCoreNum));
   1159             return pAddr[i];
   1160         }
   1161     }
   1162 #endif /* PORTMOD_PM4X10TD_SUPPORT */
   1163 
   1164 #ifdef PORTMOD_PM12X10_SUPPORT
   1165     /* When port dones't find PM4x10, find PM12x10 again. */
   1166     for (i=0; i<SOC_TD2P_PM12X10_COUNT*SOC_PM12X10_PM4X10_COUNT; i++) {
   1167         if (core_index == _td2p_pm12x10_core_num[i]) {
   1168             SOC_IF_ERROR_RETURN
   1169                 (_soc_td2p_portctrl_device_addr_port_get(unit,
   1170                                              portmodDispatchTypePm12x10,
   1171                                              &pAddr, &pPort, &pCoreNum));
   1172             return pAddr[i];
   1173         }
   1174     }
   1175 #endif /* PORTMOD_PM12X10_SUPPORT */
   1176 #endif
   1177     return -1;
   1178 }
   1179 
   1180 int
   1181 soc_td2p_portctrl_pm_type_get(int unit, soc_port_t phy_port,
   1182                               int* pm_type)
   1183 {
   1184     if ((phy_port < 0) || (phy_port > 128)) {
   1185         return SOC_E_PARAM;
   1186     }
   1187 
   1188 #ifdef PORTMOD_PM4X10TD_SUPPORT
   1189     *pm_type = portmodDispatchTypePm4x10;
   1190     return SOC_E_NONE;
   1191 #else /* PORTMOD_PM4X10TD_SUPPORT */
   1192     *pm_type = -1;
   1193     return SOC_E_UNAVAIL;
   1194 #endif /* PORTMOD_PM4X10TD_SUPPORT */
   1195 }
   1196 
   1197 #endif /* BCM_TRIDENT2PLUS_SUPPORT */