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


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