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

trident3.c (546291B)


      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  * File:        trident3.c
      8  * Purpose:
      9  * Requires:
     10  */
     11 
     12 
     13 #include <shared/bsl.h>
     14 
     15 #include <sal/core/boot.h>
     16 #include <sal/core/dpc.h>
     17 #include <shared/bsl.h>
     18 #include <soc/tdm/core/tdm_top.h>
     19 #include <soc/tdm/tomahawk/tdm_th_soc.h>
     20 #ifdef BCM_CMICX_SUPPORT
     21 #include <soc/cmicx.h>
     22 #include <soc/cmicx_miim.h>
     23 #include <shared/cmicfw/iproc_m0ssq.h>
     24 #endif
     25 
     26 #include <soc/bradley.h>
     27 #include <soc/drv.h>
     28 #include <soc/error.h>
     29 #include <soc/debug.h>
     30 #include <soc/mem.h>
     31 #include <soc/i2c.h>
     32 #include <soc/l2x.h>
     33 
     34 #ifdef BCM_TRIDENT3_SUPPORT
     35 
     36 #include <soc/mmu_config.h>
     37 #include <soc/trident3.h>
     38 #include <soc/trident3_tdm.h>
     39 #include <soc/tomahawk.h>
     40 #include <soc/esw/cancun.h>
     41 #include <soc/soc_ser_log.h>
     42 #include <soc/pstats.h>
     43 #include <soc/scache.h>
     44 #include <soc/flexport/trident3/trident3_flexport_defines.h>
     45 
     46 #define _TDM_LENGTH                    256
     47 #define _OVS_GROUP_COUNT               6
     48 #define _OVS_GROUP_TDM_LENGTH          12
     49 #define TD3_NUM_PHY_PORT                (132)
     50 #define TD3_NUM_PORT                    (132)
     51 #define TD3_NUM_MMU_PORT                (226)
     52 
     53 /* Value hardcoded in set_tdm.c, definition needs to be matched */
     54 #define PORT_STATE_UNUSED              0
     55 #define PORT_STATE_LINERATE            1
     56 #define PORT_STATE_OVERSUB             2
     57 #define PORT_STATE_CONTINUATION        3 /* part of other port */
     58 
     59 #define PORT_BLOCK_BASE_PORT(port) \
     60         (1 + ((SOC_INFO(unit).port_l2p_mapping[port] - 1) & ~0x3));
     61 
     62 /* IUAT number of shared banks */
     63 
     64 #define SOC_IUAT_8K_BANKS              4
     65 #define SOC_IUAT_16K_BANKS             4
     66 
     67 #define IS_MGMT_PORT(unit,port) IS_MANAGEMENT_PORT(unit, port)
     68 
     69 static int num_shared_alpm_banks[SOC_MAX_NUM_DEVICES] = {8};
     70 static soc_mem_t *_soc_td3_alpm_bkt_view_map[SOC_MAX_NUM_DEVICES];
     71 static int8 *_soc_td3_alpm2_bnk_fmt_map[SOC_MAX_NUM_DEVICES];
     72 int
     73 _soc_td3_port_speed_cap[SOC_MAX_NUM_DEVICES][TRIDENT3_PHY_PORTS_PER_DEV];
     74 
     75 typedef struct _soc_td3_mmu_traffic_ctrl_s {
     76     uint8   thdo_drop_bmp[TD3_NUM_PORT];
     77 } _soc_td3_mmu_traffic_ctrl_t;
     78 
     79 #define   MMU_TRAFFIC_EN_CTRL           (1 << 1)
     80 #define   PORT_TX_EN_CTRL               (1 << 2)
     81 static    _soc_td3_mmu_traffic_ctrl_t
     82               *_soc_td3_mmu_traffic_ctrl[SOC_MAX_NUM_DEVICES];
     83 static    sal_mutex_t _fwd_ctrl_lock[SOC_MAX_NUM_DEVICES];
     84 #define   FWD_CTRL_LOCK(unit) \
     85           sal_mutex_take(_fwd_ctrl_lock[unit], sal_mutex_FOREVER)
     86 #define   FWD_CTRL_UNLOCK(unit) \
     87           sal_mutex_give(_fwd_ctrl_lock[unit])
     88 
     89 int soc_td3_rx_etype_niv[SOC_MAX_NUM_DEVICES];
     90 int soc_td3_rx_etype_pe[SOC_MAX_NUM_DEVICES];
     91 
     92 int
     93 _soc_trident3_init_mmu_memory(int unit);
     94 int
     95 soc_trident3_init_alpm2_memory(int unit);
     96 /* Externs */
     97 extern int soc_trident3_get_alpm_banks(int unit);
     98 extern int soc_td3_hash_mutex_init (int unit);
     99 
    100 static const soc_reg_t pvtmon_result_reg[] = {
    101     TOP_PVTMON_RESULT_0r, TOP_PVTMON_RESULT_1r,
    102     TOP_PVTMON_RESULT_2r, TOP_PVTMON_RESULT_3r,
    103     TOP_PVTMON_RESULT_4r, TOP_PVTMON_RESULT_5r,
    104     TOP_PVTMON_RESULT_6r, TOP_PVTMON_RESULT_7r,
    105     TOP_PVTMON_RESULT_8r, TOP_PVTMON_RESULT_9r,
    106     TOP_PVTMON_RESULT_10r, TOP_PVTMON_RESULT_11r
    107 };
    108 
    109 #ifdef BCM_MAVERICK2_SUPPORT
    110 static const soc_reg_t pvtmon_result_reg_mv2[] = {
    111     TOP_PVTMON_RESULT_0r, TOP_PVTMON_RESULT_1r,
    112     TOP_PVTMON_RESULT_2r, TOP_PVTMON_RESULT_3r,
    113     TOP_PVTMON_RESULT_4r, TOP_PVTMON_RESULT_5r,
    114     TOP_PVTMON_RESULT_6r, TOP_PVTMON_RESULT_7r,
    115     TOP_PVTMON_RESULT_8r, TOP_PVTMON_RESULT_11r
    116 };
    117 #endif
    118 
    119 egr_vlan_xlate_1_hash_control_entry_t       egr_vlan_1_hash_control;
    120 egr_vlan_xlate_2_hash_control_entry_t       egr_vlan_2_hash_control;
    121 egr_vp_vlan_membership_hash_control_entry_t egr_vp_vlan_mbm_hash_control;
    122 exact_match_hash_control_entry_t            exact_match_hash_control;
    123 ing_dnat_address_type_hash_control_entry_t  ing_dnat_hash_control;
    124 ing_vp_vlan_membership_hash_control_entry_t ing_vp_vlan_mbm_hash_control;
    125 l2_entry_hash_control_entry_t               l2_entry_hash_control;
    126 l3_entry_hash_control_entry_t               l3_entry_hash_control;
    127 mpls_entry_hash_control_entry_t             mpls_entry_hash_control;
    128 subport_id_to_sgpp_map_hash_control_entry_t subport_hash_control;
    129 vlan_xlate_1_hash_control_entry_t           vlan_1_hash_control;
    130 vlan_xlate_2_hash_control_entry_t           vlan_2_hash_control;
    131 uft_shared_banks_control_entry_t            uft_shared_banks_control;
    132 ip_uat_16k_shared_banks_control_entry_t     ip_uat_16k_shared_banks_control;
    133 ip_uat_8k_shared_banks_control_entry_t      ip_uat_8k_shared_banks_control;
    134 ep_uat_shared_banks_control_entry_t         ep_uat_shared_banks_control;
    135 
    136 int
    137 soc_trident3_init_alpm2_memory(int unit)
    138 {
    139     if (_soc_td3_alpm2_bnk_fmt_map[unit] != NULL) {
    140         sal_free(_soc_td3_alpm2_bnk_fmt_map[unit]);
    141         _soc_td3_alpm2_bnk_fmt_map[unit] = NULL;
    142     }
    143 
    144     if (NULL == _soc_td3_alpm2_bnk_fmt_map[unit]) {
    145         if ((_soc_td3_alpm2_bnk_fmt_map[unit] = sal_alloc(sizeof(int8) * \
    146             soc_mem_index_count(unit, L3_DEFIP_ALPM_RAWm), "alpm_bnt_map")) \
    147             == NULL) {
    148             return SOC_E_MEMORY;
    149         }
    150     }
    151 
    152     sal_memset(_soc_td3_alpm2_bnk_fmt_map[unit], 0,
    153                sizeof(int8) * soc_mem_index_count(unit, L3_DEFIP_ALPM_RAWm));
    154     return SOC_E_NONE;
    155 }
    156 
    157 int
    158 soc_td3_post_mmu_init_update(int unit)
    159 {
    160     int port;
    161     soc_info_t *si = &SOC_INFO(unit);
    162 
    163     PBMP_ALL_ITER(unit, port) {
    164         /* Set init speed to max speed by default */
    165         si->port_init_speed[port] = si->port_speed_max[port];
    166         if (_soc_td3_port_speed_cap[unit][port]) {
    167             /* If cap speed is available then adjust max speed for further use */
    168             si->port_speed_max[port] = _soc_td3_port_speed_cap[unit][port];
    169         }
    170     }
    171     return SOC_E_NONE;
    172 }
    173 
    174 /*
    175  * Function:
    176  *      soc_trident3_iuat_sizing
    177  * Purpose:
    178  *      Given number of entries for IUAT memory, determine number of 8k and 16k
    179  *      IUAT banks (already allocated + shared banks for requesting module)
    180  * Parameters:
    181  *      unit (IN)         - switch unit
    182  *      iuat entries (IN) - number of memory entries
    183  *      iuat_16k (IN/OUT) - total number of allocated 16k banks
    184  *      iuat_8k (IN/OUT)  - total number of allocated 8k banks
    185  * Returns:
    186  *      SOC_E_*
    187  */
    188 int
    189 soc_trident3_iuat_sizing(int unit, int iuat_entries, int *iuat_16k, int *iuat_8k)
    190 {
    191     if (iuat_entries == 0) {
    192         return SOC_E_NONE;
    193     } else if (iuat_entries <= (8 *1024)) {
    194         /* Minimum hash table size should be > 8k */
    195         return SOC_E_PARAM;
    196     }
    197 
    198     /* Recurse for iuat_entries > 32k */
    199     while (iuat_entries > (32 * 1024)) {
    200         int residual_entries = 32 * 1024;
    201         SOC_IF_ERROR_RETURN
    202             (soc_trident3_iuat_sizing(unit, residual_entries, iuat_16k, iuat_8k));
    203         iuat_entries -= residual_entries;
    204     }
    205 
    206     /* Allocation Policy - Minimum Number of banks to be allocated is 2
    207      * Preferable if banks allocated are of the same size
    208      */
    209 
    210     /* Depending on number of iuat entries, there are several allocation schemes
    211      * possible. They are listed in order of priority. If none of them are
    212      * possible, error is returned.
    213      */
    214 
    215     /* This case works only when iuat_entries > 32k and recursion has happened */
    216     if(iuat_entries <= 8 * 1024) {
    217         if ((*iuat_8k + 1) <= SOC_IUAT_8K_BANKS) {
    218             *iuat_8k += 1;
    219         } else {
    220             return SOC_E_PARAM;
    221         }
    222     } else if (iuat_entries <= 16 * 1024) {
    223        /* For iuat entries in range 1 to (16 * 1024)
    224         * 1. Allocate two 8k banks
    225         */
    226         if ((*iuat_8k + 2) <= SOC_IUAT_8K_BANKS) {
    227             *iuat_8k += 2;
    228         } else {
    229             return SOC_E_PARAM;
    230         }
    231     } else if (iuat_entries <= 24 * 1024) {
    232         /* For iuat entries in range (16 * 1024) + 1 to 24 * 1024
    233          * 1. Allocate two 16k banks
    234          * 2. Allocate one 16k bank and one 8k bank
    235          * 3. Allocate three 8k banks
    236          */
    237         if ((*iuat_16k + 2) <= SOC_IUAT_16K_BANKS){
    238             *iuat_16k += 2;
    239         } else if (((*iuat_16k + 1) <= SOC_IUAT_16K_BANKS) &&
    240                     ((*iuat_8k + 1) <= SOC_IUAT_8K_BANKS)) {
    241             *iuat_8k += 1;
    242             *iuat_16k += 1;
    243         } else if ((*iuat_8k + 3) <= SOC_IUAT_8K_BANKS) {
    244             *iuat_8k += 3;
    245         } else {
    246             return SOC_E_PARAM;
    247         }
    248     } else { /* remaining case: (iuat_entries <= 32 * 1024) */
    249         /* For iuat entries in range (24 * 1024) + 1 to 32 * 1024,
    250          * 1. Allocate two 16k banks
    251          * 2. Allocate four 8k banks
    252          * 3. Allocate two 8k banks and one 16k bank.
    253          */
    254         if ((*iuat_16k + 2) <= SOC_IUAT_16K_BANKS) {
    255             *iuat_16k += 2;
    256         } else if ((*iuat_8k + 4) <= SOC_IUAT_8K_BANKS) {
    257             *iuat_8k += 4;
    258         } else if(((*iuat_8k + 2) <= SOC_IUAT_8K_BANKS) &&
    259                     (*iuat_16k + 1) <= SOC_IUAT_16K_BANKS) {
    260             *iuat_8k += 2;
    261             *iuat_16k += 1;
    262         } else {
    263             return SOC_E_PARAM;
    264         }
    265     }
    266     return SOC_E_NONE;
    267 }
    268 
    269 /*
    270  * Function:
    271  *      soc_trident3_mem_config
    272  * Purpose:
    273  *      Configure depth of UFT/UAT memories
    274  * Parameters:
    275  *      unit (IN)    - switch unit
    276  * Returns:
    277  *      SOC_E_*
    278  */
    279 int
    280 soc_trident3_mem_config(int unit)
    281 {
    282     soc_persist_t *sop;
    283     int l2_entries, fixed_l2_entries, shared_l2_banks;
    284     int num_ipv6_128b_entries = 0;
    285     int config_v6_entries = 0;
    286     int defip_config = 0;
    287 #define _SOC_TD3_DEFIP_MAX_TCAMS    8
    288 #define _SOC_TD3_DEFIP_TCAM_DEPTH   2048
    289     int l3_entries, fixed_l3_entries, shared_l3_banks;
    290     int fpem_entries, shared_fpem_banks;
    291     int mpls_entries, vlan_xlate_1_entries, vlan_xlate_2_entries;
    292     int alpm_enable = 0;
    293     int mpls_16k_banks, mpls_8k_banks;
    294     int vlan_xlate_1_16k_banks, vlan_xlate_1_8k_banks;
    295     int vlan_xlate_2_16k_banks, vlan_xlate_2_8k_banks;
    296     int uat_16k_banks, uat_8k_banks;
    297     int egr_vlan_xlate_1_entries, egr_vlan_xlate_2_entries;
    298     int egr_vlan_xlate_1_banks, egr_vlan_xlate_2_banks;
    299     int num_lag_rh_flowset_entries;
    300 
    301     sop = SOC_PERSIST(unit);
    302 
    303     /*  UFT BANK SIZING
    304      *
    305      * bank 0-1 are dedicated L2 banks (16k entries per bank)
    306      * bank 10-11 are dedicated L3 banks (8k entries per bank)
    307      * bank 2-9 are shared banks (32k L2/L3 or 16k FPEM entries
    308      *                              or 48k ALPM entries per bank)
    309      */
    310 
    311     l2_entries = soc_property_get(unit, spn_L2_MEM_ENTRIES, 32 * 1024);
    312     fixed_l2_entries = 32 * 1024;  /* 32k dedicated L2 entries, (16k * 2 banks) */
    313     if (l2_entries < fixed_l2_entries) {
    314         l2_entries = fixed_l2_entries;
    315         shared_l2_banks = 0;
    316     } else {
    317         l2_entries -= fixed_l2_entries;
    318         shared_l2_banks = (l2_entries + (32 * 1024 - 1)) / (32 * 1024);
    319         l2_entries = fixed_l2_entries + shared_l2_banks * 32 * 1024;
    320     }
    321 
    322     l3_entries = soc_property_get(unit, spn_L3_MEM_ENTRIES, 16 * 1024);
    323     fixed_l3_entries = 16 * 1024;  /* 16k dedicated L3 entries, (8k * 2 banks) */
    324     if (l3_entries < fixed_l3_entries) {
    325         l3_entries = fixed_l3_entries;
    326         shared_l3_banks = 0;
    327     } else {
    328         l3_entries -= fixed_l3_entries;
    329         shared_l3_banks = (l3_entries + (32 * 1024 - 1)) / (32 * 1024);
    330         l3_entries = fixed_l3_entries + shared_l3_banks * 32 * 1024;
    331     }
    332 
    333     fpem_entries = soc_property_get(unit, spn_FPEM_MEM_ENTRIES, 0);
    334     shared_fpem_banks = (fpem_entries + (16 * 1024 - 1)) / (16 * 1024);
    335     /* Allocate atleast 2 banks to FP for dual hash benefits */
    336     if(shared_fpem_banks == 1) {
    337         if ((shared_l2_banks + shared_l3_banks) > 6) {
    338             LOG_ERROR(BSL_LS_SOC_COMMON,
    339                         (BSL_META_U(unit,
    340                                     "Config Error - Atleast two shared UFT"
    341                                     "banks should be allocated to FPEM. \n")));
    342             return SOC_E_PARAM;
    343         }
    344         shared_fpem_banks = 2;
    345     }
    346     fpem_entries = shared_fpem_banks * 16 * 1024;
    347 
    348     if (shared_l2_banks + shared_l3_banks + shared_fpem_banks > 8) {
    349         return SOC_E_PARAM;
    350     }
    351 
    352     if (soc_feature(unit, soc_feature_alpm)) {
    353         alpm_enable = soc_property_get(unit, spn_L3_ALPM_ENABLE, 0);
    354     }
    355 
    356     /* ALPM needs either 4 banks or 8 banks depending on ALPM bank mode.
    357      * If more than 4 banks are already allocated to non ALPM tables (L2, L3,
    358      * FPEM), then ALPM needs cannot be satisfied */
    359     if ((alpm_enable) &&
    360         (shared_l2_banks + shared_l3_banks + shared_fpem_banks > 4)) {
    361         return SOC_E_PARAM;
    362     }
    363 
    364     _soc_alpm_mode[unit] = alpm_enable;
    365 
    366     /* IUAT BANK SIZING
    367      *
    368      * Banks 0-3 are shared banks of size 8k per bank
    369      * Banks 4-7 are shared banks of size 16k per bank
    370      */
    371 
    372     uat_16k_banks = 0; uat_8k_banks = 0;
    373     mpls_entries = soc_property_get(unit, spn_MPLS_MEM_ENTRIES, 32768);
    374     SOC_IF_ERROR_RETURN(soc_trident3_iuat_sizing(unit, mpls_entries,
    375                                                  &uat_16k_banks, &uat_8k_banks));
    376     mpls_16k_banks = uat_16k_banks;
    377     mpls_8k_banks = uat_8k_banks;
    378     mpls_entries = mpls_16k_banks * 16 * 1024 + mpls_8k_banks * 8 * 1024;
    379 
    380     vlan_xlate_1_entries = soc_property_get(unit, spn_VLAN_XLATE_1_MEM_ENTRIES,
    381                                             32768);
    382     SOC_IF_ERROR_RETURN(soc_trident3_iuat_sizing(unit, vlan_xlate_1_entries,
    383                                                  &uat_16k_banks, &uat_8k_banks));
    384     vlan_xlate_1_16k_banks = uat_16k_banks - mpls_16k_banks;
    385     vlan_xlate_1_8k_banks = uat_8k_banks - mpls_8k_banks;
    386     vlan_xlate_1_entries = vlan_xlate_1_16k_banks * 16 * 1024 +
    387                             vlan_xlate_1_8k_banks * 8 * 1024;
    388 
    389     vlan_xlate_2_entries = soc_property_get(unit, spn_VLAN_XLATE_2_MEM_ENTRIES,
    390                                             32768);
    391     SOC_IF_ERROR_RETURN(soc_trident3_iuat_sizing(unit, vlan_xlate_2_entries,
    392                                                  &uat_16k_banks, &uat_8k_banks));
    393     vlan_xlate_2_16k_banks = uat_16k_banks - mpls_16k_banks -
    394                                 vlan_xlate_1_16k_banks;
    395     vlan_xlate_2_8k_banks = uat_8k_banks - mpls_8k_banks - vlan_xlate_1_8k_banks;
    396     vlan_xlate_2_entries = vlan_xlate_2_16k_banks * 16 * 1024 +
    397                             vlan_xlate_2_8k_banks * 8 * 1024;
    398 
    399     /* EUAT BANK SIZING
    400      *
    401      * Banks 0-3 are shared banks of size 8k per bank
    402      */
    403 
    404     egr_vlan_xlate_1_entries = soc_property_get(unit,
    405                                     spn_EGR_VLAN_XLATE_1_MEM_ENTRIES, 16384);
    406     egr_vlan_xlate_1_banks = (egr_vlan_xlate_1_entries + (8 * 1024 - 1)) /
    407                                                                     ( 8 * 1024);
    408     egr_vlan_xlate_1_entries = egr_vlan_xlate_1_banks * 8 * 1024;
    409 
    410     egr_vlan_xlate_2_entries = soc_property_get(unit,
    411                                     spn_EGR_VLAN_XLATE_2_MEM_ENTRIES, 16384);
    412     egr_vlan_xlate_2_banks = (egr_vlan_xlate_2_entries + (8 * 1024 - 1)) /
    413                                                                     ( 8 * 1024);
    414     egr_vlan_xlate_2_entries = egr_vlan_xlate_2_banks * 8 * 1024;
    415 
    416     if (egr_vlan_xlate_1_banks + egr_vlan_xlate_2_banks > 4) {
    417         return SOC_E_PARAM;
    418     }
    419 
    420     /* LP memory sizing
    421      * Memory Bank with 1W,2W,4W support - 3.5k entries
    422      * Memory Bank with 1W,2W support    - 3k entries
    423      * Memory Bank with 1W support       - 2k entries
    424      */
    425 
    426     /* Adjust L2 table size */
    427     sop->memState[L2Xm].index_max = l2_entries - 1;
    428     sop->memState[L2_ENTRY_SINGLEm].index_max = l2_entries - 1;
    429     sop->memState[L2_ENTRY_ONLY_SINGLEm].index_max = l2_entries - 1;
    430     sop->memState[L2_ENTRY_ECCm].index_max = l2_entries - 1;
    431     sop->memState[L2_HITDA_ONLYm].index_max = l2_entries / 4 - 1;
    432     sop->memState[L2_HITSA_ONLYm].index_max = l2_entries / 4 - 1;
    433     /* 4k per dedicated L2 bank, 14k per shared L2 bank */
    434     sop->memState[L2_ENTRY_LPm].index_max = (2 * 4 * 1024) +
    435                                 (shared_l2_banks * 14 * 1024) - 1;
    436 
    437     /* Adjust L3 table size */
    438     sop->memState[L3_ENTRY_SINGLEm].index_max = l3_entries - 1;
    439     sop->memState[L3_ENTRY_ONLY_SINGLEm].index_max = l3_entries - 1;
    440     sop->memState[L3_ENTRY_ECCm].index_max = l3_entries - 1;
    441     sop->memState[L3_ENTRY_DOUBLEm].index_max = l3_entries / 2 - 1;
    442     sop->memState[L3_ENTRY_ONLY_DOUBLEm].index_max = l3_entries / 2 - 1;
    443     sop->memState[L3_ENTRY_QUADm].index_max = l3_entries / 4 - 1;
    444     sop->memState[L3_ENTRY_ONLY_QUADm].index_max = l3_entries / 4 - 1;
    445     sop->memState[L3_ENTRY_HIT_ONLYm].index_max = l3_entries / 4 - 1;
    446     /* 3.5k per dedicated L3 bank, 14k per shared L3 bank */
    447     /* 2 * 3.5 * 1024 is replaced by 7 * 1024 to avoid automatic type
    448      * conversion, which could force shared_l3_banks to double type */
    449     sop->memState[L3_ENTRY_LPm].index_max = (7 * 1024) +
    450                                    (shared_l3_banks * 14 * 1024) - 1;
    451 
    452     /* Adjust FP exact match table size */
    453     sop->memState[EXACT_MATCH_2m].index_max = fpem_entries - 1;
    454     sop->memState[EXACT_MATCH_2_PIPE0m].index_max = fpem_entries - 1;
    455     sop->memState[EXACT_MATCH_2_PIPE1m].index_max = fpem_entries - 1;
    456     sop->memState[EXACT_MATCH_2_ENTRY_ONLYm].index_max = fpem_entries - 1;
    457     sop->memState[EXACT_MATCH_2_ENTRY_ONLY_PIPE0m].index_max = fpem_entries - 1;
    458     sop->memState[EXACT_MATCH_2_ENTRY_ONLY_PIPE1m].index_max = fpem_entries - 1;
    459     sop->memState[EXACT_MATCH_4m].index_max = fpem_entries / 2 - 1;
    460     sop->memState[EXACT_MATCH_4_PIPE0m].index_max = fpem_entries / 2 - 1;
    461     sop->memState[EXACT_MATCH_4_PIPE1m].index_max = fpem_entries / 2 - 1;
    462     sop->memState[EXACT_MATCH_4_ENTRY_ONLYm].index_max = fpem_entries / 2 - 1;
    463     sop->memState[EXACT_MATCH_4_ENTRY_ONLY_PIPE0m].index_max = fpem_entries / 2 - 1;
    464     sop->memState[EXACT_MATCH_4_ENTRY_ONLY_PIPE1m].index_max = fpem_entries / 2 - 1;
    465     sop->memState[EXACT_MATCH_HIT_ONLYm].index_max = fpem_entries / 2 - 1;
    466     sop->memState[EXACT_MATCH_ECCm].index_max = fpem_entries * 2 - 1;
    467     sop->memState[EXACT_MATCH_ECC_PIPE0m].index_max = fpem_entries * 2 - 1;
    468     sop->memState[EXACT_MATCH_ECC_PIPE1m].index_max = fpem_entries * 2 - 1;
    469     /* 14k per shared FPEM bank */
    470     sop->memState[EXACT_MATCH_LPm].index_max =
    471                               shared_fpem_banks * 14 * 1024 - 1;
    472     sop->memState[EXACT_MATCH_LP_PIPE0m].index_max =
    473                               shared_fpem_banks * 14 * 1024 -1;
    474     sop->memState[EXACT_MATCH_LP_PIPE1m].index_max =
    475                               shared_fpem_banks * 14 * 1024 -1;
    476 
    477     /* Adjust MPLS table size */
    478 
    479     sop->memState[MPLS_ENTRY_SINGLEm].index_max = mpls_entries - 1;
    480     sop->memState[MPLS_ENTRYm].index_max = mpls_entries / 2 - 1;
    481     /* 3k per 8k bank and 6k per 8k bank */
    482     sop->memState[MPLS_ENTRY_LPm].index_max = (mpls_8k_banks * 3 * 1024 +
    483                                               mpls_16k_banks * 2 * 3 * 1024) - 1;
    484     sop->memState[MPLS_ENTRY_ECCm].index_max = mpls_entries - 1;
    485 
    486     /* Adjust VLAN_XLATE_1 table size */
    487 
    488     sop->memState[VLAN_XLATE_1_SINGLEm].index_max = vlan_xlate_1_entries - 1;
    489     sop->memState[VLAN_XLATE_1_DOUBLEm].index_max = vlan_xlate_1_entries / 2 - 1;
    490     /* 3k per 8k bank and 6k per 8k bank */
    491     sop->memState[VLAN_XLATE_1_LPm].index_max = ((vlan_xlate_1_16k_banks * 2 * 3 * 1024)
    492                                                 + (vlan_xlate_1_8k_banks * 3 * 1024)) - 1;
    493     sop->memState[VLAN_XLATE_1_ECCm].index_max = vlan_xlate_1_entries - 1;
    494 
    495     /* Adjust VLAN_XLATE_2 table size */
    496 
    497     sop->memState[VLAN_XLATE_2_SINGLEm].index_max = vlan_xlate_2_entries - 1;
    498     sop->memState[VLAN_XLATE_2_DOUBLEm].index_max = vlan_xlate_2_entries / 2 - 1;
    499     /* 3k per 8k bank and 6k per 8k bank */
    500     sop->memState[VLAN_XLATE_2_LPm].index_max = (vlan_xlate_2_16k_banks * 2 * 3 * 1024)
    501                                                 + (vlan_xlate_2_8k_banks * 3 * 1024) - 1;
    502     sop->memState[VLAN_XLATE_2_ECCm].index_max = vlan_xlate_2_entries - 1;
    503 
    504     /* Adjust EGR_VLAN_XLATE_1 table size */
    505 
    506     sop->memState[EGR_VLAN_XLATE_1_SINGLEm].index_max = egr_vlan_xlate_1_entries - 1;
    507     sop->memState[EGR_VLAN_XLATE_1_DOUBLEm].index_max = egr_vlan_xlate_1_entries / 2 - 1;
    508     /* 3k per bank */
    509     sop->memState[EGR_VLAN_XLATE_1_LPm].index_max = egr_vlan_xlate_1_banks * 3 * 1024 - 1;
    510     sop->memState[EGR_VLAN_XLATE_1_ECCm].index_max = egr_vlan_xlate_1_entries - 1;
    511 
    512     /* Adjust EGR_VLAN_XLATE_2 table size */
    513 
    514     sop->memState[EGR_VLAN_XLATE_2_SINGLEm].index_max = egr_vlan_xlate_2_entries - 1;
    515     sop->memState[EGR_VLAN_XLATE_2_DOUBLEm].index_max = egr_vlan_xlate_2_entries / 2 - 1;
    516     /* 3k per bank */
    517     sop->memState[EGR_VLAN_XLATE_2_LPm].index_max = egr_vlan_xlate_2_banks * 3 * 1024 - 1;
    518     sop->memState[EGR_VLAN_XLATE_2_ECCm].index_max = egr_vlan_xlate_2_entries - 1;
    519 
    520 
    521     SOC_CONTROL(unit)->l3_defip_max_tcams = _SOC_TD3_DEFIP_MAX_TCAMS;
    522     SOC_CONTROL(unit)->l3_defip_tcam_size = _SOC_TD3_DEFIP_TCAM_DEPTH;
    523 
    524     if (soc_property_get(unit, "l3_defip_sizing", TRUE)) {
    525         if (!alpm_enable) {
    526             defip_config = soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1);
    527 
    528             num_ipv6_128b_entries = soc_property_get(unit,
    529                                         spn_NUM_IPV6_LPM_128B_ENTRIES,
    530                                         (defip_config ? 4096 : 0));
    531             num_ipv6_128b_entries = num_ipv6_128b_entries +
    532                                     (num_ipv6_128b_entries % 2);
    533 
    534             config_v6_entries = num_ipv6_128b_entries;
    535             if (soc_property_get(unit, spn_LPM_SCALING_ENABLE, 0)) {
    536                 num_ipv6_128b_entries = 0;
    537                 if (!soc_property_get(unit, spn_LPM_IPV6_128B_RESERVED, 1)) {
    538                     config_v6_entries = ((config_v6_entries /
    539                                         SOC_CONTROL(unit)->l3_defip_tcam_size) +
    540                                         ((config_v6_entries %
    541                                          SOC_CONTROL(unit)->l3_defip_tcam_size)
    542                                         ? 1 : 0)) * SOC_CONTROL(unit)->l3_defip_tcam_size;
    543                 }
    544             }
    545             sop->memState[L3_DEFIP_PAIR_128m].index_max =
    546                                               num_ipv6_128b_entries - 1;
    547             sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max =
    548                                               num_ipv6_128b_entries - 1;
    549             sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max =
    550                                               num_ipv6_128b_entries - 1;
    551             sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max =
    552                                               num_ipv6_128b_entries - 1;
    553             sop->memState[L3_DEFIPm].index_max =
    554                                      (SOC_CONTROL(unit)->l3_defip_max_tcams *
    555                                      SOC_CONTROL(unit)->l3_defip_tcam_size) -
    556                                      (num_ipv6_128b_entries * 2) - 1;
    557 
    558             sop->memState[L3_DEFIP_ONLYm].index_max =
    559                                           sop->memState[L3_DEFIPm].index_max;
    560             sop->memState[L3_DEFIP_DATA_ONLYm].index_max =
    561                                           sop->memState[L3_DEFIPm].index_max;
    562             sop->memState[L3_DEFIP_HIT_ONLYm].index_max =
    563                                           sop->memState[L3_DEFIPm].index_max;
    564             SOC_CONTROL(unit)->l3_defip_index_remap = num_ipv6_128b_entries;
    565         } else {
    566             if (soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1)) {
    567                 /* slightly different processing for v6-128 */
    568                 num_ipv6_128b_entries = soc_property_get(unit,
    569                                             spn_NUM_IPV6_LPM_128B_ENTRIES,
    570                                             4096);
    571                 num_ipv6_128b_entries = num_ipv6_128b_entries +
    572                                         (num_ipv6_128b_entries % 2);
    573                 config_v6_entries = num_ipv6_128b_entries;
    574                 sop->memState[L3_DEFIP_PAIR_128m].index_max =
    575                                         num_ipv6_128b_entries - 1;
    576                 sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max =
    577                                         num_ipv6_128b_entries - 1;
    578                 sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max =
    579                                         num_ipv6_128b_entries - 1;
    580                 sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max =
    581                                         num_ipv6_128b_entries - 1;
    582                 sop->memState[L3_DEFIPm].index_max =
    583                                   (SOC_CONTROL(unit)->l3_defip_max_tcams *
    584                                   SOC_CONTROL(unit)->l3_defip_tcam_size) -
    585                                   (num_ipv6_128b_entries * 2) - 1;
    586 
    587                 sop->memState[L3_DEFIP_ONLYm].index_max =
    588                                         sop->memState[L3_DEFIPm].index_max;
    589                 sop->memState[L3_DEFIP_DATA_ONLYm].index_max =
    590                                         sop->memState[L3_DEFIPm].index_max;
    591                 sop->memState[L3_DEFIP_HIT_ONLYm].index_max =
    592                                         sop->memState[L3_DEFIPm].index_max;
    593 
    594                 SOC_CONTROL(unit)->l3_defip_index_remap =
    595                                         (num_ipv6_128b_entries / 2) * 2;
    596             } else {
    597                 sop->memState[L3_DEFIP_PAIR_128m].index_max = -1;
    598                 sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max = -1;
    599                 sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max = -1;
    600                 sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max = -1;
    601             }
    602         }
    603         soc_l3_defip_indexes_init(unit, config_v6_entries);
    604     }
    605 
    606     /* Adjust ALPM table size */
    607     if (alpm_enable) {
    608         /* The check below is sufficient because if ALPM mode is enabled
    609          * and number of shared banks used is > 4 we return SOC_E_PARAM
    610          * in code at the top of this function.
    611          */
    612         if (shared_l2_banks + shared_l3_banks + shared_fpem_banks > 0) {
    613             sop->memState[L3_DEFIP_ALPM_RAWm].index_max =
    614                 sop->memState[L3_DEFIP_ALPM_RAWm].index_max/2;
    615             sop->memState[L3_DEFIP_ALPM_IPV4m].index_max =
    616                 sop->memState[L3_DEFIP_ALPM_IPV4m].index_max/2;
    617             sop->memState[L3_DEFIP_ALPM_IPV4_1m].index_max =
    618                 sop->memState[L3_DEFIP_ALPM_IPV4_1m].index_max/2;
    619             sop->memState[L3_DEFIP_ALPM_IPV6_64m].index_max =
    620                 sop->memState[L3_DEFIP_ALPM_IPV6_64m].index_max/2;
    621             sop->memState[L3_DEFIP_ALPM_IPV6_64_1m].index_max =
    622                 sop->memState[L3_DEFIP_ALPM_IPV6_64_1m].index_max/2;
    623             sop->memState[L3_DEFIP_ALPM_IPV6_128m].index_max =
    624                 sop->memState[L3_DEFIP_ALPM_IPV6_128m].index_max/2;
    625             sop->memState[L3_DEFIP_ALPM_HIT_ONLYm].index_max =
    626                 sop->memState[L3_DEFIP_ALPM_HIT_ONLYm].index_max/2;
    627             sop->memState[L3_DEFIP_ALPM_ECCm].index_max =
    628                 sop->memState[L3_DEFIP_ALPM_ECCm].index_max/2;
    629         }
    630     } else {
    631         sop->memState[L3_DEFIP_ALPM_RAWm].index_max = -1;
    632         sop->memState[L3_DEFIP_ALPM_IPV4m].index_max = -1;
    633         sop->memState[L3_DEFIP_ALPM_IPV4_1m].index_max = -1;
    634         sop->memState[L3_DEFIP_ALPM_IPV6_64m].index_max = -1;
    635         sop->memState[L3_DEFIP_ALPM_IPV6_64_1m].index_max = -1;
    636         sop->memState[L3_DEFIP_ALPM_IPV6_128m].index_max = -1;
    637         sop->memState[L3_DEFIP_ALPM_HIT_ONLYm].index_max = -1;
    638         sop->memState[L3_DEFIP_ALPM_ECCm].index_max = -1;
    639     }
    640 
    641     /* Adjust MY_STATION_TCAM table in Emulator */
    642     if (SAL_BOOT_QUICKTURN) {
    643         sop->memState[MY_STATION_TCAMm].index_max = 31;
    644         sop->memState[MY_STATION_TCAM_2m].index_max =
    645             sop->memState[MY_STATION_TCAMm].index_max;
    646         sop->memState[MY_STATION_TCAM_2_DATA_ONLYm].index_max =
    647             sop->memState[MY_STATION_TCAMm].index_max;
    648         sop->memState[MY_STATION_TCAM_2_ENTRY_ONLYm].index_max =
    649             sop->memState[MY_STATION_TCAMm].index_max;
    650         sop->memState[MY_STATION_TCAM_DATA_ONLYm].index_max =
    651             sop->memState[MY_STATION_TCAMm].index_max;
    652         sop->memState[MY_STATION_TCAM_ENTRY_ONLYm].index_max =
    653             sop->memState[MY_STATION_TCAMm].index_max;
    654     }
    655 
    656     if (_soc_td3_alpm_bkt_view_map[unit] != NULL) {
    657         sal_free(_soc_td3_alpm_bkt_view_map[unit]);
    658         _soc_td3_alpm_bkt_view_map[unit] = NULL;
    659     }
    660 
    661     if (NULL == _soc_td3_alpm_bkt_view_map[unit]) {
    662         if ((_soc_td3_alpm_bkt_view_map[unit] =
    663             sal_alloc(sizeof(soc_mem_t) * SOC_TD3_ALPM_MAX_BKTS(unit),
    664                       "alpm_bkt_map")) == NULL) {
    665             return SOC_E_MEMORY;
    666         }
    667     }
    668 
    669     sal_memset(_soc_td3_alpm_bkt_view_map[unit], INVALIDm,
    670                sizeof(soc_mem_t) * SOC_TD3_ALPM_MAX_BKTS(unit));
    671 
    672     if (soc_trident3_alpm_mode_get(unit)) {
    673         SOC_IF_ERROR_RETURN(soc_trident3_init_alpm2_memory(unit));
    674     }
    675 
    676    /* Enhanced hashing  LAG/TRUNK config
    677     * LAG/TRUNK share the same flow set table used in RH
    678     * 64k is shared between LAG and HGT for
    679     * - 32k each - default
    680     * - 64K dedicated to HGT RH
    681     * - 64K dedicated to LAG RH
    682     */
    683     num_lag_rh_flowset_entries = soc_property_get(unit,
    684                 spn_TRUNK_RESILIENT_HASH_TABLE_SIZE, 32768);
    685 
    686     switch (num_lag_rh_flowset_entries) {
    687         case 0:
    688             sop->memState[RH_LAG_FLOWSETm].index_max = -1;
    689             sop->memState[RH_LAG_FLOWSET_PIPE0m].index_max = -1;
    690             sop->memState[RH_LAG_FLOWSET_PIPE1m].index_max = -1;
    691             break;
    692         case 65536:
    693             sop->memState[RH_HGT_FLOWSETm].index_max = -1;
    694             sop->memState[RH_HGT_FLOWSET_PIPE0m].index_max = -1;
    695             sop->memState[RH_HGT_FLOWSET_PIPE1m].index_max = -1;
    696             break;
    697         case 32768:
    698             sop->memState[RH_HGT_FLOWSETm].index_max = 32767;
    699             sop->memState[RH_HGT_FLOWSET_PIPE0m].index_max = 32767;
    700             sop->memState[RH_HGT_FLOWSET_PIPE1m].index_max = 32767;
    701             sop->memState[RH_LAG_FLOWSETm].index_max = 32767;
    702             sop->memState[RH_LAG_FLOWSET_PIPE0m].index_max = 32767;
    703             sop->memState[RH_LAG_FLOWSET_PIPE1m].index_max = 32767;
    704             break;
    705         default:
    706             return SOC_E_CONFIG;
    707     }
    708     return SOC_E_NONE;
    709 }
    710 
    711 void
    712 _soc_trident3_alpm2_bnk_fmt_set(int unit, int index, int8 fmt)
    713 {
    714     _soc_td3_alpm2_bnk_fmt_map[unit][index] = fmt;
    715 }
    716 
    717 int8
    718 _soc_trident3_alpm2_bnk_fmt_get(int unit, int index)
    719 {
    720     return _soc_td3_alpm2_bnk_fmt_map[unit][index];
    721 }
    722 
    723 void
    724 _soc_trident3_alpm_bkt_view_set(int unit, int index, soc_mem_t view)
    725 {
    726     int bkt = soc_trident3_get_alpm_banks(unit);
    727     if (bkt == 8) {
    728         bkt = 3;
    729     } else if (bkt == 4) {
    730         bkt = 2;
    731     } else if (bkt == 2) {
    732         bkt = 1;
    733     }
    734     bkt = (index >> bkt) & SOC_TD3_ALPM_BKT_MASK(unit);
    735 
    736     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "Unit:%d ALPM bkt set index:%d bkt:%d view:%s\n"),
    737                  unit, index, bkt, SOC_MEM_NAME(unit, view)));
    738     _soc_td3_alpm_bkt_view_map[unit][bkt] = view;
    739 }
    740 
    741 soc_mem_t
    742 _soc_trident3_alpm_bkt_view_get(int unit, int index)
    743 {
    744     soc_mem_t view;
    745     int bkt = soc_trident3_get_alpm_banks(unit);
    746     if (bkt == 8) {
    747         bkt = 3;
    748     } else if (bkt == 4) {
    749         bkt = 2;
    750     } else if (bkt == 2) {
    751         bkt = 1;
    752     }
    753     bkt = (index >> bkt) & SOC_TD3_ALPM_BKT_MASK(unit);
    754 
    755     view = _soc_td3_alpm_bkt_view_map[unit][bkt];
    756     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "Unit:%d ALPM bkt get index:%d bkt:%d view:%s\n"),
    757                  unit, index, bkt, SOC_MEM_NAME(unit, view)));
    758     return view;
    759 }
    760 
    761 int
    762 soc_trident3_mem_cpu_write_control(int unit, soc_mem_t mem, int copyno,
    763                                    int enable, int *orig_enable)
    764 {
    765     soc_reg_t reg;
    766     soc_field_t field;
    767     uint32 rval, fval;
    768     int blk, port, block_info_index;
    769     uint32 orig_fval, enable_fval, disable_fval;
    770 
    771     enable_fval = 1;
    772     disable_fval = 0;
    773 
    774     switch (mem) {
    775     case CLPORT_WC_UCMEM_DATAm:
    776         reg = CLPORT_WC_UCMEM_CTRLr;
    777         field = ACCESS_MODEf;
    778         SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
    779             port = SOC_BLOCK_PORT(unit, blk);
    780             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    781             /* It will use the setting from the last block */
    782             *orig_enable = soc_reg_field_get(unit, reg, rval, field);
    783             soc_reg_field_set(unit, reg, &rval, field, enable ? 1 : 0);
    784             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
    785         }
    786         return SOC_E_NONE;
    787     default:
    788         block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
    789         if ((SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_XPE) ||
    790             (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_SED) ||
    791             (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_SC)){
    792             reg = MMU_GCFG_MISCCONFIGr;
    793             field = REFRESH_ENf;
    794             enable_fval = 0;
    795             disable_fval = 1;
    796             SOC_IF_ERROR_RETURN
    797                 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    798             orig_fval = soc_reg_field_get(unit, reg, rval, field);
    799             fval = enable ? enable_fval : disable_fval;
    800             *orig_enable = orig_fval == enable_fval;
    801             if (fval != orig_fval) {
    802                 soc_reg_field_set(unit, reg, &rval, field, fval);
    803                 SOC_IF_ERROR_RETURN
    804                     (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    805             }
    806         }
    807         return _soc_trident2_mem_cpu_write_control(unit, mem, copyno,
    808                                                    enable, orig_enable);
    809     }
    810     return SOC_E_NONE;
    811 
    812 #if 0
    813     soc_reg_t reg;
    814     soc_field_t field;
    815     int blk, port;
    816     uint32 rval;
    817 
    818     switch (mem) {
    819     case CLPORT_WC_UCMEM_DATAm:
    820         reg = CLPORT_WC_UCMEM_CTRLr;
    821         field = ACCESS_MODEf;
    822         SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
    823             port = SOC_BLOCK_PORT(unit, blk);
    824             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    825             /* It will use the setting from the last block */
    826             *orig_enable = soc_reg_field_get(unit, reg, rval, field);
    827             soc_reg_field_set(unit, reg, &rval, field, enable ? 1 : 0);
    828             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
    829         }
    830         return SOC_E_NONE;
    831     default:
    832         return _soc_trident2_mem_cpu_write_control(unit, mem, copyno,
    833                                                    enable, orig_enable);
    834     }
    835 #endif
    836 }
    837 
    838 
    839 int
    840 soc_trident3_reg_cpu_write_control(int unit, int enable)
    841 {
    842     uint32 intfo_dis = 0;
    843 
    844     if (enable) {
    845         /* Disable HW updates */
    846         soc_reg_field_set(unit, INTFO_HW_UPDATE_DISr, &intfo_dis,
    847                           EG_SPf, 1);
    848         soc_reg_field_set(unit, INTFO_HW_UPDATE_DISr, &intfo_dis,
    849                           ING_SPf, 1);
    850         soc_reg_field_set(unit, INTFO_HW_UPDATE_DISr, &intfo_dis,
    851                           CONGST_STf, 1);
    852     }
    853     SOC_IF_ERROR_RETURN(WRITE_INTFO_HW_UPDATE_DISr(unit, intfo_dis));
    854 
    855     return SOC_E_NONE;
    856 }
    857 
    858 soc_mem_t
    859 _soc_trident3_pmem(int unit, int port, soc_mem_t mema, soc_mem_t memb)
    860 {
    861     return (SOC_INFO(unit).port_pipe[port]) ? memb : mema;
    862 }
    863 
    864 uint32 _soc_td3_mmu_port(int unit, int port)
    865 {
    866     soc_info_t *si = &SOC_INFO(unit);
    867     return si->port_p2m_mapping[si->port_l2p_mapping[port]];
    868 }
    869 
    870 /*
    871  * cpu port (mmu port 64): 48 queues (650-697)
    872  * loopback port (mmu port 65, 193): 10 queues (640-649)
    873  * mgmt port (mmu port 192): 10 UC, 10 MC queues
    874  */
    875 int
    876 soc_trident3_num_cosq_init_port(int unit, int port)
    877 {
    878     soc_info_t *si;
    879     int mmu_port;
    880 
    881     si = &SOC_INFO(unit);
    882 
    883     mmu_port = SOC_TD3_MMU_PORT(unit, port);
    884 
    885     if (IS_CPU_PORT(unit, port)) {
    886         si->port_num_cosq[port] = 48;
    887         si->port_cosq_base[port] = SOC_TD3_CPU_MCQ_BASE;
    888     } else if (IS_LB_PORT(unit, port)) {
    889         si->port_num_cosq[port] = 10;
    890         si->port_cosq_base[port] = SOC_TD3_LB_MCQ_BASE;
    891     } else if (IS_MGMT_PORT(unit, port)) {
    892         si->port_num_cosq[port] = 10;
    893         si->port_num_uc_cosq[port] = 10;
    894         if (si->port_l2p_mapping[port] == 128) {
    895             /* 2nd Mgmt port */
    896             si->port_cosq_base[port] = SOC_TD3_SECOND_MGMT_BASE;
    897             si->port_uc_cosq_base[port] = SOC_TD3_SECOND_MGMT_BASE;
    898         } else {
    899             si->port_cosq_base[port] = SOC_TD3_MGMT_MCQ_BASE;
    900             si->port_uc_cosq_base[port] = SOC_TD3_MGMT_UCQ_BASE;
    901         }
    902     } else {
    903         si->port_num_cosq[port] = 10;
    904         si->port_cosq_base[port] =
    905             (mmu_port % 64) * 10;
    906         si->port_num_uc_cosq[port] = 10;
    907         si->port_uc_cosq_base[port] =
    908             (mmu_port % 64) * 10;
    909         si->port_num_ext_cosq[port] = 0;
    910     }
    911 
    912     return SOC_E_NONE;
    913 }
    914 
    915 /*
    916  * cpu port (mmu port 64): 48 queues (650-697)
    917  * loopback port (mmu port 65, 193): 10 queues (640-649)
    918  * mgmt port (mmu port 192): 10 UC, 10 MC queues
    919  */
    920 int
    921 soc_trident3_num_cosq_init(int unit)
    922 {
    923     int port;
    924 
    925     PBMP_ALL_ITER(unit, port) {
    926         SOC_IF_ERROR_RETURN
    927             (soc_trident3_num_cosq_init_port(unit, port));
    928     }
    929 
    930     return SOC_E_NONE;
    931 }
    932 
    933 STATIC int
    934 soc_trident3_max_frequency_get(int unit,  uint16 dev_id, uint8 rev_id,
    935                                int skew_id, int *frequency)
    936 {
    937     switch (dev_id) {
    938     case BCM56870_DEVICE_ID:
    939     case BCM56873_DEVICE_ID:
    940         *frequency = CCLK_FREQ_1525MHZ;
    941         break;
    942     default:
    943         return SOC_E_INTERNAL;
    944     }
    945 
    946     return SOC_E_NONE;
    947 }
    948 
    949 void
    950 soc_trident3_tsc_map_get(int unit, uint32 *tsc_map)
    951 {
    952     *tsc_map = 0xffffffff;
    953 }
    954 
    955 void
    956 soc_trident3_pipe_map_get(int unit, uint32 *pipe_map)
    957 {
    958     soc_info_t *si;
    959     int port;
    960 
    961     si = &SOC_INFO(unit);
    962 
    963     *pipe_map = 0;
    964     PBMP_LB_ITER(unit, port) {
    965         *pipe_map |= 1 << si->port_pipe[port];
    966     }
    967 }
    968 
    969 /*
    970  * #1   single: 100  -   x  -   x  -   x  SOC_TD3_PORT_RATIO_SINGLE
    971  * #2   single:  40  -   x  -   x  -   x  SOC_TD3_PORT_RATIO_TRI_023_2_1_1
    972  * #3   dual:    50  -   x  -  50  -   x  SOC_TD3_PORT_RATIO_DUAL_1_1
    973  * #4   dual:    40  -   x  -  40  -   x  SOC_TD3_PORT_RATIO_DUAL_1_1
    974  * #5   dual:    20  -   x  -  20  -   x  SOC_TD3_PORT_RATIO_DUAL_1_1
    975  * #6   dual:    40  -   x  -  20  -   x  SOC_TD3_PORT_RATIO_DUAL_2_1
    976  * #7   dual:    20  -   x  -  40  -   x  SOC_TD3_PORT_RATIO_DUAL_1_2
    977  * #8   tri:     50  -   x  - 25/x - 25/x SOC_TD3_PORT_RATIO_TRI_023_2_1_1
    978  * #9   tri:     20  -   x  - 10/x - 10/x SOC_TD3_PORT_RATIO_TRI_023_2_1_1
    979  * #10  tri:     40  -   x  - 10/x - 10/x SOC_TD3_PORT_RATIO_TRI_023_4_1_1
    980  * #11  tri:    25/x - 25/x -  50  -   x  SOC_TD3_PORT_RATIO_TRI_012_1_1_2
    981  * #12  tri:    10/x - 10/x -  20  -   x  SOC_TD3_PORT_RATIO_TRI_012_1_1_2
    982  * #13  tri:    10/x - 10/x -  40  -   x  SOC_TD3_PORT_RATIO_TRI_012_1_1_4
    983  * #14  quad:   25/x - 25/x - 25/x - 25/x SOC_TD3_PORT_RATIO_QUAD
    984  * #15  quad:   10/x - 10/x - 10/x - 10/x SOC_TD3_PORT_RATIO_QUAD
    985  */
    986 void
    987 soc_trident3_port_ratio_get(int unit, int clport, int *mode)
    988 {
    989     soc_info_t *si;
    990     int port, phy_port_base, lane;
    991     int num_lanes[_TD3_PORTS_PER_PBLK];
    992     int speed_max[_TD3_PORTS_PER_PBLK];
    993 
    994     si = &SOC_INFO(unit);
    995     phy_port_base = 1 + clport * _TD3_PORTS_PER_PBLK;
    996     for (lane = 0; lane < _TD3_PORTS_PER_PBLK; lane += 2) {
    997         port = si->port_p2l_mapping[phy_port_base + lane];
    998         if (port == -1 || SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
    999             num_lanes[lane] = -1;
   1000             speed_max[lane] = -1;
   1001         } else {
   1002             num_lanes[lane] = si->port_num_lanes[port];
   1003             speed_max[lane] = si->port_speed_max[port];
   1004         }
   1005     }
   1006 
   1007     if (num_lanes[0] == 4) {
   1008         *mode = SOC_TD3_PORT_RATIO_SINGLE;
   1009     } else if (num_lanes[0] == 2 && num_lanes[2] == 2) {
   1010         if (speed_max[0] == speed_max[2]) {
   1011             *mode = SOC_TD3_PORT_RATIO_DUAL_1_1;
   1012         } else if (speed_max[0] > speed_max[2]) {
   1013             *mode = SOC_TD3_PORT_RATIO_DUAL_2_1;
   1014         } else {
   1015             *mode = SOC_TD3_PORT_RATIO_DUAL_1_2;
   1016         }
   1017     } else if (num_lanes[0] == 2) {
   1018         if (num_lanes[2] == -1) {
   1019             *mode = SOC_TD3_PORT_RATIO_DUAL_1_1;
   1020         } else {
   1021             *mode = (speed_max[0] == 20000 || speed_max[0] == 21000 ) ?
   1022                 SOC_TD3_PORT_RATIO_TRI_023_2_1_1 : SOC_TD3_PORT_RATIO_TRI_023_4_1_1;
   1023         }
   1024     } else if (num_lanes[2] == 2) {
   1025         if (num_lanes[0] == -1) {
   1026             *mode = SOC_TD3_PORT_RATIO_DUAL_1_1;
   1027         } else {
   1028             *mode = (speed_max[2] == 20000 || speed_max[2] == 21000 ) ?
   1029                 SOC_TD3_PORT_RATIO_TRI_012_1_1_2 : SOC_TD3_PORT_RATIO_TRI_012_1_1_4;
   1030         }
   1031     } else {
   1032         *mode = SOC_TD3_PORT_RATIO_QUAD;
   1033     }
   1034 }
   1035 
   1036 #if 0
   1037 STATIC void
   1038 _soc_trident3_pipe_bandwidth_get(int unit, int pipe,
   1039                                  int *max_pipe_core_bandwidth,
   1040                                  int *pipe_linerate_bandwidth,
   1041                                  int *pipe_oversub_bandwidth)
   1042 {
   1043     soc_info_t *si;
   1044     int port;
   1045     int bandwidth;
   1046 
   1047     si = &SOC_INFO(unit);
   1048 
   1049     *max_pipe_core_bandwidth = si->bandwidth / 4;
   1050 
   1051     *pipe_linerate_bandwidth = 0;
   1052     *pipe_oversub_bandwidth = 0;
   1053     PBMP_PORT_ITER(unit, port) {
   1054         if (si->port_pipe[port] != pipe) {
   1055             continue;
   1056         }
   1057         bandwidth = si->port_speed_max[port] >= 2500 ?
   1058             si->port_speed_max[port] : 2500;
   1059         if (SOC_PBMP_MEMBER(si->oversub_pbm, port)) {
   1060             *pipe_oversub_bandwidth += bandwidth;
   1061         } else {
   1062             *pipe_linerate_bandwidth += bandwidth;
   1063         }
   1064     }
   1065     /* 10G cpu/management, 5G loopback, 10G purge/refresh */
   1066     *pipe_linerate_bandwidth += 25;
   1067 }
   1068 #endif
   1069 
   1070 #if defined(BCM_TD3_ASF_EXCLUDE)
   1071 /*
   1072  * Cut-through class encoding
   1073  * 0 - SAF
   1074  * 1 - 10GE
   1075  * 2 - HG[11]
   1076  * 3 - 20GE
   1077  * 4 - 21[HG}
   1078  * 5 - 25GE
   1079  * 6 - HG[27]
   1080  * 7 - 40GE
   1081  * 8 - HG[42]
   1082  * 9 - 50GE
   1083  * 10 - HG[53]
   1084  * 11 - 100GE
   1085  * 12 - HG[106]
   1086  */
   1087 STATIC void
   1088 _soc_trident3_speed_to_ct_class_mapping(int unit, int speed, int *ct_class)
   1089 {
   1090     if (speed >= 40000) {
   1091         if (speed >= 100000) {
   1092             *ct_class = speed > 100000 ? 12 : 11;
   1093         } else if (speed >= 50000) {
   1094             *ct_class = speed > 50000 ? 10 : 9;
   1095         } else {
   1096             *ct_class = speed > 40000 ? 8 : 7;
   1097         }
   1098     } else {
   1099         if (speed >= 25000) {
   1100             *ct_class = speed > 25000 ? 6 : 5;
   1101         } else if (speed >= 20000) {
   1102             *ct_class = speed > 20000 ? 4 : 3;
   1103         } else {
   1104             *ct_class = speed > 10000 ? 2 : 1;
   1105         }
   1106     }
   1107 }
   1108 #endif
   1109 
   1110 /*
   1111  * Oversubscription group speed class encoding
   1112  * 0 - 0
   1113  * 1 - 2 (10G)
   1114  * 2 - 4 (20G)
   1115  * 3 - 5 (25G)
   1116  * 4 - 8 (40G)
   1117  * 5 - 10 (50G)
   1118  * 6 - 20 (100G)
   1119  */
   1120 STATIC void
   1121 _soc_trident3_speed_to_ovs_class_mapping(int unit, int speed, int *ovs_class)
   1122 {
   1123     if (speed >= 40000) {
   1124         if (speed >= 100000) {
   1125             *ovs_class = 6;
   1126         } else if (speed >= 50000) {
   1127             *ovs_class = 5;
   1128         } else {
   1129             *ovs_class = 4;
   1130         }
   1131     } else {
   1132         if (speed >= 25000) {
   1133             *ovs_class = 3;
   1134         } else if (speed >= 20000) {
   1135             *ovs_class = 2;
   1136         } else {
   1137             *ovs_class = 1;
   1138         }
   1139     }
   1140 }
   1141 
   1142 /* Function to get the number of ports present in a given Port Macro */
   1143 STATIC int
   1144 soc_td3_ports_per_pm_get(int unit, int pm_id)
   1145 {
   1146     soc_info_t *si;
   1147     int phy_port, num_ports = 0, i;
   1148 
   1149     si = &SOC_INFO(unit);
   1150     if (pm_id >= _TD3_PBLKS_PER_DEV(unit)) {
   1151        return SOC_E_PARAM;
   1152     }
   1153     phy_port = 1 + (pm_id * _TD3_PORTS_PER_PBLK);
   1154 
   1155     for (i = 0; i < _TD3_PORTS_PER_PBLK; ) {
   1156         if (si->port_p2l_mapping[phy_port + i] != -1) {
   1157             num_ports ++;
   1158             i += si->port_num_lanes[si->port_p2l_mapping[phy_port + i]];
   1159         } else {
   1160             i ++;
   1161         }
   1162     }
   1163     return num_ports;
   1164 }
   1165 
   1166 STATIC int
   1167 _soc_td3_port_flex_init(int unit, int is_any_cap)
   1168 {
   1169     soc_info_t *si;
   1170     int pm, blk_idx, blk_type;
   1171     int flex_en, static_ports, max_ports;
   1172 
   1173     si = &SOC_INFO(unit);
   1174     SHR_BITCLR_RANGE(si->flexible_pm_bitmap, 0, SOC_MAX_NUM_BLKS);
   1175 
   1176     /* portmap_x=y:speed:i */
   1177     /* portmap_x=y:speed:cap */
   1178     if (SOC_PBMP_NOT_NULL(SOC_PORT_DISABLED_BITMAP(unit, all)) || is_any_cap) {
   1179         SHR_BITSET_RANGE(si->flexible_pm_bitmap, 2, _TD3_PBLKS_PER_DEV(unit));
   1180     } else {
   1181         /* port_flex_enable{x}=<0...1> */
   1182         /* port_flex_enable_corex=<0...1> */
   1183         /* port_flex_enable=<0...1> */
   1184         for (blk_idx = 0; (blk_idx < SOC_MAX_NUM_BLKS) && (SOC_BLOCK_TYPE(unit, blk_idx)!= -1); blk_idx++) {
   1185             blk_type = SOC_BLOCK_TYPE(unit, blk_idx);
   1186             pm = SOC_BLOCK_NUMBER(unit, blk_idx);
   1187             if (blk_type == SOC_BLK_CLPORT) {
   1188        /* port_flex_enable_corex=<0...1> */
   1189                 flex_en = soc_property_suffix_num_get_only_suffix(unit,
   1190                     pm, spn_PORT_FLEX_ENABLE, "core", -1);
   1191                 /* port_flex_enable{x}=<0...1> */
   1192                 /* port_flex_enable=<0...1> */
   1193                 if (flex_en == -1) {
   1194                     flex_en = soc_property_phys_port_get(unit,
   1195                         (pm * _TD3_PORTS_PER_PBLK + 1),
   1196                         spn_PORT_FLEX_ENABLE, 0);
   1197                 }
   1198                 if (flex_en) {
   1199                     SHR_BITSET(si->flexible_pm_bitmap, blk_idx);
   1200                 }
   1201             }
   1202         }
   1203     }
   1204 
   1205     si->flex_eligible =
   1206         (!SHR_BITNULL_RANGE(si->flexible_pm_bitmap, 1, _TD3_PBLKS_PER_DEV(unit)));
   1207 
   1208     /* port_flex_max_ports */
   1209     memset(&(si->pm_max_ports), 0xff, sizeof(si->pm_max_ports));
   1210     for (blk_idx = 0; (blk_idx < SOC_MAX_NUM_BLKS) && (SOC_BLOCK_TYPE(unit, blk_idx)!= -1); blk_idx++) {
   1211         blk_type = SOC_BLOCK_TYPE(unit, blk_idx);
   1212         pm = SOC_BLOCK_NUMBER(unit, blk_idx);
   1213         if (blk_type == SOC_BLK_CLPORT) {
   1214             static_ports = soc_td3_ports_per_pm_get(unit, pm);
   1215             if (SHR_BITGET(si->flexible_pm_bitmap, blk_idx)) {
   1216                 /* port_flex_max_ports{x}=y */
   1217                 max_ports = soc_property_phys_port_get(unit,
   1218                     (pm * _TD3_PORTS_PER_PBLK + 1),
   1219                     spn_PORT_FLEX_MAX_PORTS, -1);
   1220                 /* port_flex_max_ports_corex=y */
   1221                 if (max_ports == -1) {
   1222                     max_ports = soc_property_suffix_num_get(unit, pm,
   1223                         spn_PORT_FLEX_MAX_PORTS, "core", 4);
   1224                 }
   1225                 /* validation check */
   1226                 if ((max_ports < 0) || (max_ports > 4) || (max_ports < static_ports)) {
   1227                     LOG_CLI((BSL_META_U(unit,
   1228                         "Core %d: Bad port_flex_max_ports %d; static ports %d"),
   1229                         pm, max_ports, static_ports));
   1230                     return SOC_E_CONFIG;
   1231                 }
   1232                 si->pm_max_ports[blk_idx] = max_ports;
   1233             } else {
   1234                 si->pm_max_ports[blk_idx] = static_ports;
   1235             }
   1236 
   1237         }
   1238     }
   1239 
   1240     return SOC_E_NONE;
   1241 }
   1242 
   1243 /*
   1244  * Function:
   1245  *      soc_trident3_port_map_validity_check
   1246  * Purpose:
   1247  *      Logical Port <-> Physical port map is fixed in Trident3.
   1248  *      This function checks if port map used in config.bcm is correct.
   1249  * Parameters:
   1250  *      unit (IN) - switch unit
   1251  *      port (IN) - device port
   1252  *      phy_port (IN) - physical port
   1253  * Returns:
   1254  *      SOC_E_FAIL OR SOC_E_NONE
   1255  */
   1256 int
   1257 soc_trident3_port_map_validity_check(int unit, int port, int phy_port) {
   1258 
   1259     int pmap_err = 0;
   1260 
   1261     if ((port >= 0) && (port <= 64)) {
   1262         if (port != phy_port) {
   1263             pmap_err = 1;
   1264         }
   1265     } else if((port == 65) && (phy_port != 130)) {
   1266         pmap_err = 1;
   1267     } else if ((port == 66) && (phy_port != 129)) {
   1268         pmap_err = 1;
   1269     } else if((port >= 67) && (port <= 130)) {
   1270         if (port != phy_port + 2) {
   1271             pmap_err = 1;
   1272         }
   1273     } else if((port == 131) && (phy_port != 131)) {
   1274         pmap_err = 1;
   1275     }
   1276 
   1277     if (pmap_err) {
   1278         LOG_CLI((BSL_META_U(unit,
   1279                             "Port %d: Invalid port map configuration\n"),
   1280                             port));
   1281         return SOC_E_FAIL;
   1282     }
   1283 
   1284     return SOC_E_NONE;
   1285 }
   1286 
   1287 /*
   1288  * Trident3 port mapping
   1289  *
   1290  *                   physical   idb/       device   mmu
   1291  *                   port       idb port   port     port
   1292  *     CMIC          0          0/64       0        64
   1293  *     CLPORT0-7     1-32       0/0-31     1-32     0-31
   1294  *     CLPORT8-15    33-64      0/32-63    33-64    32-63
   1295  *     CLPORT16-23   65-96      1/0-32     67-98    128-159
   1296  *     CLPORT24-31   97-128     1/32-63    99-130   160-191
   1297  *     MGMT          129        1/64       66       192
   1298  *     LBPORT0       130        0/65       65       65
   1299  *     LBPORT1       131        1/65       131      193
   1300  * Although MMU port number is flexible within the above range, it is
   1301  *     configured as a fixed mapped to physical port number
   1302  */
   1303 int
   1304 soc_trident3_port_config_init(int unit, uint16 dev_id)
   1305 {
   1306 #if defined(BCM_56870_A0)
   1307     soc_info_t *si;
   1308     char *config_str, *sub_str, *sub_str_end;
   1309     static const char str_2p5[] = "2.5";
   1310     char str_buf[8];
   1311     int rv, oversub_mode;
   1312     int num_port, num_phy_port, num_mmu_port;
   1313     int port, phy_port, mmu_port, idb_port;
   1314     int pipe, xpe, sc, index, bandwidth_cap, is_any_cap = FALSE;
   1315     int port_bandwidth, blk_idx;
   1316     char option1=0, option2=0;
   1317     uint32 pipe_map, xpe_map, sc_map, ipipe_map, epipe_map;
   1318     soc_pbmp_t oversub_pbm;
   1319     int list_len, frequency;
   1320     static const int freq_list[] = { 1525, 1425, 1325, 1012, 850 };
   1321     const char *str_ratio[] = { "2:3", "1:1" };
   1322     static const int dpp_ratio_x10_list[] = {
   1323         15, /* core clk : pp clk ratio is 3:2 (default) */
   1324         10  /* core clk : pp clk ratio is 1:1 */
   1325     };
   1326 
   1327     static const struct {
   1328         int port;
   1329         int phy_port;
   1330         int pipe;
   1331         int idb_port;
   1332         int mmu_port;
   1333     } fixed_ports[] = {
   1334         { 0,   0,   0, 64, 64 },    /* cpu port */
   1335         { 65,  130, 0, 65, 65 },    /* loopback port 0 */
   1336         { 131, 131, 1, 65, 193 },   /* loopback port 1 */
   1337     };
   1338 
   1339     si = &SOC_INFO(unit);
   1340 
   1341     num_phy_port = TD3_NUM_PHY_PORT;
   1342     num_port = TD3_NUM_PORT;
   1343     num_mmu_port = TD3_NUM_MMU_PORT;
   1344 
   1345     soc_trident3_max_frequency_get(unit, dev_id, -1, -1, &si->frequency);
   1346     frequency = soc_property_get(unit, spn_CORE_CLOCK_FREQUENCY, -1);
   1347 
   1348     /* Core CLK frequency */
   1349     if (frequency != -1 && frequency <= si->frequency) {
   1350         list_len = COUNTOF(freq_list);
   1351         for (index = 0; index < list_len; index++) {
   1352             if (freq_list[index] <= si->frequency &&
   1353                 frequency == freq_list[index]) {
   1354                 break;
   1355             }
   1356         }
   1357 
   1358         if (index < list_len) {
   1359             si->frequency = frequency;
   1360         } else {
   1361             LOG_CLI((BSL_META_U(unit,
   1362                                 "*** Input core clock frequency %dMHz is not "
   1363                                 "supported!\n"), frequency));
   1364         }
   1365     }
   1366 
   1367     config_str = soc_property_get_str(unit, spn_DPP_CLOCK_RATIO);
   1368     if (config_str) {
   1369         list_len = COUNTOF(dpp_ratio_x10_list);
   1370         for (index = 0; index < list_len; index++) {
   1371             if (!sal_strcmp(config_str, str_ratio[index])) {
   1372                 break;
   1373             }
   1374         }
   1375         if (index < list_len &&
   1376             !(si->frequency > 1012 && dpp_ratio_x10_list[index] == 10)) {
   1377             /* ratio 1:1 with core freq larger than 1125MHz is not supported */
   1378             si->dpp_clk_ratio_x10 = dpp_ratio_x10_list[index];
   1379         } else {
   1380             LOG_CLI((BSL_META_U(unit,
   1381                                 "*** Input dpp clock frequency ratio %s is not "
   1382                                 "supported with core frequency %d!\n"),
   1383                      config_str, si->frequency));
   1384         }
   1385     }
   1386 
   1387     si->bandwidth = 2048000;
   1388 
   1389 
   1390     oversub_pbm = soc_property_get_pbmp(unit, spn_PBMP_OVERSUBSCRIBE, 0);
   1391     oversub_mode = soc_property_get(unit, spn_OVERSUBSCRIBE_MODE, 1) ||
   1392                    SOC_PBMP_NOT_NULL(oversub_pbm);
   1393 
   1394     si->oversub_mode = oversub_mode;
   1395     si->os_mixed_sister_25_50_enable = soc_property_get(unit,
   1396                          spn_OVERSUBSCRIBE_MIXED_SISTER_25_50_ENABLE, 0);
   1397 
   1398     /* Line rate mode requires DPR 1:1 and Core frequency no more than 1125MHz */
   1399     if ((!si->oversub_mode)) {
   1400         if (si->frequency > 1012) {
   1401             LOG_CLI((BSL_META_U(unit,
   1402                                 "*** Input core clock frequency %dMHz is not "
   1403                                 "supported with line rate mode! "
   1404                                 "Must be no more than 1012MHz.\n"), si->frequency));
   1405             return SOC_E_FAIL;
   1406         }
   1407         if (si->dpp_clk_ratio_x10 != 10) {
   1408             LOG_CLI((BSL_META_U(unit,
   1409                                 "*** Input dpp clock frequency ratio %s is not "
   1410                                 "supported with line rate mode! "
   1411                                 "Must be 1:1.\n"), (config_str ? config_str : "")));
   1412             return SOC_E_FAIL;
   1413         }
   1414     }
   1415 
   1416     for (phy_port = 0; phy_port < num_phy_port; phy_port++) {
   1417         si->port_p2l_mapping[phy_port] = -1;
   1418         si->port_p2m_mapping[phy_port] = -1;
   1419     }
   1420     for (port = 0; port < num_port; port++) {
   1421         si->port_l2p_mapping[port] = -1;
   1422         si->port_l2i_mapping[port] = -1;
   1423         si->port_speed_max[port] = -1;
   1424         si->port_group[port] = -1;
   1425         si->port_serdes[port] = -1;
   1426         si->port_pipe[port] = -1;
   1427         si->port_num_lanes[port] = -1;
   1428     }
   1429     for (mmu_port = 0; mmu_port < num_mmu_port; mmu_port++) {
   1430         si->port_m2p_mapping[mmu_port] = -1;
   1431     }
   1432     SOC_PBMP_CLEAR(si->eq_pbm);
   1433     SOC_PBMP_CLEAR(si->management_pbm);
   1434     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   1435         SOC_PBMP_CLEAR(si->pipe_pbm[pipe]);
   1436     };
   1437     SOC_PBMP_CLEAR(si->oversub_pbm);
   1438     SOC_PBMP_CLEAR(si->all.disabled_bitmap);
   1439 
   1440     /* Populate the fixed mapped ports */
   1441     for (index = 0; index < COUNTOF(fixed_ports); index++) {
   1442         port = fixed_ports[index].port;
   1443         phy_port = fixed_ports[index].phy_port;
   1444         pipe = fixed_ports[index].pipe;;
   1445 
   1446         si->port_l2p_mapping[port] = phy_port;
   1447         si->port_l2i_mapping[port] = fixed_ports[index].idb_port;
   1448         si->port_p2l_mapping[phy_port] = port;
   1449         si->port_p2m_mapping[phy_port] = fixed_ports[index].mmu_port;
   1450         si->port_pipe[port] = pipe;
   1451     }
   1452 
   1453     rv = SOC_E_NONE;
   1454     for (port = 1; port < num_port; port++) {
   1455         if (si->port_l2p_mapping[port] != -1) { /* fixed mapped port */
   1456             continue;
   1457         }
   1458 
   1459         config_str = soc_property_port_get_str(unit, port, spn_PORTMAP);
   1460         if (config_str == NULL) {
   1461             continue;
   1462         }
   1463 
   1464         /*
   1465          * portmap_<port>=<physical port number>:<bandwidth in Gb>[:<bandwidth cap in Gb/i(inactive)/1/2/4(num lanes)>][:<i>]
   1466          * eg:    portmap_1=1:100
   1467          *     or portmap_1=1:40
   1468          *     or portmap_1=1:40:i
   1469          *     or portmap_1=1:40:2
   1470          *     or portmap_1=1:40:2:i
   1471          *     or portmap_1=1:10:100
   1472          */
   1473         sub_str = config_str;
   1474 
   1475         /* Parse physical port number */
   1476         phy_port = sal_ctoi(sub_str, &sub_str_end);
   1477         if (sub_str == sub_str_end) {
   1478             LOG_CLI((BSL_META_U(unit,
   1479                                 "Port %d: Missing physical port information \"%s\"\n"),
   1480                      port, config_str));
   1481             rv = SOC_E_FAIL;
   1482             continue;
   1483         }
   1484         if (phy_port < 0 || phy_port >= num_phy_port) {
   1485             LOG_CLI((BSL_META_U(unit,
   1486                                 "Port %d: Invalid physical port number %d\n"),
   1487                      port, phy_port));
   1488             rv = SOC_E_FAIL;
   1489             continue;
   1490         }
   1491         /* coverity[check_after_sink : FALSE] */
   1492         if (si->port_p2l_mapping[phy_port] != -1) {
   1493             LOG_CLI((BSL_META_U(unit,
   1494                                 "Port %d: Physical port %d is used by port %d\n"),
   1495                      port, phy_port, si->port_p2l_mapping[phy_port]));
   1496             rv = SOC_E_FAIL;
   1497             continue;
   1498         }
   1499 
   1500         /* Skip ':' between physical port number and bandwidth */
   1501         sub_str = sub_str_end;
   1502         if (*sub_str != '\0') {
   1503             if (*sub_str != ':') {
   1504                 LOG_CLI((BSL_META_U(unit,
   1505                                     "Port %d: Bad config string \"%s\"\n"),
   1506                          port, config_str));
   1507                 rv = SOC_E_FAIL;
   1508                 continue;
   1509             }
   1510             sub_str++;
   1511         }
   1512 
   1513         if (soc_trident3_port_map_validity_check(unit, port, phy_port)) {
   1514             rv = SOC_E_FAIL;
   1515             continue;
   1516         }
   1517 
   1518         /* Parse bandwidth */
   1519         for (index = 0; index < sizeof(str_2p5) - 1; index++) {
   1520             if (sub_str[index] == '\0') {
   1521                 break;
   1522             }
   1523             str_buf[index] = sub_str[index];
   1524         }
   1525         str_buf[index] = '\0';
   1526         if (!sal_strcmp(str_buf, str_2p5)) {
   1527             port_bandwidth = 2500;
   1528             sub_str_end = &sub_str[sizeof(str_2p5) - 1];
   1529         } else {
   1530             port_bandwidth = sal_ctoi(sub_str, &sub_str_end) * 1000;
   1531             if (sub_str == sub_str_end) {
   1532                 LOG_CLI((BSL_META_U(unit,
   1533                                     "Port %d: Missing bandwidth information \"%s\"\n"),
   1534                          port, config_str));
   1535                 rv = SOC_E_FAIL;
   1536                 continue;
   1537             }
   1538             switch (port_bandwidth) {
   1539             case 1000:
   1540             case 10000:
   1541             case 11000:
   1542             case 20000:
   1543             case 21000:
   1544             case 25000:
   1545             case 27000:
   1546             case 40000:
   1547             case 42000:
   1548             case 50000:
   1549             case 53000:
   1550             case 100000:
   1551             case 106000:
   1552                 break;
   1553             default:
   1554                 LOG_CLI((BSL_META_U(unit,
   1555                                     "Port %d: Invalid bandwidth %d Gb\n"),
   1556                          port, port_bandwidth / 1000));
   1557                 rv = SOC_E_FAIL;
   1558                 continue;
   1559             }
   1560             if ((!si->oversub_mode) && ((port_bandwidth == 100000) ||
   1561                                         (port_bandwidth == 106000))) {
   1562                 LOG_CLI((BSL_META_U(unit,
   1563                                     "Port %d: %d Gb is Invalid bandwidth for line rate configuration\n"),
   1564                          port, port_bandwidth / 1000));
   1565                 return SOC_E_FAIL;
   1566             }
   1567         }
   1568 
   1569         /* Check if option presents */
   1570         option1 = 0; option2 = 0;
   1571         sub_str = sub_str_end;
   1572         if (*sub_str != '\0') {
   1573             /* Skip ':' between bandwidth and options */
   1574             /* Skip ':' between bandwidth and bandwidth cap or options */
   1575             if (*sub_str != ':') {
   1576                 LOG_CLI((BSL_META_U(unit,
   1577                                     "Port %d: Bad config string \"%s\"\n"),
   1578                          port, config_str));
   1579                 rv = SOC_E_FAIL;
   1580                 continue;
   1581             }
   1582             sub_str++;
   1583 
   1584             if (*sub_str != '\0') {
   1585                 /* Parse bandwidth cap or options */
   1586                 bandwidth_cap = sal_ctoi(sub_str, &sub_str_end) * 1000;
   1587                 switch (bandwidth_cap) {
   1588                 case 20000:
   1589                 case 21000:
   1590                 case 25000:
   1591                 case 27000:
   1592                 case 40000:
   1593                 case 42000:
   1594                 case 50000:
   1595                 case 53000:
   1596                 case 100000:
   1597                 case 106000:
   1598                     sub_str = sub_str_end;
   1599                     _soc_td3_port_speed_cap[unit][port] = bandwidth_cap;
   1600                     /* Flex config detected, port speed cap specified */
   1601                     is_any_cap = TRUE;
   1602                     break;
   1603                 default:
   1604                     if (!(*sub_str == 'i' || *sub_str == '1' ||
   1605                           *sub_str == 'm' || *sub_str == '2' ||
   1606                           *sub_str == '4')) {
   1607                         LOG_CLI((BSL_META_U(unit,
   1608                                             "Port %d: Bad config string "
   1609                                             "\"%s\"\n"),
   1610                              port, config_str));
   1611                         rv = SOC_E_FAIL;
   1612                         continue;
   1613                     } else {
   1614                         option1 = *sub_str;
   1615                         sub_str++;
   1616                     }
   1617                 }
   1618 
   1619                 /* Check if more options present */
   1620                 if (*sub_str != '\0') {
   1621                     /* Skip ':' between options */
   1622                     if (*sub_str != ':') {
   1623                         LOG_CLI((BSL_META_U(unit,
   1624                                             "Port %d: Bad config string \"%s\"\n"),
   1625                                  port, config_str));
   1626                         rv = SOC_E_FAIL;
   1627                         continue;
   1628                     }
   1629                     sub_str++;
   1630 
   1631                     if (*sub_str != 'i' && *sub_str != 'm') {
   1632                         LOG_CLI((BSL_META_U(unit,
   1633                                             "Port %d: Bad config string \"%s\"\n"),
   1634                                  port, config_str));
   1635                         rv = SOC_E_FAIL;
   1636                         continue;
   1637                     }
   1638                     option2 = *sub_str;
   1639                     sub_str++;
   1640                 }
   1641             }
   1642         }
   1643 
   1644         /* Check trailing string */
   1645         if (*sub_str != '\0') {
   1646             LOG_CLI((BSL_META_U(unit,
   1647                                 "Port %d: Bad config string \"%s\"\n"),
   1648                      port, config_str));
   1649             rv = SOC_E_FAIL;
   1650             continue;
   1651         }
   1652 
   1653         /* Update soc_info */
   1654         si->port_l2p_mapping[port] = phy_port;
   1655         si->port_p2l_mapping[phy_port] = port;
   1656         if (phy_port == 129) { /* management port 0 */
   1657             pipe = 1;
   1658             si->port_l2i_mapping[port] = 64;
   1659             si->port_p2m_mapping[phy_port] = 192;
   1660             si->port_serdes[port] = 32;
   1661             SOC_PBMP_PORT_ADD(si->management_pbm, port);
   1662             if (option2 == 'm'){
   1663                 si->port_num_lanes[port] = (option1 == '4')? 4 : (option1 == '2')? 2 : 1;
   1664             } else {
   1665                 si->port_num_lanes[port] = 1;
   1666             }
   1667         } else if ((phy_port == 128) && ((option1 == 'm')||(option2 == 'm'))) { /* Management port 1 */
   1668             pipe = 1;
   1669             si->port_l2i_mapping[port] = 63;        /* Local  MMU Port */
   1670             si->port_p2m_mapping[phy_port] = 191;   /* Global MMU Port */
   1671             si->port_serdes[port] = 32;
   1672             SOC_PORT_BLOCK(unit, phy_port) = SOC_PORT_BLOCK(unit, 129); /* lane 2 */
   1673             SOC_PORT_BINDEX(unit, phy_port) = 2;
   1674             SOC_PBMP_PORT_ADD(si->management_pbm, port);
   1675             if (option2 == 'm'){
   1676                 si->port_num_lanes[port] = (option1 == '2')? 2 : 1;
   1677             } else {
   1678                 si->port_num_lanes[port] = 1;
   1679             }
   1680         } else {
   1681             idb_port = (phy_port - 1) % _TD3_PORTS_PER_PIPE;
   1682             pipe = (phy_port - 1) / _TD3_PORTS_PER_PIPE;
   1683             si->port_l2i_mapping[port] = idb_port;
   1684             si->port_p2m_mapping[phy_port] = (pipe << 7) | idb_port;
   1685             si->port_serdes[port] = (phy_port - 1) / _TD3_PORTS_PER_PBLK;
   1686             if (phy_port == 128) {
   1687                 SOC_PORT_BLOCK(unit, phy_port) = SOC_PORT_BLOCK(unit, 127);
   1688                 SOC_PORT_BINDEX(unit, phy_port) = SOC_PORT_BINDEX(unit, 127) + 1;
   1689             }
   1690         }
   1691         si->port_pipe[port] = pipe;
   1692         SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port);
   1693         si->port_speed_max[port] = port_bandwidth;
   1694         if (option1 == 'i') {
   1695             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port);
   1696         } else {
   1697             if ((option2 != 'm') && (option1 != 'm')) {
   1698                 switch (option1) {
   1699                     case '1': si->port_num_lanes[port] = 1; break;
   1700                     case '2': si->port_num_lanes[port] = 2; break;
   1701                     case '4': si->port_num_lanes[port] = 4; break;
   1702                     default: si->port_num_lanes[port] = 4; break;
   1703                 }
   1704             }
   1705         }
   1706         if (option2 == 'i') {
   1707             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port);
   1708         }
   1709         if (oversub_mode) {
   1710             SOC_PBMP_PORT_ADD(si->oversub_pbm, port);
   1711         }
   1712     }
   1713 
   1714     for (index = 1; index < COUNTOF(fixed_ports); index++) {
   1715         pipe = fixed_ports[index].pipe;
   1716         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   1717             /* Remove loopback port if the entire pipe is not in use */
   1718             port = fixed_ports[index].port;
   1719             phy_port = fixed_ports[index].phy_port;
   1720             si->port_l2p_mapping[port] = -1;
   1721             si->port_l2i_mapping[port] = -1;
   1722             si->port_p2l_mapping[phy_port] = -1;
   1723             si->port_p2m_mapping[phy_port] = -1;
   1724             si->port_pipe[port] = -1;
   1725         } else {
   1726             port = fixed_ports[index].port;
   1727             SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port);
   1728         }
   1729     }
   1730 
   1731     if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
   1732         LOG_CLI((BSL_META_U(unit,
   1733                             "physical to logical mapping:")));
   1734         for (index = 0; index < num_phy_port; index++) {
   1735             if (index % 16 == 0) {
   1736                 LOG_CLI((BSL_META_U(unit,
   1737                                     "\n    ")));
   1738             }
   1739             LOG_CLI((BSL_META_U(unit,
   1740                                 " %3d"), si->port_p2l_mapping[index]));
   1741         }
   1742         LOG_CLI((BSL_META_U(unit,
   1743                             "\n")));
   1744         LOG_CLI((BSL_META_U(unit,
   1745                             "physical port bandwidth:")));
   1746         for (index = 0; index < num_phy_port; index++) {
   1747             if (index % 16 == 0) {
   1748                 LOG_CLI((BSL_META_U(unit,
   1749                                     "\n    ")));
   1750             }
   1751             port = si->port_p2l_mapping[index];
   1752             if (port == -1) {
   1753                 LOG_CLI((BSL_META_U(unit,
   1754                                     "  -1")));
   1755             } else if (si->port_speed_max[port] == 2500) {
   1756                 LOG_CLI((BSL_META_U(unit,
   1757                                     " 2.5")));
   1758             } else {
   1759                 LOG_CLI((BSL_META_U(unit,
   1760                                     " %3d"), si->port_speed_max[port] / 1000));
   1761             }
   1762         }
   1763         LOG_CLI((BSL_META_U(unit,
   1764                             "\n")));
   1765 
   1766         LOG_CLI((BSL_META_U(unit,
   1767                             "physical to mmu mapping:")));
   1768         for (index = 0; index < num_phy_port; index++) {
   1769             if (index % 16 == 0) {
   1770                 LOG_CLI((BSL_META_U(unit,
   1771                                     "\n    ")));
   1772             }
   1773             LOG_CLI((BSL_META_U(unit,
   1774                                 " %3d"), si->port_p2m_mapping[index]));
   1775         }
   1776         LOG_CLI((BSL_META_U(unit,
   1777                             "\n")));
   1778     }
   1779 
   1780     
   1781 
   1782     /* Setup port_num_lanes */
   1783     for (port = 0; port < num_port; port++) {
   1784         if (si->port_speed_max[port] > 53000) {
   1785             si->port_num_lanes[port] = 4;
   1786         } else if (si->port_speed_max[port] == 40000 ||
   1787                    si->port_speed_max[port] == 42000) {
   1788             /* Note: 40G, HG[42] can operate either in dual or quad lane mode
   1789                      Check if adjacent ports exist to set dual lane mode */
   1790             phy_port = si->port_l2p_mapping[port];
   1791             if (phy_port >= 1 && phy_port <= 127 && phy_port != -1) {
   1792                 int sis_port;
   1793 
   1794                 if (phy_port % 4 == 1) {
   1795                     sis_port = si->port_p2l_mapping[phy_port+2];
   1796                     if ((si->port_speed_max[sis_port] > 0) &&
   1797                         !SOC_PBMP_MEMBER(si->all.disabled_bitmap, sis_port)) {
   1798                         si->port_num_lanes[port] = 2;
   1799                     }
   1800                 } else if (phy_port % 4 == 3) {
   1801                     sis_port = si->port_p2l_mapping[phy_port-2];
   1802                     if ((si->port_speed_max[sis_port] > 0) &&
   1803                         !SOC_PBMP_MEMBER(si->all.disabled_bitmap, sis_port)) {
   1804                         si->port_num_lanes[port] = 2;
   1805                     }
   1806                 }
   1807             }
   1808             /* Else set to quad lane mode by default if the user did not
   1809                specify anything and no sister ports existed */
   1810             if (si->port_num_lanes[port] == -1) {
   1811                 si->port_num_lanes[port] = 4;
   1812             }
   1813         } else if ((si->port_speed_max[port] >= 20000) &&
   1814                     !(si->port_speed_max[port] == 25000 ||
   1815                       si->port_speed_max[port] == 27000)) {
   1816             /* 50G, HG[53], 20G MLD, HG[21] use 2 lanes */
   1817             si->port_num_lanes[port] = 2;
   1818         } else if (si->port_speed_max[port] > 0) {
   1819             /* 10G XFI, HG[11], 25G XFI and HG[27] use 1 lane */
   1820             if (!SOC_PBMP_MEMBER(SOC_INFO(unit).management_pbm, port)) {
   1821                 si->port_num_lanes[port] = 1;
   1822             }
   1823         }
   1824     }
   1825 
   1826     /* get flex port properties */
   1827     if (SOC_FAILURE(_soc_td3_port_flex_init(unit, is_any_cap))) {
   1828         rv = SOC_E_FAIL;
   1829     }
   1830 
   1831 #if defined(BCM_WARM_BOOT_SUPPORT)
   1832     if (si->flex_eligible) {
   1833         if (SOC_WARM_BOOT(unit)) {
   1834             SOC_IF_ERROR_RETURN(
   1835                 soc_td3_flexport_scache_recovery(unit));
   1836         } else {
   1837             SOC_IF_ERROR_RETURN(
   1838                 soc_td3_flexport_scache_allocate(unit));
   1839         }
   1840     }
   1841 #endif
   1842 
   1843     /*
   1844      * After WARM BOOT flex port scache recovery, P/L and L/P bit map changed
   1845      * Need to redo bit map creation per port type.
   1846      */
   1847 
   1848     /* Setup high speed port (HSP) pbm */
   1849     for (port = 0; port < num_port; port++) {
   1850         phy_port = si->port_l2p_mapping[port];
   1851         if (phy_port == -1) {
   1852             continue;
   1853         }
   1854 
   1855         if (phy_port == 129) { /* management port 0 */
   1856             pipe = 1;
   1857             si->port_l2i_mapping[port] = 64;
   1858             si->port_p2m_mapping[phy_port] = 192;
   1859             si->port_serdes[port] = 32;
   1860             SOC_PBMP_PORT_ADD(si->management_pbm, port);
   1861         } else if ((phy_port == 128) && (option1 == 'm')) { /* Management port 1 */
   1862             pipe = 1;
   1863             si->port_l2i_mapping[port] = 63;        /* Local  MMU Port */
   1864             si->port_p2m_mapping[phy_port] = 191;   /* Global MMU Port */
   1865             si->port_serdes[port] = 32;
   1866             SOC_PORT_BLOCK(unit, phy_port) = SOC_PORT_BLOCK(unit, 129); /* lane 2 */
   1867             SOC_PORT_BINDEX(unit, phy_port) = 2;
   1868             SOC_PBMP_PORT_ADD(si->management_pbm, port);
   1869         } else if (phy_port >= 130) { /* loopback port (130 and 131 in TD3) */
   1870             pipe = phy_port - 130;
   1871             idb_port = 65;
   1872         } else if (phy_port == 0) {
   1873             pipe = 0;
   1874         } else {
   1875             idb_port = (phy_port - 1) % _TD3_PORTS_PER_PIPE;
   1876             pipe = (phy_port - 1) / _TD3_PORTS_PER_PIPE;
   1877             si->port_l2i_mapping[port] = idb_port;
   1878             si->port_p2m_mapping[phy_port] = (pipe << 7) | idb_port;
   1879             si->port_serdes[port] = (phy_port - 1) / _TD3_PORTS_PER_PBLK;
   1880         }
   1881         si->port_pipe[port] = pipe;
   1882         SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port);
   1883 
   1884         if (oversub_mode) {
   1885             SOC_PBMP_PORT_ADD(si->oversub_pbm, port);
   1886         }
   1887 
   1888         if (si->port_speed_max[port] >= 40000) {
   1889             SOC_PBMP_PORT_ADD(si->eq_pbm, port);
   1890         }
   1891     }
   1892 
   1893     /* Setup pipe/xpe mapping
   1894      * XPE_E / XPE_D (SC/SED): IP 0/1 EP 0/1
   1895      */
   1896     pipe_map = 0;
   1897     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   1898         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   1899             continue;
   1900         }
   1901         pipe_map |= 1 << pipe;
   1902     }
   1903     xpe_map = 0;
   1904     for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   1905         ipipe_map = 0x3 & pipe_map;
   1906         epipe_map = 0x3 & pipe_map;
   1907         if (ipipe_map == 0 || epipe_map == 0) {
   1908             continue;
   1909         }
   1910         xpe_map |= 1 << xpe;
   1911         si->xpe_ipipe_map[xpe] = ipipe_map;
   1912         si->xpe_epipe_map[xpe] = epipe_map;
   1913     }
   1914     sc_map = 0;
   1915     for (sc = 0; sc < NUM_SLICE(unit); sc++) {
   1916         ipipe_map = pipe_map;
   1917         epipe_map = 0x3 & pipe_map;
   1918         if (ipipe_map == 0 || epipe_map == 0) {
   1919             continue;
   1920         }
   1921         sc_map |= 1 << sc;
   1922         si->sc_ipipe_map[sc] = ipipe_map;
   1923         si->sc_epipe_map[sc] = epipe_map;
   1924     }
   1925     for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) {
   1926         /* Number of pipes is 4 in Tomahawk */
   1927         /* coverity[overrun-local : FALSE] */
   1928         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   1929             continue;
   1930         }
   1931         /* coverity[overrun-local : FALSE] */
   1932         si->ipipe_xpe_map[pipe] = 0x1 & xpe_map;
   1933         /* coverity[overrun-local : FALSE] */
   1934         si->epipe_xpe_map[pipe] = 0x1 & xpe_map;
   1935         /* coverity[overrun-local : FALSE] */
   1936         si->ipipe_sc_map[pipe] = 0x1 & sc_map;
   1937         /* coverity[overrun-local : FALSE] */
   1938         si->epipe_sc_map[pipe] = 0x1 & sc_map;
   1939     }
   1940 
   1941     /* Setup clport refclk master block bitmap.
   1942      * In TD3, there are 8 port macros (clport 6,7,24,25) that
   1943      * will driven directly from the system board and they will act as the
   1944      * refclk master to drive the other instances.
   1945      */
   1946     SHR_BITCLR_RANGE(si->pm_ref_master_bitmap, 0, SOC_MAX_NUM_BLKS);
   1947     for (blk_idx = 0; (blk_idx < SOC_MAX_NUM_BLKS) && (SOC_BLOCK_TYPE(unit, blk_idx)!= -1); blk_idx++) {
   1948         int blknum = SOC_BLOCK_NUMBER(unit, blk_idx);
   1949         int blktype = SOC_BLOCK_TYPE(unit, blk_idx);
   1950 
   1951         /* CLPORTs 7,8,23,24 provide master clock for other ports */
   1952         if (blktype == SOC_BLK_CLPORT) {
   1953             if ((blknum == 7 || blknum == 8 || blknum == 23 || blknum == 24)) {
   1954                 SHR_BITSET(si->pm_ref_master_bitmap, blk_idx);
   1955             }
   1956         }
   1957     }
   1958 
   1959     return rv;
   1960 #else
   1961     return SOC_E_UNAVAIL;
   1962 #endif
   1963 }
   1964 
   1965 #if !defined(BCM_TD3_ASF_EXCLUDE)
   1966 int
   1967 soc_td3_port_oversub_ratio_get(
   1968     int              unit,
   1969     soc_port_t       port,
   1970     OUT int* const   ratio)
   1971 {
   1972     soc_info_t          *si;
   1973     _soc_trident3_tdm_temp_t *tdm;
   1974     int                  pipe, hpipe, max_ovs_ratio;
   1975 
   1976     if (!ratio) {
   1977         return SOC_E_PARAM;
   1978     }
   1979 
   1980     if (SAL_BOOT_XGSSIM) {
   1981         *ratio = 0;
   1982         return SOC_E_NONE;
   1983     }
   1984 
   1985     si = &SOC_INFO(unit);
   1986     tdm = SOC_CONTROL(unit)->tdm_info;
   1987 
   1988     if (!si || !tdm) {
   1989         return SOC_E_INTERNAL;
   1990     }
   1991 
   1992     max_ovs_ratio = 0;
   1993     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   1994         for (hpipe = 0; hpipe < TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
   1995             if (max_ovs_ratio < tdm->ovs_ratio_x1000[pipe][hpipe]) {
   1996                 max_ovs_ratio = tdm->ovs_ratio_x1000[pipe][hpipe];
   1997             }
   1998         }
   1999     }
   2000     *ratio = max_ovs_ratio;
   2001 
   2002     return SOC_E_NONE;
   2003 }
   2004 #endif
   2005 
   2006 uint32 soc_td3_temp_mon_mask[SOC_MAX_NUM_DEVICES]={0};
   2007 
   2008 /*
   2009  * Function:
   2010  *      soc_td3_set_idb_dpp_ctrl
   2011  * Purpose:
   2012  *      Configure IDB DPP credits
   2013  * Parameters:
   2014  *      unit (IN)    - switch unit
   2015  * Returns:
   2016  *      SOC_E_*
   2017  */
   2018 int
   2019 soc_td3_set_idb_dpp_ctrl(int unit)
   2020 {
   2021     soc_reg_t reg;
   2022     uint32 pipe_map, in_progress;
   2023     int pipe;
   2024     uint32 rval, rval0;
   2025     int pipe_init_usec;
   2026     soc_timeout_t to;
   2027     static const soc_reg_t idb_dpp_ctrl[2] = {
   2028         IDB_DPP_CTRL_PIPE0r, IDB_DPP_CTRL_PIPE1r
   2029     };
   2030 
   2031     soc_trident3_pipe_map_get(unit, &pipe_map);
   2032 
   2033     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   2034         if (!(pipe_map & (1 << pipe))) {
   2035             continue;
   2036         }
   2037         reg = idb_dpp_ctrl[pipe];
   2038         rval = 0;
   2039         /*SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));*/
   2040         soc_reg_field_set(unit, reg, &rval, MAX_REF_CNTf, 4);
   2041         soc_reg_field_set(unit, reg, &rval, MAX_SBUS_CNTf, 4);
   2042         soc_reg_field_set(unit, reg, &rval, CREDITSf, 62);
   2043         soc_reg_field_set(unit, reg, &rval, DONEf, 0);
   2044         soc_reg_field_set(unit, reg, &rval, STARTf, 1);
   2045         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   2046     }
   2047 
   2048     /* For simulation, set timeout to 10 sec.  Otherwise, timeout = 50 ms */
   2049     if (SAL_BOOT_SIMULATION) {
   2050         pipe_init_usec = 10000000;
   2051     } else {
   2052         pipe_init_usec = 50000;
   2053     }
   2054     soc_timeout_init(&to, pipe_init_usec, 0);
   2055 
   2056     /* Wait for DPP credit initialization done */
   2057     in_progress = pipe_map;
   2058     do {
   2059         for (pipe = 0; pipe < NUM_PIPE(unit) && in_progress; pipe++) {
   2060             reg = SOC_REG_UNIQUE_ACC(unit, IDB_DPP_CTRLr)[pipe];
   2061             if (in_progress & (1 << pipe)) { /* not done yet */
   2062                 SOC_IF_ERROR_RETURN
   2063                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval0));
   2064                 if (soc_reg_field_get(unit, reg, rval0, DONEf)) {
   2065                     in_progress ^= (1 << pipe);
   2066                 }
   2067             }
   2068         }
   2069         if (soc_timeout_check(&to)) {
   2070             LOG_WARN(BSL_LS_SOC_COMMON,
   2071                      (BSL_META_U(unit,
   2072                                  "unit %d : IDB_DPP_CTRL timeout\n"), unit));
   2073             break;
   2074         }
   2075     } while (in_progress != 0);
   2076 
   2077     return SOC_E_NONE;
   2078 }
   2079 
   2080 STATIC int
   2081 _soc_trident3_idb_init(int unit)
   2082 {
   2083     soc_info_t *si;
   2084     _soc_trident3_tdm_temp_t *tdm;
   2085     soc_reg_t reg;
   2086     soc_field_t field;
   2087     int block_info_idx, pipe, clport, obm, lane;
   2088     int port, phy_port_base, lport;
   2089     int lossless, i, count;
   2090     uint32 rval0, rval1, fval;
   2091     uint32 rval_port_cfg = 0, rval_max_usage_cfg = 0;
   2092     uint64 rval64;
   2093     int num_lanes, oversub_ratio_idx;
   2094     uint32 entry[SOC_MAX_MEM_WORDS];
   2095     soc_mem_t mem;
   2096 
   2097     static const struct _obm_setting_s {
   2098         int discard_limit;
   2099         int lossless_xoff;
   2100         int lossy_only_lossy_low_pri;
   2101         int port_xoff[3];          /* for oversub ratio 1.5, 1.8, and above */
   2102         int lossy_low_pri[3];      /* for oversub ratio 1.5, 1.8, and above */
   2103         int lossy_discard[3];      /* for oversub ratio 1.5, 1.8, and above */
   2104         int buffer_start[4];
   2105         int buffer_end[4];
   2106     } obm_settings[] = { /* indexed by number of lanes */
   2107         { /* 0 - invalid  */ 0 },
   2108         { /* 1 lane */
   2109             1148, 136, 806,
   2110             { 428, 428, 428 }, /* port_xoff */
   2111             { 235, 235, 235 }, /* lossy_low_pri */
   2112             { 573, 573, 573 },  /* lossy_discard */
   2113             { 0,    1152, 2304, 3456}, /* buffer_start */
   2114             { 1151, 2303, 3455, 4607}  /* buffer_end */
   2115         },
   2116         { /* 2 lanes */
   2117             2300, 324, 1958,
   2118             { 1310, 1310, 1310 }, /* port_xoff */
   2119             { 235, 235, 235 }, /* lossy_low_pri */
   2120             { 573, 573, 573 },  /* lossy_discard */
   2121             { 0,    0, 2304,    0   },  /* buffer_start */
   2122             { 2303, 4607, 4607, 4607}   /* buffer_end */
   2123         },
   2124         { /* 3 - invalid  */ 0 },
   2125         { /* 4 lanes */
   2126             4604, 774, 4262,
   2127             { 2989, 2989, 2989 }, /* port_xoff */
   2128             { 235, 235, 235 }, /* lossy_low_pri */
   2129             { 573, 573, 573 },  /* lossy_discard */
   2130             { 0,    0,    0,    0   }, /* buffer_start */
   2131             { 4607, 4607, 4607, 4607}  /* buffer_end */
   2132         }
   2133     };
   2134 
   2135     static const soc_reg_t obm_ctrl_regs[] = {
   2136         IDB_OBM0_CONTROLr, IDB_OBM1_CONTROLr,
   2137         IDB_OBM2_CONTROLr, IDB_OBM3_CONTROLr,
   2138         IDB_OBM4_CONTROLr, IDB_OBM5_CONTROLr,
   2139         IDB_OBM6_CONTROLr, IDB_OBM7_CONTROLr,
   2140         IDB_OBM8_CONTROLr, IDB_OBM9_CONTROLr,
   2141         IDB_OBM10_CONTROLr, IDB_OBM11_CONTROLr,
   2142         IDB_OBM12_CONTROLr, IDB_OBM13_CONTROLr,
   2143         IDB_OBM14_CONTROLr, IDB_OBM15_CONTROLr
   2144     };
   2145     static const soc_reg_t obm_ca_ctrl_regs[] = {
   2146         IDB_OBM0_CA_CONTROLr, IDB_OBM1_CA_CONTROLr,
   2147         IDB_OBM2_CA_CONTROLr, IDB_OBM3_CA_CONTROLr,
   2148         IDB_OBM4_CA_CONTROLr, IDB_OBM5_CA_CONTROLr,
   2149         IDB_OBM6_CA_CONTROLr, IDB_OBM7_CA_CONTROLr,
   2150         IDB_OBM8_CA_CONTROLr, IDB_OBM9_CA_CONTROLr,
   2151         IDB_OBM10_CA_CONTROLr, IDB_OBM11_CA_CONTROLr,
   2152         IDB_OBM12_CA_CONTROLr, IDB_OBM13_CA_CONTROLr,
   2153         IDB_OBM14_CA_CONTROLr, IDB_OBM15_CA_CONTROLr
   2154     };
   2155     static const soc_reg_t obm_thresh_regs[] = {
   2156         IDB_OBM0_THRESHOLDr, IDB_OBM1_THRESHOLDr,
   2157         IDB_OBM2_THRESHOLDr, IDB_OBM3_THRESHOLDr,
   2158         IDB_OBM4_THRESHOLDr, IDB_OBM5_THRESHOLDr,
   2159         IDB_OBM6_THRESHOLDr, IDB_OBM7_THRESHOLDr,
   2160         IDB_OBM8_THRESHOLDr, IDB_OBM9_THRESHOLDr,
   2161         IDB_OBM10_THRESHOLDr, IDB_OBM11_THRESHOLDr,
   2162         IDB_OBM12_THRESHOLDr, IDB_OBM13_THRESHOLDr,
   2163         IDB_OBM14_THRESHOLDr, IDB_OBM15_THRESHOLDr
   2164     };
   2165     static const soc_reg_t obm_thresh_1_regs[] = {
   2166         IDB_OBM0_THRESHOLD_1r, IDB_OBM1_THRESHOLD_1r,
   2167         IDB_OBM2_THRESHOLD_1r, IDB_OBM3_THRESHOLD_1r,
   2168         IDB_OBM4_THRESHOLD_1r, IDB_OBM5_THRESHOLD_1r,
   2169         IDB_OBM6_THRESHOLD_1r, IDB_OBM7_THRESHOLD_1r,
   2170         IDB_OBM8_THRESHOLD_1r, IDB_OBM9_THRESHOLD_1r,
   2171         IDB_OBM10_THRESHOLD_1r, IDB_OBM11_THRESHOLD_1r,
   2172         IDB_OBM12_THRESHOLD_1r, IDB_OBM13_THRESHOLD_1r,
   2173         IDB_OBM14_THRESHOLD_1r, IDB_OBM15_THRESHOLD_1r
   2174     };
   2175     static const soc_reg_t obm_fc_thresh_regs[] = {
   2176         IDB_OBM0_FC_THRESHOLDr, IDB_OBM1_FC_THRESHOLDr,
   2177         IDB_OBM2_FC_THRESHOLDr, IDB_OBM3_FC_THRESHOLDr,
   2178         IDB_OBM4_FC_THRESHOLDr, IDB_OBM5_FC_THRESHOLDr,
   2179         IDB_OBM6_FC_THRESHOLDr, IDB_OBM7_FC_THRESHOLDr,
   2180         IDB_OBM8_FC_THRESHOLDr, IDB_OBM9_FC_THRESHOLDr,
   2181         IDB_OBM10_FC_THRESHOLDr, IDB_OBM11_FC_THRESHOLDr,
   2182         IDB_OBM12_FC_THRESHOLDr, IDB_OBM13_FC_THRESHOLDr,
   2183         IDB_OBM14_FC_THRESHOLDr, IDB_OBM15_FC_THRESHOLDr
   2184     };
   2185     static const soc_reg_t obm_fc_thresh_1_regs[] = {
   2186         IDB_OBM0_FC_THRESHOLD_1r, IDB_OBM1_FC_THRESHOLD_1r,
   2187         IDB_OBM2_FC_THRESHOLD_1r, IDB_OBM3_FC_THRESHOLD_1r,
   2188         IDB_OBM4_FC_THRESHOLD_1r, IDB_OBM5_FC_THRESHOLD_1r,
   2189         IDB_OBM6_FC_THRESHOLD_1r, IDB_OBM7_FC_THRESHOLD_1r,
   2190         IDB_OBM8_FC_THRESHOLD_1r, IDB_OBM9_FC_THRESHOLD_1r,
   2191         IDB_OBM10_FC_THRESHOLD_1r, IDB_OBM11_FC_THRESHOLD_1r,
   2192         IDB_OBM12_FC_THRESHOLD_1r, IDB_OBM13_FC_THRESHOLD_1r,
   2193         IDB_OBM14_FC_THRESHOLD_1r, IDB_OBM15_FC_THRESHOLD_1r
   2194     };
   2195     static const soc_reg_t obm_shared_regs[] = {
   2196         IDB_OBM0_SHARED_CONFIGr, IDB_OBM1_SHARED_CONFIGr,
   2197         IDB_OBM2_SHARED_CONFIGr, IDB_OBM3_SHARED_CONFIGr,
   2198         IDB_OBM4_SHARED_CONFIGr, IDB_OBM5_SHARED_CONFIGr,
   2199         IDB_OBM6_SHARED_CONFIGr, IDB_OBM7_SHARED_CONFIGr,
   2200         IDB_OBM8_SHARED_CONFIGr, IDB_OBM9_SHARED_CONFIGr,
   2201         IDB_OBM10_SHARED_CONFIGr, IDB_OBM11_SHARED_CONFIGr,
   2202         IDB_OBM12_SHARED_CONFIGr, IDB_OBM13_SHARED_CONFIGr,
   2203         IDB_OBM14_SHARED_CONFIGr, IDB_OBM15_SHARED_CONFIGr
   2204     };
   2205     static const soc_reg_t obm_max_usage_regs[] = {
   2206         IDB_OBM0_MAX_USAGE_SELECTr, IDB_OBM1_MAX_USAGE_SELECTr,
   2207         IDB_OBM2_MAX_USAGE_SELECTr, IDB_OBM3_MAX_USAGE_SELECTr,
   2208         IDB_OBM4_MAX_USAGE_SELECTr, IDB_OBM5_MAX_USAGE_SELECTr,
   2209         IDB_OBM6_MAX_USAGE_SELECTr, IDB_OBM7_MAX_USAGE_SELECTr,
   2210         IDB_OBM8_MAX_USAGE_SELECTr, IDB_OBM9_MAX_USAGE_SELECTr,
   2211         IDB_OBM10_MAX_USAGE_SELECTr, IDB_OBM11_MAX_USAGE_SELECTr,
   2212         IDB_OBM12_MAX_USAGE_SELECTr, IDB_OBM13_MAX_USAGE_SELECTr,
   2213         IDB_OBM14_MAX_USAGE_SELECTr, IDB_OBM15_MAX_USAGE_SELECTr
   2214     };
   2215     static const soc_field_t obm_bypass_fields[] = {
   2216         PORT0_BYPASS_ENABLEf, PORT1_BYPASS_ENABLEf,
   2217         PORT2_BYPASS_ENABLEf, PORT3_BYPASS_ENABLEf
   2218     };
   2219     static const soc_field_t obm_oversub_fields[] = {
   2220         PORT0_OVERSUB_ENABLEf, PORT1_OVERSUB_ENABLEf,
   2221         PORT2_OVERSUB_ENABLEf, PORT3_OVERSUB_ENABLEf
   2222     };
   2223     static const soc_field_t obm_ca_sop_fields[] = {
   2224         PORT0_CA_SOPf, PORT1_CA_SOPf, PORT2_CA_SOPf, PORT3_CA_SOPf
   2225     };
   2226     static const soc_reg_t obm_port_config_regs[] = {
   2227         IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr,
   2228         IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr,
   2229         IDB_OBM4_PORT_CONFIGr, IDB_OBM5_PORT_CONFIGr,
   2230         IDB_OBM6_PORT_CONFIGr, IDB_OBM7_PORT_CONFIGr,
   2231         IDB_OBM8_PORT_CONFIGr, IDB_OBM9_PORT_CONFIGr,
   2232         IDB_OBM10_PORT_CONFIGr, IDB_OBM11_PORT_CONFIGr,
   2233         IDB_OBM12_PORT_CONFIGr, IDB_OBM13_PORT_CONFIGr,
   2234         IDB_OBM14_PORT_CONFIGr, IDB_OBM15_PORT_CONFIGr
   2235     };
   2236     static const soc_reg_t obm_fc_config_regs[] = {
   2237         IDB_OBM0_FLOW_CONTROL_CONFIGr, IDB_OBM1_FLOW_CONTROL_CONFIGr,
   2238         IDB_OBM2_FLOW_CONTROL_CONFIGr, IDB_OBM3_FLOW_CONTROL_CONFIGr,
   2239         IDB_OBM4_FLOW_CONTROL_CONFIGr, IDB_OBM5_FLOW_CONTROL_CONFIGr,
   2240         IDB_OBM6_FLOW_CONTROL_CONFIGr, IDB_OBM7_FLOW_CONTROL_CONFIGr,
   2241         IDB_OBM8_FLOW_CONTROL_CONFIGr, IDB_OBM9_FLOW_CONTROL_CONFIGr,
   2242         IDB_OBM10_FLOW_CONTROL_CONFIGr, IDB_OBM11_FLOW_CONTROL_CONFIGr,
   2243         IDB_OBM12_FLOW_CONTROL_CONFIGr, IDB_OBM13_FLOW_CONTROL_CONFIGr,
   2244         IDB_OBM14_FLOW_CONTROL_CONFIGr, IDB_OBM15_FLOW_CONTROL_CONFIGr
   2245     };
   2246     static const soc_reg_t obm_buffer_config_regs[] = {
   2247         IDB_OBM0_BUFFER_CONFIGr, IDB_OBM1_BUFFER_CONFIGr,
   2248         IDB_OBM2_BUFFER_CONFIGr, IDB_OBM3_BUFFER_CONFIGr,
   2249         IDB_OBM4_BUFFER_CONFIGr, IDB_OBM5_BUFFER_CONFIGr,
   2250         IDB_OBM6_BUFFER_CONFIGr, IDB_OBM7_BUFFER_CONFIGr,
   2251         IDB_OBM8_BUFFER_CONFIGr, IDB_OBM9_BUFFER_CONFIGr,
   2252         IDB_OBM10_BUFFER_CONFIGr, IDB_OBM11_BUFFER_CONFIGr,
   2253         IDB_OBM12_BUFFER_CONFIGr, IDB_OBM13_BUFFER_CONFIGr,
   2254         IDB_OBM14_BUFFER_CONFIGr, IDB_OBM15_BUFFER_CONFIGr
   2255     };
   2256     static const soc_mem_t obm_pri_map_mem[][4] = {
   2257         {IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m,
   2258          IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m
   2259         },
   2260         {IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m,
   2261          IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m
   2262         },
   2263         {IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m,
   2264          IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m
   2265         },
   2266         {IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m,
   2267          IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m
   2268         },
   2269         {IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m,
   2270          IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m
   2271         },
   2272         {IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m,
   2273          IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m
   2274         },
   2275         {IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m,
   2276          IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m
   2277         },
   2278         {IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m,
   2279          IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m
   2280         },
   2281         {IDB_OBM8_PRI_MAP_PORT0m, IDB_OBM8_PRI_MAP_PORT1m,
   2282          IDB_OBM8_PRI_MAP_PORT2m, IDB_OBM8_PRI_MAP_PORT3m
   2283         },
   2284         {IDB_OBM9_PRI_MAP_PORT0m, IDB_OBM9_PRI_MAP_PORT1m,
   2285          IDB_OBM9_PRI_MAP_PORT2m, IDB_OBM9_PRI_MAP_PORT3m
   2286         },
   2287         {IDB_OBM10_PRI_MAP_PORT0m, IDB_OBM10_PRI_MAP_PORT1m,
   2288          IDB_OBM10_PRI_MAP_PORT2m, IDB_OBM10_PRI_MAP_PORT3m
   2289         },
   2290         {IDB_OBM11_PRI_MAP_PORT0m, IDB_OBM11_PRI_MAP_PORT1m,
   2291          IDB_OBM11_PRI_MAP_PORT2m, IDB_OBM11_PRI_MAP_PORT3m
   2292         },
   2293         {IDB_OBM12_PRI_MAP_PORT0m, IDB_OBM12_PRI_MAP_PORT1m,
   2294          IDB_OBM12_PRI_MAP_PORT2m, IDB_OBM12_PRI_MAP_PORT3m
   2295         },
   2296         {IDB_OBM13_PRI_MAP_PORT0m, IDB_OBM13_PRI_MAP_PORT1m,
   2297          IDB_OBM13_PRI_MAP_PORT2m, IDB_OBM13_PRI_MAP_PORT3m
   2298         },
   2299         {IDB_OBM14_PRI_MAP_PORT0m, IDB_OBM14_PRI_MAP_PORT1m,
   2300          IDB_OBM14_PRI_MAP_PORT2m, IDB_OBM14_PRI_MAP_PORT3m
   2301         },
   2302         {IDB_OBM15_PRI_MAP_PORT0m, IDB_OBM15_PRI_MAP_PORT1m,
   2303          IDB_OBM15_PRI_MAP_PORT2m, IDB_OBM15_PRI_MAP_PORT3m
   2304         },
   2305     };
   2306 
   2307     static const soc_field_t obm_ob_pri_fields[] = {
   2308         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf,
   2309         OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
   2310         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf,
   2311         OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf,
   2312         OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf,
   2313         OFFSET15_OB_PRIORITYf
   2314     };
   2315     static const int hw_mode_values[SOC_TD3_PORT_RATIO_COUNT] = {
   2316         0, 1, 1, 1, 3, 5, 4, 6, 2
   2317     };
   2318 
   2319     si = &SOC_INFO(unit);
   2320     tdm = SOC_CONTROL(unit)->tdm_info;
   2321     lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 0);
   2322 
   2323     rval_port_cfg = 0;
   2324     reg = SOC_REG_UNIQUE_ACC(unit, obm_port_config_regs[0])[0];
   2325     soc_reg_field_set(unit, reg, &rval_port_cfg, PORT_PRIf, 2);
   2326 
   2327     rval_max_usage_cfg = 0;
   2328     reg = SOC_REG_UNIQUE_ACC(unit, obm_max_usage_regs[0])[0];
   2329     soc_reg_field_set(unit, reg, &rval_max_usage_cfg, PRIORITY_SELECTf, 2);
   2330 
   2331     sal_memset(entry, 0, sizeof(idb_obm0_pri_map_port0_entry_t));
   2332     mem = SOC_MEM_UNIQUE_ACC(unit, obm_pri_map_mem[0][0])[0];
   2333 
   2334     count = COUNTOF(obm_ob_pri_fields);
   2335     for (i = 0; i < count; i++) {
   2336         soc_mem_field32_set(unit, mem, entry, obm_ob_pri_fields[i], 2);
   2337     }
   2338 
   2339     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   2340         port = SOC_BLOCK_PORT(unit, block_info_idx);
   2341         phy_port_base = PORT_BLOCK_BASE_PORT(port);
   2342         pipe = si->port_pipe[port];
   2343         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   2344         obm = clport & 0xF;
   2345 
   2346         /* Set cell assembly mode then toggle reset to send initial credit
   2347          * to EP */
   2348         reg = SOC_REG_UNIQUE_ACC(unit, obm_ca_ctrl_regs[obm])[pipe];
   2349         rval0 = 0;
   2350         soc_reg_field_set(unit, reg, &rval0, PORT_MODEf,
   2351                           hw_mode_values[tdm->port_ratio[clport]]);
   2352 
   2353         rval1 = rval0;
   2354         /* PORT_RESETf is a 4 bit field, set to all one's in the next step */
   2355         soc_reg_field_set(unit, reg, &rval0, PORT0_RESETf, 1);
   2356         soc_reg_field_set(unit, reg, &rval0, PORT1_RESETf, 1);
   2357         soc_reg_field_set(unit, reg, &rval0, PORT2_RESETf, 1);
   2358         soc_reg_field_set(unit, reg, &rval0, PORT3_RESETf, 1);
   2359         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   2360         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval1));
   2361 
   2362         if (!SOC_PBMP_MEMBER(si->oversub_pbm, port)) {
   2363             continue;
   2364         }
   2365 
   2366         /* Enable oversub */
   2367         reg = SOC_REG_UNIQUE_ACC(unit, obm_ctrl_regs[obm])[pipe];
   2368         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval0));
   2369         for (lane = 0; lane < _TD3_PORTS_PER_PBLK; lane++) {
   2370             if (si->port_p2l_mapping[phy_port_base + lane] == -1) {
   2371                 continue;
   2372             }
   2373             field = obm_bypass_fields[lane];
   2374             soc_reg_field_set(unit, reg, &rval0, field, 1);
   2375             field = obm_oversub_fields[lane];
   2376             soc_reg_field_set(unit, reg, &rval0, field, 1);
   2377             lport = si->port_p2l_mapping[phy_port_base + lane];
   2378             /* Update CA_SOP settings */
   2379             if (si->port_speed_max[lport] < 100000) {
   2380                 field = obm_ca_sop_fields[lane];
   2381                 soc_reg_field_set(unit, reg, &rval0, field, 0);
   2382             }
   2383         }
   2384 
   2385         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   2386         if (!SOC_PBMP_MEMBER(si->oversub_pbm, port)) {
   2387             continue;
   2388         }
   2389 
   2390         /* Configure buffer */
   2391         for (lane = 0; lane < _TD3_PORTS_PER_PBLK; lane++) {
   2392             port = si->port_p2l_mapping[phy_port_base + lane];
   2393             if (port == -1) {
   2394                 continue;
   2395             }
   2396             num_lanes = si->port_num_lanes[port];
   2397             reg = SOC_REG_UNIQUE_ACC(unit, obm_buffer_config_regs[obm])[pipe];
   2398             SOC_IF_ERROR_RETURN
   2399                 (soc_reg32_get(unit, reg, REG_PORT_ANY, lane, &rval0));
   2400             fval = obm_settings[num_lanes].buffer_start[lane];
   2401             soc_reg_field_set(unit, reg, &rval0, BUFFER_STARTf, fval);
   2402             fval = obm_settings[num_lanes].buffer_end[lane];
   2403             soc_reg_field_set(unit, reg, &rval0, BUFFER_ENDf, fval);
   2404             SOC_IF_ERROR_RETURN
   2405                 (soc_reg32_set(unit, reg, REG_PORT_ANY, lane, rval0));
   2406         }
   2407 
   2408         /* Configure shared config */
   2409         reg = SOC_REG_UNIQUE_ACC(unit, obm_shared_regs[obm])[pipe];
   2410         SOC_IF_ERROR_RETURN
   2411             (soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval64));
   2412         soc_reg64_field32_set(unit, reg, &rval64, SOP_DISCARD_MODEf, 1);
   2413         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval64));
   2414 
   2415         if (lossless) {
   2416             if ((tdm->ovs_ratio_x1000[pipe][0] + tdm->ovs_ratio_x1000[pipe][1]) >= 1800) { /* ratio >= 1.8 */
   2417                 oversub_ratio_idx = 2;
   2418             } else if ((tdm->ovs_ratio_x1000[pipe][0] + tdm->ovs_ratio_x1000[pipe][1]) >= 1500) { /* ratio >= 1.5 */
   2419                 oversub_ratio_idx = 1;
   2420             } else {
   2421                 oversub_ratio_idx = 0;
   2422             }
   2423 
   2424             for (lane = 0; lane < _TD3_PORTS_PER_PBLK; lane++) {
   2425                 port = si->port_p2l_mapping[phy_port_base + lane];
   2426                 if (port == -1) {
   2427                     continue;
   2428                 }
   2429                 num_lanes = si->port_num_lanes[port];
   2430 
   2431                 /* Configure threshold */
   2432                 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe];
   2433                 SOC_IF_ERROR_RETURN
   2434                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   2435                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf,
   2436                                       4604);
   2437                 fval = obm_settings[num_lanes].lossy_low_pri[oversub_ratio_idx];
   2438                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf, fval);
   2439                 fval = obm_settings[num_lanes].lossy_discard[oversub_ratio_idx];
   2440                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf, fval);
   2441                 SOC_IF_ERROR_RETURN
   2442                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   2443 
   2444                 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_1_regs[obm])[pipe];
   2445                 SOC_IF_ERROR_RETURN
   2446                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   2447                 fval = obm_settings[num_lanes].discard_limit;
   2448                 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf, fval);
   2449                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf,
   2450                                       4604);
   2451                 SOC_IF_ERROR_RETURN
   2452                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   2453 
   2454                 /* Configure flow control threshold */
   2455                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe];
   2456                 SOC_IF_ERROR_RETURN
   2457                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   2458                 fval = obm_settings[num_lanes].lossless_xoff;
   2459                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf,
   2460                                       fval);
   2461                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf,
   2462                                       fval - 30);
   2463                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf, fval);
   2464                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf,
   2465                                       fval - 30);
   2466                 SOC_IF_ERROR_RETURN
   2467                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   2468 
   2469                 /* Configure flow control threshold_1 */
   2470                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_1_regs[obm])[pipe];
   2471                 SOC_IF_ERROR_RETURN
   2472                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   2473                 fval = obm_settings[num_lanes].port_xoff[oversub_ratio_idx];
   2474                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf, fval);
   2475                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf, fval - 30);
   2476                 SOC_IF_ERROR_RETURN
   2477                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   2478 
   2479                 /* Configure flow control config */
   2480                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_config_regs[obm])[pipe];
   2481                 SOC_IF_ERROR_RETURN
   2482                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   2483                 soc_reg64_field32_set(unit, reg, &rval64, PORT_FC_ENf, 1);
   2484                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_FC_ENf, 1);
   2485                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_FC_ENf, 0);
   2486                 soc_reg64_field32_set(unit, reg, &rval64,
   2487                                       LOSSLESS0_PRIORITY_PROFILEf, 0xffff);
   2488                 soc_reg64_field32_set(unit, reg, &rval64,
   2489                                       LOSSLESS1_PRIORITY_PROFILEf, 0);
   2490                 soc_reg64_field32_set(unit, reg, &rval64,
   2491                                       XOFF_REFRESH_TIMERf, 0x100);
   2492                 SOC_IF_ERROR_RETURN
   2493                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   2494 
   2495                 /* OBM Port config */
   2496                 reg = SOC_REG_UNIQUE_ACC(unit, obm_port_config_regs[obm])[pipe];
   2497                 SOC_IF_ERROR_RETURN
   2498                     (soc_reg32_set(unit, reg, REG_PORT_ANY, lane,
   2499                                    rval_port_cfg));
   2500                 mem = SOC_MEM_UNIQUE_ACC
   2501                         (unit, obm_pri_map_mem[obm][lane])[pipe];
   2502                 SOC_IF_ERROR_RETURN
   2503                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, entry));
   2504             }
   2505             reg = SOC_REG_UNIQUE_ACC(unit, obm_max_usage_regs[obm])[pipe];
   2506             SOC_IF_ERROR_RETURN
   2507                 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval_max_usage_cfg));
   2508         } else { /* lossy */
   2509             for (lane = 0; lane < _TD3_PORTS_PER_PBLK; lane++) {
   2510                 port = si->port_p2l_mapping[phy_port_base + lane];
   2511                 if (port == -1) {
   2512                     continue;
   2513                 }
   2514                 num_lanes = si->port_num_lanes[port];
   2515 
   2516                 /* Configure threshold */
   2517                 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe];
   2518                 SOC_IF_ERROR_RETURN
   2519                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   2520                 fval = obm_settings[num_lanes].discard_limit;
   2521                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf,
   2522                                       fval - 4);
   2523                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf,
   2524                                       4604);
   2525                 fval = obm_settings[num_lanes].lossy_only_lossy_low_pri;
   2526                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf, fval);
   2527                 SOC_IF_ERROR_RETURN
   2528                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   2529 
   2530                 /* Configure threshold_1 */
   2531                 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_1_regs[obm])[pipe];
   2532                 SOC_IF_ERROR_RETURN
   2533                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   2534                 fval = obm_settings[num_lanes].discard_limit;
   2535                 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf, fval);
   2536                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf,
   2537                                       4604);
   2538                 SOC_IF_ERROR_RETURN
   2539                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   2540 
   2541                 /* Configure flow control threshold */
   2542                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_1_regs[obm])[pipe];
   2543                 SOC_IF_ERROR_RETURN
   2544                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   2545                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf, 4604);
   2546                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf, 4604);
   2547                 SOC_IF_ERROR_RETURN
   2548                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   2549 
   2550                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe];
   2551                 SOC_IF_ERROR_RETURN
   2552                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   2553                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf,
   2554                                       4604);
   2555                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf, 4604);
   2556                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf, 4604);
   2557                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf,
   2558                                       4604);
   2559                 SOC_IF_ERROR_RETURN
   2560                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   2561 
   2562                 /* Configure flow control config */
   2563                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_config_regs[obm])[pipe];
   2564                 SOC_IF_ERROR_RETURN
   2565                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   2566                 soc_reg64_field32_set(unit, reg, &rval64,
   2567                                       XOFF_REFRESH_TIMERf, 0x100);
   2568                 SOC_IF_ERROR_RETURN
   2569                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   2570             }
   2571         }
   2572     }
   2573 
   2574     /* Toggle cpu port cell assembly reset to send initial credit to EP */
   2575     reg = IDB_CA_CPU_CONTROLr;
   2576     rval0 = 0;
   2577     soc_reg_field_set(unit, reg, &rval0, PORT_RESETf, 1);
   2578     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   2579     sal_msleep(5);
   2580     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 0));
   2581 
   2582     /* Toggle loopback cell assembly reset to send initial credit to EP */
   2583     reg = IDB_CA_LPBK_CONTROLr;
   2584     rval0 = 0;
   2585     soc_reg_field_set(unit, reg, &rval0, PORT_RESETf, 1);
   2586     PBMP_LB_ITER(unit, port) {
   2587         reg = SOC_REG_UNIQUE_ACC(unit, IDB_CA_LPBK_CONTROLr)
   2588                                             [si->port_pipe[port]] ;
   2589         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   2590         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 0));
   2591     }
   2592 
   2593     soc_td3_set_idb_dpp_ctrl(unit);
   2594 
   2595     return SOC_E_NONE;
   2596 }
   2597 #ifdef BCM_WARM_BOOT_SUPPORT
   2598 
   2599 #define SOC_TDM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
   2600 #define SOC_TDM_WB_DEFAULT_VERSION            SOC_TDM_WB_VERSION_1_0
   2601 
   2602 int soc_td3_tdm_scache_allocate(int unit)
   2603 {
   2604     int rv = SOC_E_NONE;
   2605     uint8 *tdm_scache_ptr;
   2606     soc_scache_handle_t scache_handle;
   2607     uint32 alloc_get = 0;
   2608     uint32 alloc_size = 0;
   2609     int stable_size;
   2610     int default_ver = SOC_TDM_WB_DEFAULT_VERSION;
   2611     int ilen, ovs_size, pkt_shp_size, hpipes;
   2612 
   2613     ilen = sizeof(int);
   2614     ovs_size = TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE *
   2615                TRIDENT3_OVS_GROUP_COUNT_PER_HPIPE *
   2616                TRIDENT3_OVS_GROUP_TDM_LENGTH;
   2617     pkt_shp_size = TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE *
   2618                    TRIDENT3_PKT_SCH_LENGTH;
   2619     hpipes = TRIDENT3_PIPES_PER_DEV * TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE;
   2620 
   2621     alloc_size = (ilen * TRIDENT3_TDM_LENGTH) + /* IDB TDM info on pipe0 */
   2622                  (ilen * TRIDENT3_TDM_LENGTH) + /* MMU TDM info on pipe0 */
   2623                  (ilen * ovs_size)     + /* Oversub group info on pipe0 */
   2624                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe0     */
   2625                  (ilen * TRIDENT3_TDM_LENGTH) + /* IDB TDM info on pipe1 */
   2626                  (ilen * TRIDENT3_TDM_LENGTH) + /* MMU TDM info on pipe1 */
   2627                  (ilen * ovs_size)     + /* Oversub group info on pipe1 */
   2628                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe1     */
   2629                  (ilen * TRIDENT3_PHY_PORTS_PER_DEV) + /* hpipe id of phy-port */
   2630                  (ilen * TRIDENT3_PHY_PORTS_PER_DEV) + /* pblk id of phy-port */
   2631                  (ilen * TRIDENT3_PBLKS_PER_DEV)     + /* port ratio */
   2632                  (ilen * hpipes);                  /* oversub ratio */
   2633     alloc_get = alloc_size;
   2634 
   2635     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_TDM_HANDLE, 0);
   2636     /* check to see if an scache table has been configured */
   2637     rv = soc_stable_size_get(unit, &stable_size);
   2638     if (SOC_FAILURE(rv) || stable_size <= 0) {
   2639         return rv;
   2640     }
   2641 
   2642     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
   2643                                       TRUE, &alloc_get,
   2644                                       &tdm_scache_ptr,
   2645                                       default_ver,
   2646                                       NULL);
   2647 
   2648     if (rv  == SOC_E_CONFIG) {
   2649         /* Probably Level1 */
   2650         return SOC_E_NONE;
   2651     }
   2652     /* NotRequired but just to confirm Get the pointer for the Level 2 cache */
   2653     if (alloc_get != alloc_size) {
   2654         /* Expected size doesn't match retrieved size */
   2655         LOG_ERROR(BSL_LS_SOC_COMMON,
   2656                   (BSL_META_U(unit,
   2657                   "ERROR: scache memory for tdm size mismatch"
   2658                   "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   2659         return SOC_E_INTERNAL;
   2660     }
   2661 
   2662     if (NULL == tdm_scache_ptr) {
   2663         LOG_ERROR(BSL_LS_SOC_COMMON,
   2664                   (BSL_META_U(unit,
   2665                   "ERROR: scache memory not allocated for tdm"
   2666                   "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   2667         return SOC_E_MEMORY;
   2668     }
   2669     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2670                 (BSL_META_U(unit,
   2671                 "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   2672     return SOC_E_NONE;
   2673 }
   2674 
   2675 
   2676 /*
   2677  * Function:
   2678  *      soc_td3_tdm_scache_sync
   2679  * Purpose:
   2680  *      Record TDM info that maybe changed during flexport for Level 2 WB
   2681  *
   2682  * Warm Boot Version Map:
   2683  *
   2684  *  BCM_WB_VERSION_1_0
   2685  *    IDB TDM info on pipe0
   2686  *    MMU TDM info on pipe0
   2687  *    Oversub group info on pipe0
   2688  *    pkt shaper info on pipe0
   2689  *    IDB TDM info on pipe1
   2690  *    MMU TDM info on pipe1
   2691  *    Oversub group info on pipe1
   2692  *    pkt shaper info on pipe1
   2693  *    pblk id of phy-port
   2694  *    port ratio
   2695  *    oversub ratio
   2696  *
   2697  * Parameters:
   2698  *      unit - StrataSwitch unit number.
   2699  * Returns:
   2700  *      SOC_E_XXX
   2701  */
   2702 int soc_td3_tdm_scache_sync(int unit)
   2703 {
   2704     uint8 *tdm_scache_ptr;
   2705     soc_scache_handle_t scache_handle;
   2706     uint32 alloc_get = 0;
   2707     uint32 alloc_size = 0;
   2708     uint32 var_size = 0;
   2709     uint32 scache_offset=0;
   2710     int rv = 0;
   2711     int ilen, ovs_size, pkt_shp_size, hpipes, phy_port;
   2712     _soc_trident3_tdm_temp_t  *tdm = SOC_CONTROL(unit)->tdm_info;
   2713 
   2714     ilen = sizeof(int);
   2715     ovs_size = TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE *
   2716                TRIDENT3_OVS_GROUP_COUNT_PER_HPIPE *
   2717                TRIDENT3_OVS_GROUP_TDM_LENGTH;
   2718     pkt_shp_size = TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE *
   2719                    TRIDENT3_PKT_SCH_LENGTH;
   2720     hpipes = TRIDENT3_PIPES_PER_DEV * TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE;
   2721 
   2722     alloc_size = (ilen * TRIDENT3_TDM_LENGTH) + /* IDB TDM info on pipe0 */
   2723                  (ilen * TRIDENT3_TDM_LENGTH) + /* MMU TDM info on pipe0 */
   2724                  (ilen * ovs_size)     + /* Oversub group info on pipe0 */
   2725                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe0     */
   2726                  (ilen * TRIDENT3_TDM_LENGTH) + /* IDB TDM info on pipe1 */
   2727                  (ilen * TRIDENT3_TDM_LENGTH) + /* MMU TDM info on pipe1 */
   2728                  (ilen * ovs_size)     + /* Oversub group info on pipe1 */
   2729                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe1     */
   2730                  (ilen * TRIDENT3_PHY_PORTS_PER_DEV) + /* hpipe id of phy-port */
   2731                  (ilen * TRIDENT3_PHY_PORTS_PER_DEV) + /* pblk id of phy-port */
   2732                  (ilen * TRIDENT3_PBLKS_PER_DEV)     + /* port ratio */
   2733                  (ilen * hpipes);                  /* oversub ratio */
   2734     alloc_get = alloc_size;
   2735 
   2736     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_TDM_HANDLE, 0);
   2737     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
   2738                                       FALSE, &alloc_get,
   2739                                       &tdm_scache_ptr,
   2740                                       SOC_TDM_WB_DEFAULT_VERSION,
   2741                                       NULL);
   2742     if (rv == SOC_E_NOT_FOUND) {
   2743         /* Probably Level1 */
   2744         return SOC_E_NONE;
   2745     }
   2746     if (alloc_get != alloc_size) {
   2747         /* Expected size doesn't match retrieved size */
   2748         LOG_ERROR(BSL_LS_SOC_COMMON,
   2749                   (BSL_META_U(unit,
   2750                   "ERROR: scache memory for tdm size mismatch"
   2751                   "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   2752         return SOC_E_INTERNAL;
   2753     }
   2754     if (NULL == tdm_scache_ptr) {
   2755         LOG_ERROR(BSL_LS_SOC_COMMON,
   2756                   (BSL_META_U(unit,
   2757                   "ERROR: scache memory not allocated for tdm"
   2758                   "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
   2759         return SOC_E_MEMORY;
   2760     }
   2761 
   2762     /* IDB TDM info on pipe0 */
   2763     var_size = ilen * TRIDENT3_TDM_LENGTH;
   2764     sal_memcpy(&tdm_scache_ptr[scache_offset],
   2765                tdm->tdm_pipe[0].idb_tdm,
   2766                var_size);
   2767     scache_offset += var_size;
   2768 
   2769     /* MMU TDM info on pipe0 */
   2770     var_size = ilen * TRIDENT3_TDM_LENGTH;
   2771     sal_memcpy(&tdm_scache_ptr[scache_offset],
   2772                tdm->tdm_pipe[0].mmu_tdm,
   2773                var_size);
   2774     scache_offset += var_size;
   2775 
   2776     /* Oversub group info on pipe0 */
   2777     var_size = ilen * ovs_size;
   2778     sal_memcpy(&tdm_scache_ptr[scache_offset],
   2779                tdm->tdm_pipe[0].ovs_tdm,
   2780                var_size);
   2781     scache_offset += var_size;
   2782 
   2783     /* pkt shaper info on pipe0 */
   2784     var_size = ilen * pkt_shp_size;
   2785     sal_memcpy(&tdm_scache_ptr[scache_offset],
   2786                tdm->tdm_pipe[0].pkt_shaper_tdm,
   2787                var_size);
   2788     scache_offset += var_size;
   2789 
   2790     /* IDB TDM info on pipe1 */
   2791     var_size = ilen * TRIDENT3_TDM_LENGTH;
   2792     sal_memcpy(&tdm_scache_ptr[scache_offset],
   2793                tdm->tdm_pipe[1].idb_tdm,
   2794                var_size);
   2795     scache_offset += var_size;
   2796 
   2797     /* MMU TDM info on pipe1 */
   2798     var_size = ilen * TRIDENT3_TDM_LENGTH;
   2799     sal_memcpy(&tdm_scache_ptr[scache_offset],
   2800                tdm->tdm_pipe[1].mmu_tdm,
   2801                var_size);
   2802     scache_offset += var_size;
   2803 
   2804     /* Oversub group info on pipe1 */
   2805     var_size = ilen * ovs_size;
   2806     sal_memcpy(&tdm_scache_ptr[scache_offset],
   2807                tdm->tdm_pipe[1].ovs_tdm,
   2808                var_size);
   2809     scache_offset += var_size;
   2810 
   2811     /* pkt shaper info on pipe1 */
   2812     var_size = ilen * pkt_shp_size;
   2813     sal_memcpy(&tdm_scache_ptr[scache_offset],
   2814                tdm->tdm_pipe[1].pkt_shaper_tdm,
   2815                var_size);
   2816     scache_offset += var_size;
   2817 
   2818     /* hpipe id of phy-port */
   2819     for (phy_port = 0; phy_port < TRIDENT3_PHY_PORTS_PER_DEV; phy_port++) {
   2820         var_size = ilen;
   2821         sal_memcpy(&tdm_scache_ptr[scache_offset],
   2822                    &tdm->pblk_info[phy_port].pblk_hpipe_num,
   2823                    var_size);
   2824         scache_offset += var_size;
   2825     }
   2826 
   2827     /* pblk id of phy-port */
   2828     for (phy_port = 0; phy_port < TRIDENT3_PHY_PORTS_PER_DEV; phy_port++) {
   2829         var_size = ilen;
   2830         sal_memcpy(&tdm_scache_ptr[scache_offset],
   2831                    &tdm->pblk_info[phy_port].pblk_cal_idx,
   2832                    var_size);
   2833         scache_offset += var_size;
   2834     }
   2835 
   2836     /* port ratio */
   2837     var_size = ilen * TRIDENT3_PBLKS_PER_DEV;
   2838     sal_memcpy(&tdm_scache_ptr[scache_offset],
   2839                tdm->port_ratio,
   2840                var_size);
   2841     scache_offset += var_size;
   2842 
   2843     /* oversub ratio */
   2844     var_size = ilen * hpipes;
   2845     sal_memcpy(&tdm_scache_ptr[scache_offset],
   2846                tdm->ovs_ratio_x1000,
   2847                var_size);
   2848     scache_offset += var_size;
   2849 
   2850     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2851                 (BSL_META_U(unit,
   2852                 "%s()[LINE:%d] \n"),FUNCTION_NAME(),  __LINE__));
   2853 
   2854     return SOC_E_NONE;
   2855 }
   2856 
   2857 /*
   2858  * Function:
   2859  *      soc_td3_tdm_scache_recovery
   2860  * Purpose:
   2861  *      Recover TDM info that maybe changed during flexport for Level 2 WB
   2862  *
   2863  * Warm Boot Version Map:
   2864  *
   2865  *  BCM_WB_VERSION_1_0
   2866  *    IDB TDM info on pipe0
   2867  *    MMU TDM info on pipe0
   2868  *    Oversub group info on pipe0
   2869  *    pkt shaper info on pipe0
   2870  *    IDB TDM info on pipe1
   2871  *    MMU TDM info on pipe1
   2872  *    Oversub group info on pipe1
   2873  *    pkt shaper info on pipe1
   2874  *    hpipe id of phy-port
   2875  *    pblk id of phy-port
   2876  *    port ratio
   2877  *    oversub ratio
   2878  *
   2879  * Parameters:
   2880  *      unit - StrataSwitch unit number.
   2881  * Returns:
   2882  *      SOC_E_XXX
   2883  */
   2884 int soc_td3_tdm_scache_recovery(int unit)
   2885 {
   2886     uint32 alloc_get = 0;
   2887     uint32 alloc_size = 0;
   2888     int rv = SOC_E_NONE;
   2889     uint8 *tdm_scache_ptr = NULL;
   2890     soc_scache_handle_t scache_handle;
   2891     uint32 scache_offset=0;
   2892     uint32 var_size = 0;
   2893     uint16 recovered_ver = 0;
   2894     int ilen, ovs_size, pkt_shp_size, hpipes, phy_port;
   2895     _soc_trident3_tdm_temp_t *tdm = SOC_CONTROL(unit)->tdm_info;
   2896 
   2897     ilen = sizeof(int);
   2898     ovs_size = TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE *
   2899                TRIDENT3_OVS_GROUP_COUNT_PER_HPIPE *
   2900                TRIDENT3_OVS_GROUP_TDM_LENGTH;
   2901     pkt_shp_size = TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE *
   2902                    TRIDENT3_PKT_SCH_LENGTH;
   2903     hpipes = TRIDENT3_PIPES_PER_DEV * TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE;
   2904 
   2905     alloc_size = (ilen * TRIDENT3_TDM_LENGTH) + /* IDB TDM info on pipe0 */
   2906                  (ilen * TRIDENT3_TDM_LENGTH) + /* MMU TDM info on pipe0 */
   2907                  (ilen * ovs_size)     + /* Oversub group info on pipe0 */
   2908                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe0     */
   2909                  (ilen * TRIDENT3_TDM_LENGTH) + /* IDB TDM info on pipe1 */
   2910                  (ilen * TRIDENT3_TDM_LENGTH) + /* MMU TDM info on pipe1 */
   2911                  (ilen * ovs_size)     + /* Oversub group info on pipe1 */
   2912                  (ilen * pkt_shp_size)    + /* pkt shaper info on pipe1     */
   2913                  (ilen * TRIDENT3_PHY_PORTS_PER_DEV) + /* hpipe id of phy-port */
   2914                  (ilen * TRIDENT3_PHY_PORTS_PER_DEV) + /* pblk id of phy-port */
   2915                  (ilen * TRIDENT3_PBLKS_PER_DEV)     + /* port ratio */
   2916                  (ilen * hpipes);                  /* oversub ratio */
   2917     alloc_get = alloc_size;
   2918 
   2919     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_TDM_HANDLE, 0);
   2920     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
   2921                                       FALSE, &alloc_get,
   2922                                       &tdm_scache_ptr,
   2923                                       SOC_TDM_WB_DEFAULT_VERSION,
   2924                                       &recovered_ver);
   2925     if (SOC_FAILURE(rv)) {
   2926         if ((rv == SOC_E_CONFIG) ||
   2927             (rv == SOC_E_NOT_FOUND)) {
   2928             /* warmboot file does not contain this
   2929              * module, or the warmboot state does not exist.
   2930              * in this case return SOC_E_NOT_FOUND
   2931              */
   2932             return SOC_E_NOT_FOUND;
   2933         } else {
   2934             /* Only Level2 - flexport treat this as a error */
   2935             LOG_ERROR(BSL_LS_SOC_COMMON,
   2936                       (BSL_META_U(unit,
   2937                       "Failed to recover scache data - %s\n"),soc_errmsg(rv)));
   2938             return rv;
   2939         }
   2940     }
   2941     if (alloc_get != alloc_size) {
   2942         /* Expected size doesn't match retrieved size */
   2943         LOG_ERROR(BSL_LS_SOC_COMMON,
   2944                   (BSL_META_U(unit,
   2945                   "ERROR: scache recovery for tdm"
   2946                   "%s()[LINE:%d] DONE \n"),
   2947                   FUNCTION_NAME(),  __LINE__));
   2948         return SOC_E_INTERNAL;
   2949     }
   2950 
   2951     if (NULL == tdm_scache_ptr) {
   2952         LOG_ERROR(BSL_LS_SOC_COMMON,
   2953                   (BSL_META_U(unit,
   2954                   "ERROR: scache recovery for tdm"
   2955                   "%s()[LINE:%d] DONE \n"),
   2956                   FUNCTION_NAME(),  __LINE__));
   2957         return SOC_E_MEMORY;
   2958     }
   2959 
   2960     /* IDB TDM info on pipe0 */
   2961     var_size = ilen * TRIDENT3_TDM_LENGTH;
   2962     sal_memcpy(tdm->tdm_pipe[0].idb_tdm,
   2963                &tdm_scache_ptr[scache_offset],
   2964                var_size);
   2965     scache_offset += var_size;
   2966 
   2967     /* MMU TDM info on pipe0 */
   2968     var_size = ilen * TRIDENT3_TDM_LENGTH;
   2969     sal_memcpy(tdm->tdm_pipe[0].mmu_tdm,
   2970                &tdm_scache_ptr[scache_offset],
   2971                var_size);
   2972     scache_offset += var_size;
   2973 
   2974     /* Oversub group info on pipe0 */
   2975     var_size = ilen * ovs_size;
   2976     sal_memcpy(tdm->tdm_pipe[0].ovs_tdm,
   2977                &tdm_scache_ptr[scache_offset],
   2978                var_size);
   2979     scache_offset += var_size;
   2980 
   2981     /* pkt shaper info on pipe0 */
   2982     var_size = ilen * pkt_shp_size;
   2983     sal_memcpy(tdm->tdm_pipe[0].pkt_shaper_tdm,
   2984                &tdm_scache_ptr[scache_offset],
   2985                var_size);
   2986     scache_offset += var_size;
   2987 
   2988     /* IDB TDM info on pipe1 */
   2989     var_size = ilen * TRIDENT3_TDM_LENGTH;
   2990     sal_memcpy(tdm->tdm_pipe[1].idb_tdm,
   2991                &tdm_scache_ptr[scache_offset],
   2992                var_size);
   2993     scache_offset += var_size;
   2994 
   2995     /* MMU TDM info on pipe1 */
   2996     var_size = ilen * TRIDENT3_TDM_LENGTH;
   2997     sal_memcpy(tdm->tdm_pipe[1].mmu_tdm,
   2998                &tdm_scache_ptr[scache_offset],
   2999                var_size);
   3000     scache_offset += var_size;
   3001 
   3002     /* Oversub group info on pipe1 */
   3003     var_size = ilen * ovs_size;
   3004     sal_memcpy(tdm->tdm_pipe[1].ovs_tdm,
   3005                &tdm_scache_ptr[scache_offset],
   3006                var_size);
   3007     scache_offset += var_size;
   3008 
   3009     /* pkt shaper info on pipe1 */
   3010     var_size = ilen * pkt_shp_size;
   3011     sal_memcpy(tdm->tdm_pipe[1].pkt_shaper_tdm,
   3012                &tdm_scache_ptr[scache_offset],
   3013                var_size);
   3014     scache_offset += var_size;
   3015 
   3016     /* hpipe id of phy-port */
   3017     for (phy_port = 0; phy_port < TRIDENT3_PHY_PORTS_PER_DEV; phy_port++) {
   3018         var_size = ilen;
   3019         sal_memcpy(&tdm->pblk_info[phy_port].pblk_hpipe_num,
   3020                    &tdm_scache_ptr[scache_offset],
   3021                    var_size);
   3022         scache_offset += var_size;
   3023     }
   3024 
   3025     /* pblk id of phy-port */
   3026     for (phy_port = 0; phy_port < TRIDENT3_PHY_PORTS_PER_DEV; phy_port++) {
   3027         var_size = ilen;
   3028         sal_memcpy(&tdm->pblk_info[phy_port].pblk_cal_idx,
   3029                    &tdm_scache_ptr[scache_offset],
   3030                    var_size);
   3031         scache_offset += var_size;
   3032     }
   3033 
   3034     /* port ratio */
   3035     var_size = ilen * TRIDENT3_PBLKS_PER_DEV;
   3036     sal_memcpy(tdm->port_ratio,
   3037                &tdm_scache_ptr[scache_offset],
   3038                var_size);
   3039     scache_offset += var_size;
   3040 
   3041     /* oversub ratio */
   3042     var_size = ilen * hpipes;
   3043     sal_memcpy(tdm->ovs_ratio_x1000,
   3044                &tdm_scache_ptr[scache_offset],
   3045                var_size);
   3046     scache_offset += var_size;
   3047 
   3048     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3049                 (BSL_META_U(unit,
   3050                 "%s()[LINE:%d] \n"),FUNCTION_NAME(),  __LINE__));
   3051 
   3052     return SOC_E_NONE;
   3053 }
   3054 #endif /* BCM_WARM_BOOT_SUPPORT */
   3055 
   3056 #define TD3_UFT_HASH_OFFSET_MAX     51
   3057 #define TD3_EUAT_HASH_OFFSET_MAX    53
   3058 #define TD3_UAT_8K_HASH_OFFSET_MAX  53
   3059 #define TD3_UAT_16K_HASH_OFFSET_MAX 52
   3060 
   3061 int
   3062 soc_trident3_uft_uat_config(int unit) {
   3063     int index, shared_bank_offset = 2;
   3064     int num_l2_banks, num_l3_banks, num_fpem_banks = 0;
   3065     int dedicated_banks = 2;
   3066     int num_entries, shared_hash_offset;
   3067     int uat_16k_banks = 0, uat_8k_banks = 0;
   3068     int mpls_16k_banks, mpls_8k_banks;
   3069     int vlan_xlate_1_16k_banks, vlan_xlate_1_8k_banks;
   3070     int vlan_xlate_2_16k_banks, vlan_xlate_2_8k_banks;
   3071     int egr_vlan_xlate_1_banks, egr_vlan_xlate_2_banks;
   3072     int m, mem_sz;
   3073     uint32 hash_control_entry[4], shared_hash_control_entry[4],
   3074     shared_8k_hash_control_entry[4];
   3075     soc_mem_t dedicated_bank_mems[] = {
   3076         ING_DNAT_ADDRESS_TYPE_HASH_CONTROLm,
   3077         EGR_VP_VLAN_MEMBERSHIP_HASH_CONTROLm,
   3078         ING_VP_VLAN_MEMBERSHIP_HASH_CONTROLm,
   3079         SUBPORT_ID_TO_SGPP_MAP_HASH_CONTROLm
   3080     };
   3081 
   3082     static const soc_field_t logical_to_physical_fields[] = {
   3083         LOGICAL_BANK_0_PHYSICAL_BANK_LOCATIONf,
   3084         LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf,
   3085         LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf,
   3086         LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf,
   3087         LOGICAL_BANK_4_PHYSICAL_BANK_LOCATIONf,
   3088         LOGICAL_BANK_5_PHYSICAL_BANK_LOCATIONf,
   3089         LOGICAL_BANK_6_PHYSICAL_BANK_LOCATIONf,
   3090         LOGICAL_BANK_7_PHYSICAL_BANK_LOCATIONf,
   3091         LOGICAL_BANK_8_PHYSICAL_BANK_LOCATIONf,
   3092         LOGICAL_BANK_9_PHYSICAL_BANK_LOCATIONf
   3093     };
   3094     static const soc_field_t dedicated_fields[] = {
   3095         HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f
   3096     };
   3097     static const soc_field_t shared_fields[] = {
   3098         B0_HASH_OFFSETf, B1_HASH_OFFSETf, B2_HASH_OFFSETf, B3_HASH_OFFSETf,
   3099         B4_HASH_OFFSETf, B5_HASH_OFFSETf, B6_HASH_OFFSETf, B7_HASH_OFFSETf
   3100     };
   3101     /* UFT/UAT control memories programming */
   3102     SOC_IF_ERROR_RETURN
   3103         (soc_trident3_hash_bank_count_get(unit, L2Xm, &num_l2_banks));
   3104     SOC_IF_ERROR_RETURN
   3105         (soc_trident3_hash_bank_count_get(unit, L3_ENTRY_ONLY_SINGLEm,
   3106                                           &num_l3_banks));
   3107     SOC_IF_ERROR_RETURN
   3108         (soc_trident3_hash_bank_count_get(unit, EXACT_MATCH_2m,
   3109                                           &num_fpem_banks));
   3110     SOC_IF_ERROR_RETURN
   3111         (soc_trident3_hash_bank_count_get(unit, EGR_VLAN_XLATE_1_SINGLEm,
   3112                                           &egr_vlan_xlate_1_banks));
   3113     SOC_IF_ERROR_RETURN
   3114         (soc_trident3_hash_bank_count_get(unit, EGR_VLAN_XLATE_2_SINGLEm,
   3115                                           &egr_vlan_xlate_2_banks));
   3116 
   3117     if (soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) {
   3118         int non_alpm = num_fpem_banks + num_l3_banks +
   3119                        num_l2_banks - 2 * (dedicated_banks);
   3120         sal_memset(hash_control_entry, 0,
   3121                     sizeof(uft_shared_banks_control_entry_t));
   3122         SOC_IF_ERROR_RETURN
   3123         (READ_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3124                                              hash_control_entry));
   3125         if ((non_alpm) && (non_alpm <= 4)) {
   3126             /* If Shared banks are used between ALPM and non-ALPM memories,
   3127              * then ALPM uses Shared Bank B2, B3, B4, B5 and non-ALPM uses
   3128              * B6, B7, B8, B9 banks
   3129              */
   3130             soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm,
   3131                                  hash_control_entry, ALPM_MODEf, 1);
   3132             soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm,
   3133                                  hash_control_entry, BANK_BYPASS_LPf, 0xf);
   3134             num_shared_alpm_banks[unit] = 4;
   3135             shared_bank_offset += 4;
   3136         } else {
   3137             soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm,
   3138                                  hash_control_entry, ALPM_MODEf, 0);
   3139             soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm,
   3140                                  hash_control_entry, BANK_BYPASS_LPf, 0xff);
   3141             num_shared_alpm_banks[unit] = 8;
   3142         }
   3143         SOC_IF_ERROR_RETURN
   3144         (WRITE_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3145                                              hash_control_entry));
   3146         SOC_IF_ERROR_RETURN
   3147             (soc_reg_field32_modify(unit, ISS_LOG_TO_PHY_BANK_MAP_2r,
   3148                                     REG_PORT_ANY, ALPM_BANK_MODEf,
   3149                                     num_shared_alpm_banks[unit] <= 4));
   3150     }
   3151 
   3152     sal_memset(shared_hash_control_entry, 0,
   3153                 sizeof(uft_shared_banks_control_entry_t));
   3154     SOC_IF_ERROR_RETURN
   3155         (READ_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3156                                         shared_hash_control_entry));
   3157     sal_memset(hash_control_entry, 0, sizeof(l2_entry_hash_control_entry_t));
   3158     SOC_IF_ERROR_RETURN
   3159         (READ_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   3160     soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm , hash_control_entry,
   3161                         HASH_TABLE_BANK_CONFIGf, (((1 << dedicated_banks) - 1)
   3162                         | (((1 << (num_l2_banks - dedicated_banks)) - 1) <<
   3163                         shared_bank_offset)));
   3164     for (index = dedicated_banks ; index < num_l2_banks ; index++) {
   3165         soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm , hash_control_entry,
   3166                             logical_to_physical_fields[index],
   3167                             index + shared_bank_offset - dedicated_banks);
   3168     }
   3169 
   3170     for (index = 0; index < dedicated_banks; index++) {
   3171         shared_hash_offset = (index == (num_l2_banks-1))? TD3_UFT_HASH_OFFSET_MAX :
   3172                               ((index * TD3_UFT_HASH_OFFSET_MAX) / (num_l2_banks-1));
   3173         soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm, hash_control_entry,
   3174                             dedicated_fields[index], shared_hash_offset);
   3175     }
   3176 
   3177     for (index = dedicated_banks; index < num_l2_banks; index++) {
   3178         shared_hash_offset = (index == (num_l2_banks-1))? TD3_UFT_HASH_OFFSET_MAX :
   3179                               ((index * TD3_UFT_HASH_OFFSET_MAX) / (num_l2_banks-1));
   3180         soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm,
   3181                             shared_hash_control_entry, shared_fields[index -
   3182                             dedicated_banks], shared_hash_offset);
   3183     }
   3184 
   3185     SOC_IF_ERROR_RETURN
   3186         (WRITE_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, hash_control_entry));
   3187 
   3188     /* Memories with only dedicated banks */
   3189     mem_sz = sizeof(dedicated_bank_mems) / sizeof(dedicated_bank_mems[0]);
   3190     for (m = 0; m < mem_sz; m++) {
   3191         sal_memset(hash_control_entry, 0, sizeof(hash_control_entry));
   3192         SOC_IF_ERROR_RETURN(
   3193             soc_mem_read(unit, dedicated_bank_mems[m], MEM_BLOCK_ANY, 0,
   3194             hash_control_entry));
   3195         for (index = 0; index < dedicated_banks; index++) {
   3196             soc_mem_field32_set(unit, dedicated_bank_mems[m],
   3197                 hash_control_entry, dedicated_fields[index], 0 + (index * 32));
   3198         }
   3199         SOC_IF_ERROR_RETURN(
   3200             soc_mem_write(unit, dedicated_bank_mems[m], MEM_BLOCK_ANY, 0,
   3201             hash_control_entry));
   3202     }
   3203 
   3204     /* Exact match */
   3205     sal_memset(hash_control_entry, 0, sizeof(exact_match_hash_control_entry_t));
   3206     SOC_IF_ERROR_RETURN
   3207         (READ_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3208                                             hash_control_entry));
   3209     shared_bank_offset += (num_l2_banks - dedicated_banks) ;
   3210 
   3211     soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, hash_control_entry,
   3212                       HASH_TABLE_BANK_CONFIGf,
   3213                       ((1 << num_fpem_banks) - 1) << shared_bank_offset);
   3214     for (index = 0 ; index < num_fpem_banks; index++) {
   3215         shared_hash_offset = (index == (num_fpem_banks-1)) ? TD3_UFT_HASH_OFFSET_MAX  :
   3216                               ((index * TD3_UFT_HASH_OFFSET_MAX) / (num_fpem_banks-1));
   3217         soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm , hash_control_entry,
   3218                           logical_to_physical_fields[index], index +
   3219                           shared_bank_offset);
   3220         soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm,
   3221                             shared_hash_control_entry,
   3222                             shared_fields[shared_bank_offset + index -
   3223                             dedicated_banks], shared_hash_offset);
   3224     }
   3225 
   3226     SOC_IF_ERROR_RETURN
   3227         (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3228                                             hash_control_entry));
   3229 
   3230     sal_memset(hash_control_entry, 0, sizeof(l3_entry_hash_control_entry_t));
   3231     SOC_IF_ERROR_RETURN
   3232         (READ_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3233                                         hash_control_entry));
   3234     shared_bank_offset += num_fpem_banks;
   3235 
   3236     soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm, hash_control_entry,
   3237                         HASH_TABLE_BANK_CONFIGf, ((((1 << (num_l3_banks -
   3238                         dedicated_banks)) - 1) << shared_bank_offset) |
   3239                         (((1 << dedicated_banks) - 1) << 10)));
   3240 
   3241     for (index = 0; index < dedicated_banks; index++) {
   3242         shared_hash_offset = (index == (num_l3_banks-1))? TD3_UFT_HASH_OFFSET_MAX :
   3243                               ((index * TD3_UFT_HASH_OFFSET_MAX)/(num_l3_banks-1));
   3244         soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm, hash_control_entry,
   3245                             dedicated_fields[index], shared_hash_offset);
   3246     }
   3247 
   3248     for (index = dedicated_banks ; index < num_l3_banks ; index++) {
   3249         shared_hash_offset = (index == (num_l3_banks-1))? TD3_UFT_HASH_OFFSET_MAX :
   3250                               ((index * TD3_UFT_HASH_OFFSET_MAX)/(num_l3_banks-1));
   3251         soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm, hash_control_entry,
   3252                           logical_to_physical_fields[index],
   3253                           index + shared_bank_offset - dedicated_banks);
   3254         soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm,
   3255                             shared_hash_control_entry,
   3256                             shared_fields[shared_bank_offset + index -
   3257                             (dedicated_banks * 2)], shared_hash_offset);
   3258     }
   3259     SOC_IF_ERROR_RETURN
   3260         (WRITE_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3261                                         hash_control_entry));
   3262     SOC_IF_ERROR_RETURN
   3263         (WRITE_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3264                                         shared_hash_control_entry));
   3265 
   3266     sal_memset(shared_hash_control_entry, 0,
   3267                 sizeof(ep_uat_shared_banks_control_entry_t));
   3268     sal_memset(hash_control_entry, 0,
   3269                 sizeof(egr_vlan_xlate_1_hash_control_entry_t));
   3270 
   3271     SOC_IF_ERROR_RETURN
   3272         (READ_EP_UAT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3273                                             shared_hash_control_entry));
   3274     SOC_IF_ERROR_RETURN
   3275         (READ_EGR_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3276                                                 hash_control_entry));
   3277     soc_mem_field32_set(unit, EGR_VLAN_XLATE_1_HASH_CONTROLm,
   3278                         hash_control_entry, HASH_TABLE_BANK_CONFIGf,
   3279                         ((1 << egr_vlan_xlate_1_banks) - 1)) ;
   3280 
   3281     for(index = 0; index < egr_vlan_xlate_1_banks; index++) {
   3282         shared_hash_offset = (index == (egr_vlan_xlate_1_banks-1))?
   3283                                TD3_EUAT_HASH_OFFSET_MAX :
   3284                                ((index * TD3_EUAT_HASH_OFFSET_MAX) / (egr_vlan_xlate_1_banks-1));
   3285         soc_mem_field32_set(unit, EGR_VLAN_XLATE_1_HASH_CONTROLm,
   3286                             hash_control_entry,
   3287                             logical_to_physical_fields[index],
   3288                             index);
   3289         soc_mem_field32_set(unit, EP_UAT_SHARED_BANKS_CONTROLm,
   3290                             shared_hash_control_entry, shared_fields[index],
   3291                             shared_hash_offset);
   3292     }
   3293     SOC_IF_ERROR_RETURN
   3294         (WRITE_EGR_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3295                                                 hash_control_entry));
   3296 
   3297     sal_memset(hash_control_entry, 0,
   3298                 sizeof(egr_vlan_xlate_2_hash_control_entry_t));
   3299 
   3300     SOC_IF_ERROR_RETURN
   3301         (READ_EGR_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3302                                                 hash_control_entry));
   3303     soc_mem_field32_set(unit, EGR_VLAN_XLATE_2_HASH_CONTROLm, hash_control_entry,
   3304                         HASH_TABLE_BANK_CONFIGf,
   3305                         ((1 << egr_vlan_xlate_2_banks) - 1) <<
   3306                         egr_vlan_xlate_1_banks) ;
   3307 
   3308     for(index = 0; index < egr_vlan_xlate_2_banks; index++) {
   3309         shared_hash_offset = (index == (egr_vlan_xlate_2_banks-1))?
   3310                                TD3_EUAT_HASH_OFFSET_MAX :
   3311                                ((index * TD3_EUAT_HASH_OFFSET_MAX) / (egr_vlan_xlate_2_banks-1));
   3312         soc_mem_field32_set(unit, EGR_VLAN_XLATE_2_HASH_CONTROLm,
   3313                             hash_control_entry,
   3314                             logical_to_physical_fields[index],
   3315                             index + egr_vlan_xlate_1_banks);
   3316         soc_mem_field32_set(unit, EP_UAT_SHARED_BANKS_CONTROLm,
   3317                             shared_hash_control_entry, shared_fields[index +
   3318                             egr_vlan_xlate_1_banks], shared_hash_offset);
   3319     }
   3320     SOC_IF_ERROR_RETURN
   3321         (WRITE_EGR_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3322                                                 hash_control_entry));
   3323     SOC_IF_ERROR_RETURN
   3324         (WRITE_EP_UAT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3325                                                 shared_hash_control_entry));
   3326 
   3327     sal_memset(shared_hash_control_entry, 0,
   3328                 sizeof(ip_uat_16k_shared_banks_control_entry_t));
   3329     sal_memset(shared_8k_hash_control_entry, 0,
   3330                 sizeof(ip_uat_8k_shared_banks_control_entry_t));
   3331     sal_memset(hash_control_entry, 0,
   3332                 sizeof(mpls_entry_hash_control_entry_t));
   3333     SOC_IF_ERROR_RETURN
   3334         (READ_IP_UAT_16K_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3335                                                 shared_hash_control_entry));
   3336     SOC_IF_ERROR_RETURN
   3337         (READ_IP_UAT_8K_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3338                                                 shared_8k_hash_control_entry));
   3339     SOC_IF_ERROR_RETURN
   3340         (READ_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3341                                                 hash_control_entry));
   3342 
   3343     num_entries = soc_mem_index_count(unit, MPLS_ENTRY_SINGLEm);
   3344     SOC_IF_ERROR_RETURN(soc_trident3_iuat_sizing(unit, num_entries,
   3345                                                     &uat_16k_banks, &uat_8k_banks));
   3346     mpls_16k_banks = uat_16k_banks;
   3347     mpls_8k_banks = uat_8k_banks;
   3348     soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, hash_control_entry,
   3349                         HASH_TABLE_BANK_CONFIGf, (((1 << mpls_8k_banks) - 1) |
   3350                         (((1 << mpls_16k_banks) - 1) << 4)));
   3351 
   3352     for(index = 0; index < mpls_8k_banks; index++) {
   3353         shared_hash_offset = (index == (mpls_8k_banks-1))?
   3354                                TD3_UAT_8K_HASH_OFFSET_MAX :
   3355                                ((index * TD3_UAT_8K_HASH_OFFSET_MAX) / (mpls_8k_banks-1));
   3356         soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, hash_control_entry,
   3357                             logical_to_physical_fields[index], index);
   3358         soc_mem_field32_set(unit, IP_UAT_8K_SHARED_BANKS_CONTROLm,
   3359                             shared_8k_hash_control_entry, shared_fields[index],
   3360                             shared_hash_offset);
   3361     }
   3362 
   3363     for(index = 0; index < mpls_16k_banks; index++) {
   3364         shared_hash_offset = (index == (mpls_16k_banks-1))?
   3365                                TD3_UAT_16K_HASH_OFFSET_MAX :
   3366                                ((index * TD3_UAT_16K_HASH_OFFSET_MAX) / (mpls_16k_banks-1));
   3367         soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm,
   3368                             hash_control_entry,
   3369                             logical_to_physical_fields[index + mpls_8k_banks], index + 4);
   3370         soc_mem_field32_set(unit, IP_UAT_16K_SHARED_BANKS_CONTROLm,
   3371                             shared_hash_control_entry, shared_fields[index],
   3372                             shared_hash_offset);
   3373     }
   3374     SOC_IF_ERROR_RETURN
   3375         (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3376                                                 hash_control_entry));
   3377 
   3378     sal_memset(hash_control_entry, 0,
   3379                 sizeof(vlan_xlate_1_hash_control_entry_t));
   3380     SOC_IF_ERROR_RETURN
   3381         (READ_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3382                                                 hash_control_entry));
   3383     num_entries = soc_mem_index_count(unit, VLAN_XLATE_1_SINGLEm);
   3384     SOC_IF_ERROR_RETURN(
   3385     soc_trident3_iuat_sizing(unit, num_entries, &uat_16k_banks,
   3386                                                     &uat_8k_banks));
   3387     vlan_xlate_1_16k_banks = uat_16k_banks - mpls_16k_banks;
   3388     vlan_xlate_1_8k_banks = uat_8k_banks - mpls_8k_banks;
   3389     soc_mem_field32_set(unit, VLAN_XLATE_1_HASH_CONTROLm, hash_control_entry,
   3390                         HASH_TABLE_BANK_CONFIGf, ((((1 << vlan_xlate_1_8k_banks)
   3391                         - 1) << mpls_8k_banks) |
   3392                         (((1 << vlan_xlate_1_16k_banks) - 1) << (4 +
   3393                         mpls_16k_banks))));
   3394 
   3395     for(index = 0; index < vlan_xlate_1_8k_banks; index++) {
   3396         shared_hash_offset = (index == (vlan_xlate_1_8k_banks-1))?
   3397                                TD3_UAT_8K_HASH_OFFSET_MAX :
   3398                                ((index * TD3_UAT_8K_HASH_OFFSET_MAX) / (vlan_xlate_1_8k_banks-1));
   3399         soc_mem_field32_set(unit, VLAN_XLATE_1_HASH_CONTROLm,
   3400                             hash_control_entry,
   3401                             logical_to_physical_fields[index], index +
   3402                             mpls_8k_banks);
   3403         soc_mem_field32_set(unit, IP_UAT_8K_SHARED_BANKS_CONTROLm,
   3404                             shared_8k_hash_control_entry, shared_fields[index +
   3405                             mpls_8k_banks], shared_hash_offset);
   3406     }
   3407 
   3408     for(index = 0; index < vlan_xlate_1_16k_banks; index++) {
   3409         shared_hash_offset = (index == (vlan_xlate_1_16k_banks-1))?
   3410                                TD3_UAT_16K_HASH_OFFSET_MAX :
   3411                                ((index * TD3_UAT_16K_HASH_OFFSET_MAX) / (vlan_xlate_1_16k_banks-1));
   3412         soc_mem_field32_set(unit, VLAN_XLATE_1_HASH_CONTROLm,
   3413                                 hash_control_entry,
   3414                                 logical_to_physical_fields[index + vlan_xlate_1_8k_banks], index +
   3415                                 mpls_16k_banks + 4);
   3416         soc_mem_field32_set(unit, IP_UAT_16K_SHARED_BANKS_CONTROLm,
   3417                             shared_hash_control_entry, shared_fields[index +
   3418                             mpls_16k_banks], shared_hash_offset);
   3419     }
   3420     SOC_IF_ERROR_RETURN
   3421         (WRITE_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3422                                                 hash_control_entry));
   3423 
   3424     sal_memset(hash_control_entry, 0,
   3425                 sizeof(vlan_xlate_2_hash_control_entry_t));
   3426     SOC_IF_ERROR_RETURN
   3427         (READ_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   3428                                                 hash_control_entry));
   3429     num_entries = soc_mem_index_count(unit, VLAN_XLATE_2_SINGLEm);
   3430     SOC_IF_ERROR_RETURN(soc_trident3_iuat_sizing(unit, num_entries,
   3431                             &uat_16k_banks, &uat_8k_banks));
   3432     vlan_xlate_2_16k_banks = uat_16k_banks - mpls_16k_banks -
   3433                                 vlan_xlate_1_16k_banks;
   3434     vlan_xlate_2_8k_banks = uat_8k_banks - mpls_8k_banks -
   3435                                 vlan_xlate_1_8k_banks;
   3436 
   3437     soc_mem_field32_set(unit, VLAN_XLATE_2_HASH_CONTROLm, hash_control_entry,
   3438                         HASH_TABLE_BANK_CONFIGf, ((((1 << vlan_xlate_2_8k_banks)
   3439                         - 1) << (mpls_8k_banks + vlan_xlate_1_8k_banks)) |
   3440                         (((1 << vlan_xlate_2_16k_banks) - 1) << (4 +
   3441                         mpls_16k_banks + vlan_xlate_1_16k_banks ))));
   3442 
   3443     for(index = 0; index < vlan_xlate_2_8k_banks; index++) {
   3444         shared_hash_offset = (index == (vlan_xlate_2_8k_banks-1))?
   3445                                TD3_UAT_8K_HASH_OFFSET_MAX :
   3446                                ((index * TD3_UAT_8K_HASH_OFFSET_MAX) / (vlan_xlate_2_8k_banks-1));
   3447         soc_mem_field32_set(unit, VLAN_XLATE_2_HASH_CONTROLm, hash_control_entry,
   3448                             logical_to_physical_fields[index], index +
   3449                             mpls_8k_banks + vlan_xlate_1_8k_banks);
   3450         soc_mem_field32_set(unit, IP_UAT_8K_SHARED_BANKS_CONTROLm,
   3451                             shared_8k_hash_control_entry, shared_fields[index +
   3452                             mpls_8k_banks + vlan_xlate_1_8k_banks],
   3453                             shared_hash_offset);
   3454     }
   3455 
   3456     for(index = 0; index < vlan_xlate_2_16k_banks; index++) {
   3457         shared_hash_offset = (index == (vlan_xlate_2_16k_banks-1))?
   3458                                TD3_UAT_16K_HASH_OFFSET_MAX :
   3459                                ((index * TD3_UAT_16K_HASH_OFFSET_MAX) / (vlan_xlate_2_16k_banks-1));
   3460         soc_mem_field32_set(unit, VLAN_XLATE_2_HASH_CONTROLm,
   3461                                 hash_control_entry,
   3462                                 logical_to_physical_fields[index + vlan_xlate_2_8k_banks], index +
   3463                                 mpls_16k_banks + vlan_xlate_1_16k_banks + 4);
   3464         soc_mem_field32_set(unit, IP_UAT_16K_SHARED_BANKS_CONTROLm,
   3465                             shared_hash_control_entry, shared_fields[index +
   3466                             mpls_16k_banks + vlan_xlate_1_16k_banks],
   3467                             shared_hash_offset);
   3468     }
   3469     SOC_IF_ERROR_RETURN
   3470         (WRITE_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3471                                                 hash_control_entry));
   3472     SOC_IF_ERROR_RETURN
   3473         (WRITE_IP_UAT_8K_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3474                                                 shared_8k_hash_control_entry));
   3475     SOC_IF_ERROR_RETURN
   3476         (WRITE_IP_UAT_16K_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3477                                                 shared_hash_control_entry));
   3478 
   3479     /* Create a mutex for s/w re-ordering */
   3480     SOC_IF_ERROR_RETURN(soc_td3_hash_mutex_init (unit));
   3481 
   3482     return SOC_E_NONE;
   3483 
   3484 }
   3485 
   3486 int
   3487 soc_trident3_init_idb_memory(int unit)
   3488 {
   3489     uint32 pipe_map;
   3490     soc_reg_t reg;
   3491     int pipe, chip_num_pipe;
   3492     uint32 rval, in_progress;
   3493     int pipe_init_usec;
   3494     soc_timeout_t to;
   3495 	static const soc_reg_t idb_tdm_config_reg[TRIDENT3_TDM_PIPES_PER_DEV] = {
   3496         	IS_TDM_CONFIG_PIPE0r, IS_TDM_CONFIG_PIPE1r
   3497         };
   3498 	static const soc_reg_t idb_opp_sched_config[TRIDENT3_TDM_PIPES_PER_DEV] = {
   3499         	IS_OPP_SCHED_CFG_PIPE0r, IS_OPP_SCHED_CFG_PIPE1r
   3500         };
   3501 
   3502     soc_trident3_pipe_map_get(unit, &pipe_map);
   3503 
   3504     /* While full chip emulaiton database is used, if only PIPE0 ports are configured
   3505      * NUM_PIPE is overwritten to 1, however we still need to reset entire chip using
   3506      * chip_num_pipe which reflects total number of pipes in the chip.
   3507      */
   3508     chip_num_pipe = soc_property_get(unit, "num_pipe", NUM_PIPE(unit));
   3509 
   3510     /* Initialize IDB memory */
   3511     rval = 0;
   3512     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1);
   3513     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1);
   3514     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, REGIONf, 1);
   3515     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, 0x100);
   3516     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   3517 
   3518     /* For simulation, set timeout to 10 sec.  Otherwise, timeout = 50 ms */
   3519     if (SAL_BOOT_SIMULATION) {
   3520         pipe_init_usec = 10000000;
   3521     } else {
   3522         pipe_init_usec = 50000;
   3523     }
   3524     soc_timeout_init(&to, pipe_init_usec, 0);
   3525 
   3526     /* Wait for IDB memory initialization done */
   3527     in_progress = pipe_map;
   3528     do {
   3529         for (pipe = 0; pipe < chip_num_pipe && in_progress; pipe++) {
   3530             reg = SOC_REG_UNIQUE_ACC(unit, ING_HW_RESET_CONTROL_2r)[pipe];
   3531             if (in_progress & (1 << pipe)) { /* not done yet */
   3532                 SOC_IF_ERROR_RETURN
   3533                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   3534                 if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   3535                     in_progress ^= (1 << pipe);
   3536                 }
   3537             }
   3538         }
   3539         if (soc_timeout_check(&to)) {
   3540             LOG_WARN(BSL_LS_SOC_COMMON,
   3541                      (BSL_META_U(unit,
   3542                                  "unit %d : ING_HW_RESET timeout\n"), unit));
   3543             break;
   3544         }
   3545     } while (in_progress != 0);
   3546     rval = 0;
   3547     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, REGIONf, 1);
   3548     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   3549 
   3550     for (pipe = 0; pipe < chip_num_pipe; pipe++) {
   3551 
   3552 		rval = 0;
   3553 		reg = idb_tdm_config_reg[pipe];
   3554 		soc_reg_field_set(unit, reg, &rval, ENABLEf, 1);
   3555         	SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   3556 
   3557 		reg = idb_opp_sched_config[pipe];
   3558         	SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   3559         	soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, 1);
   3560         	soc_reg_field_set(unit, reg, &rval, OPP1_SPACINGf, 6);
   3561         	SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   3562 	}
   3563 
   3564     return SOC_E_NONE;
   3565 }
   3566 
   3567 int
   3568 soc_trident3_clear_all_memory(int unit)
   3569 {
   3570     uint32 pipe_map;
   3571     int block_info_idx;
   3572     soc_reg_t reg;
   3573     int pipe, port, index, count;
   3574     uint32 rval, in_progress;
   3575     int pipe_init_usec;
   3576     soc_timeout_t to;
   3577     uint32 hash_control_entry[4];
   3578     uint32 bitmap = 0, uft_bmap=0;
   3579     soc_mem_t hmem = L3_ENTRY_HASH_CONTROLm;
   3580     static const struct {
   3581         soc_mem_t mem;
   3582         uint32 skip_flags; /* always skip on QUICKTURN or XGSSIM */
   3583     } cam_list[] = {
   3584         { CPU_COS_MAPm,                         BOOT_F_PLISIM },
   3585         { DST_COMPRESSIONm,                     BOOT_F_PLISIM },
   3586         { EFP_TCAMm,                            BOOT_F_PLISIM },
   3587         { EGR_FIELD_EXTRACTION_PROFILE_1_TCAMm, BOOT_F_PLISIM },
   3588         { EGR_FIELD_EXTRACTION_PROFILE_2_TCAMm, BOOT_F_PLISIM },
   3589         { EGR_PKT_FLOW_SELECT_TCAMm,            BOOT_F_PLISIM },
   3590         { EGR_QOS_CTRL_TCAMm,                   BOOT_F_PLISIM },
   3591         { EGR_ZONE_0_EDITOR_CONTROL_TCAMm,      BOOT_F_PLISIM },
   3592         { EGR_ZONE_1_EDITOR_CONTROL_TCAMm,      BOOT_F_PLISIM },
   3593         { EGR_ZONE_2_EDITOR_CONTROL_TCAMm,      BOOT_F_PLISIM },
   3594         { EGR_ZONE_3_EDITOR_CONTROL_TCAMm,      BOOT_F_PLISIM },
   3595         { EGR_ZONE_4_EDITOR_CONTROL_TCAMm,      BOOT_F_PLISIM },
   3596         { EXACT_MATCH_LOGICAL_TABLE_SELECTm,    BOOT_F_PLISIM },
   3597         { FLEX_RTAG7_HASH_TCAMm,                BOOT_F_PLISIM },
   3598         { IFP_LOGICAL_TABLE_SELECTm,            BOOT_F_PLISIM },
   3599         { IFP_TCAMm,                            BOOT_F_PLISIM },
   3600         { ING_SNATm,                            BOOT_F_PLISIM },
   3601         { IP_MULTICAST_TCAMm,                   BOOT_F_PLISIM },
   3602         { L2_USER_ENTRYm,                       BOOT_F_PLISIM },
   3603         { L3_DEFIPm,                            BOOT_F_PLISIM },
   3604         { L3_DEFIP_PAIR_128m,                   BOOT_F_PLISIM },
   3605         { L3_TUNNELm,                           BOOT_F_PLISIM },
   3606         { MY_STATION_TCAMm,                     BOOT_F_PLISIM },
   3607         { MY_STATION_TCAM_2m,                   BOOT_F_PLISIM },
   3608         { PHB_SELECT_TCAMm,                     BOOT_F_PLISIM },
   3609         { PKT_FLOW_SELECT_TCAM_0m,              BOOT_F_PLISIM },
   3610         { PKT_FLOW_SELECT_TCAM_1m,              BOOT_F_PLISIM },
   3611         { PKT_FLOW_SELECT_TCAM_2m,              BOOT_F_PLISIM },
   3612         { SRC_COMPRESSIONm,                     BOOT_F_PLISIM },
   3613         { VFP_TCAMm,                            BOOT_F_PLISIM },
   3614         { VLAN_SUBNETm,                         0 },/* VLAN API needs all 0 mask */
   3615     };
   3616 
   3617     soc_trident3_pipe_map_get(unit, &pipe_map);
   3618 
   3619     SOC_IF_ERROR_RETURN(soc_mem_read(unit, L2_ENTRY_HASH_CONTROLm,
   3620                                 MEM_BLOCK_ALL, 0, hash_control_entry));
   3621     uft_bmap |= soc_mem_field32_get(unit, L2_ENTRY_HASH_CONTROLm,
   3622                                 hash_control_entry, HASH_TABLE_BANK_CONFIGf);
   3623 
   3624     SOC_IF_ERROR_RETURN(soc_mem_read(unit, EXACT_MATCH_HASH_CONTROLm,
   3625                                 MEM_BLOCK_ALL, 0, hash_control_entry));
   3626     uft_bmap |= soc_mem_field32_get(unit, EXACT_MATCH_HASH_CONTROLm,
   3627                                 hash_control_entry, HASH_TABLE_BANK_CONFIGf);
   3628 
   3629     /* L3_ENTRY_HASH_CONTROL->HASH_TABLE_BANK_CONFIG must be set to cover shared
   3630      * UFT banks, that are not included in other hash control during HW MEM RESET ALL
   3631      * and also include dedicated L3 banks.
   3632      */
   3633     SOC_IF_ERROR_RETURN(soc_mem_read(unit, hmem, MEM_BLOCK_ALL, 0,
   3634                                 hash_control_entry));
   3635     bitmap = soc_mem_field32_get(unit, hmem, hash_control_entry,
   3636                                 HASH_TABLE_BANK_CONFIGf);
   3637 
   3638     uft_bmap = 0xFFC & ~uft_bmap;
   3639     soc_mem_field32_set(unit, hmem, hash_control_entry, HASH_TABLE_BANK_CONFIGf, uft_bmap);
   3640     SOC_IF_ERROR_RETURN(soc_mem_write(unit, hmem, MEM_BLOCK_ALL, 0, hash_control_entry));
   3641 
   3642     /* Initial IPIPE memory */
   3643     rval = 0;
   3644     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_1r(unit, rval));
   3645     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1);
   3646     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1);
   3647     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, REGIONf, 0);
   3648     /* Set count to # entries of largest IPIPE table */
   3649     count = soc_mem_index_count(unit, ING_L3_NEXT_HOPm);
   3650 
   3651     if (SOC_MEM_IS_VALID(unit, BSC_AG_AGE_TABLEm)) {
   3652         if (count < soc_mem_index_count(unit, BSC_AG_AGE_TABLEm)) {
   3653             count = soc_mem_index_count(unit, BSC_AG_AGE_TABLEm);
   3654         }
   3655     }
   3656 
   3657     if (count < soc_mem_index_count(unit, L2Xm)) {
   3658         count = soc_mem_index_count(unit, L2Xm);
   3659     }
   3660     if (count < soc_mem_index_count(unit, L3_ENTRY_ONLY_SINGLEm)) {
   3661         count = soc_mem_index_count(unit, L3_ENTRY_ONLY_SINGLEm);
   3662     }
   3663     /*if (count < soc_mem_index_count(unit, FPEM_ECCm)) {
   3664         count = soc_mem_index_count(unit, FPEM_ECCm);
   3665     } */
   3666     if (count < soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) {
   3667         count = soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m);
   3668     }
   3669     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, count);
   3670     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   3671 
   3672     /* Initial EPIPE memory */
   3673     rval = 0;
   3674     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_0r(unit, rval));
   3675     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1);
   3676     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, VALIDf, 1);
   3677     /* Set count to # entries in largest EPIPE table (EGR_L3_NEXT_HOP) */
   3678     count = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   3679     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, COUNTf, count);
   3680     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval));
   3681 
   3682     /* For simulation, set timeout to 10 sec.  Otherwise, timeout = 50 ms */
   3683     if (SAL_BOOT_SIMULATION) {
   3684         pipe_init_usec = 10000000;
   3685     } else {
   3686         pipe_init_usec = 50000;
   3687     }
   3688     soc_timeout_init(&to, pipe_init_usec, 0);
   3689 
   3690     /* Wait for IPIPE memory initialization done */
   3691     in_progress = pipe_map;
   3692     do {
   3693         for (pipe = 0; pipe < NUM_PIPE(unit) && in_progress; pipe++) {
   3694             reg = SOC_REG_UNIQUE_ACC(unit, ING_HW_RESET_CONTROL_2r)[pipe];
   3695             if (in_progress & (1 << pipe)) { /* not done yet */
   3696                 SOC_IF_ERROR_RETURN
   3697                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   3698                     if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   3699                         in_progress ^= 1 << pipe;
   3700                     }
   3701             }
   3702         }
   3703         if (soc_timeout_check(&to)) {
   3704             LOG_WARN(BSL_LS_SOC_COMMON,
   3705                      (BSL_META_U(unit,
   3706                                  "unit %d : ING_HW_RESET timeout\n"), unit));
   3707             break;
   3708         }
   3709     } while (in_progress != 0);
   3710 
   3711     /* Restore L3_ENTRY_HASH_CONTROL->HASH_TABLE_BANK_CONFIG value */
   3712     soc_mem_field32_set(unit, hmem, hash_control_entry, HASH_TABLE_BANK_CONFIGf, bitmap);
   3713     SOC_IF_ERROR_RETURN(soc_mem_write(unit, hmem, MEM_BLOCK_ALL, 0, hash_control_entry));
   3714 
   3715     /* Wait for EPIPE memory initialization done */
   3716     in_progress = pipe_map;
   3717     do {
   3718         for (pipe = 0; pipe < NUM_PIPE(unit) && in_progress; pipe++) {
   3719             reg = SOC_REG_UNIQUE_ACC(unit, EGR_HW_RESET_CONTROL_1r)[pipe];
   3720             if (in_progress & (1 << pipe)) { /* not done yet */
   3721                 SOC_IF_ERROR_RETURN
   3722                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   3723                     if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   3724                         in_progress ^= 1 << pipe;
   3725                     }
   3726             }
   3727         }
   3728         if (soc_timeout_check(&to)) {
   3729             LOG_WARN(BSL_LS_SOC_COMMON,
   3730                      (BSL_META_U(unit,
   3731                                  "unit %d : EGR_HW_RESET timeout\n"), unit));
   3732             break;
   3733         }
   3734     } while (in_progress != 0);
   3735 
   3736     rval = 0;
   3737     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   3738     rval = SOC_REG_INFO(unit, EGR_HW_RESET_CONTROL_1r).rst_val_lo;
   3739     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval));
   3740 
   3741     /* Initial IDB memory */
   3742     SOC_IF_ERROR_RETURN(WRITE_IDB_HW_CONTROLr(unit, 0));
   3743     rval = 0;
   3744     soc_reg_field_set(unit, IDB_HW_CONTROLr, &rval, IS_MEM_INITf, 1);
   3745     SOC_IF_ERROR_RETURN(WRITE_IDB_HW_CONTROLr(unit, rval));
   3746     SOC_IF_ERROR_RETURN(WRITE_IDB_HW_CONTROLr(unit, 0));
   3747 
   3748     /* Initial PORT MIB counter */
   3749     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   3750         port = SOC_BLOCK_PORT(unit, block_info_idx);
   3751         soc_reg_field_set(unit, CLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf);
   3752         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MIB_RESETr(unit, port, rval));
   3753         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MIB_RESETr(unit, port, 0));
   3754     }
   3755     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_XLPORT) {
   3756         port = SOC_BLOCK_PORT(unit, block_info_idx);
   3757         soc_reg_field_set(unit, XLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf);
   3758         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, rval));
   3759         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, 0));
   3760     }
   3761 
   3762     /* TCAM tables are not handled by hardware reset control */
   3763     if (!SAL_BOOT_QUICKTURN && !SAL_BOOT_XGSSIM) {
   3764         for (index = 0; index < COUNTOF(cam_list); index++) {
   3765             if (sal_boot_flags_get() & cam_list[index].skip_flags) {
   3766                 continue;
   3767             }
   3768 
   3769             if (!SOC_MEM_IS_VALID(unit, cam_list[index].mem)) {
   3770                 continue;
   3771             }
   3772             SOC_IF_ERROR_RETURN
   3773                 (soc_mem_clear(unit, cam_list[index].mem, COPYNO_ALL, TRUE));
   3774         }
   3775     }
   3776 
   3777 /* TD3-1847 */
   3778     if (!SOC_WARM_BOOT(unit)) {
   3779         /* Clear the higher 32k of RH_*_flowset table */
   3780         if (soc_mem_index_count(unit, RH_LAG_FLOWSETm)) {
   3781             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ENHANCED_HASHING_CONTROL_2r,
   3782                         REG_PORT_ANY, RH_DLB_SELECTIONf, 1));
   3783             SOC_IF_ERROR_RETURN
   3784                 (soc_mem_clear(unit, RH_LAG_FLOWSETm, COPYNO_ALL, TRUE));
   3785             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ENHANCED_HASHING_CONTROL_2r,
   3786                         REG_PORT_ANY, RH_DLB_SELECTIONf, 0));
   3787         }
   3788         if (soc_mem_index_count(unit, RH_HGT_FLOWSETm)) {
   3789             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ENHANCED_HASHING_CONTROL_2r,
   3790                         REG_PORT_ANY, RH_DLB_SELECTIONf, 1));
   3791 
   3792             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ENHANCED_HASHING_CONTROL_2r,
   3793                         REG_PORT_ANY, HGT_LAG_FLOWSET_TABLE_CONFIGf, 2));
   3794             SOC_IF_ERROR_RETURN
   3795                 (soc_mem_clear(unit, RH_HGT_FLOWSETm, COPYNO_ALL, TRUE));
   3796             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ENHANCED_HASHING_CONTROL_2r,
   3797                         REG_PORT_ANY, RH_DLB_SELECTIONf, 0));
   3798             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ENHANCED_HASHING_CONTROL_2r,
   3799                         REG_PORT_ANY, HGT_LAG_FLOWSET_TABLE_CONFIGf, 0));
   3800         }
   3801     }
   3802 
   3803     soc_td3_rx_etype_niv[unit] = 0;
   3804     soc_td3_rx_etype_pe[unit] = 0;
   3805 
   3806     return SOC_E_NONE;
   3807 
   3808 }
   3809 
   3810 /* Determine a PLL's current DCO value.  The PLL should be checked to ensure
   3811    that it is locked prior to calling this function */
   3812 int
   3813 _soc_trident3_pll_dco_code_get(int unit, soc_td3_plls_e pll, uint32 *dco_code)
   3814 {
   3815     soc_reg_t stat_ctrl_reg;
   3816     soc_reg_t stat_reg;
   3817     soc_field_t stat_sel_fld, stat_rst_fld, stat_mode_fld, stat_update_fld;
   3818     soc_field_t stat_fld;
   3819     uint32 rval;
   3820 
   3821     stat_sel_fld = STAT_SELECTf;
   3822     stat_rst_fld = STAT_RESETf;
   3823     stat_mode_fld = STAT_MODEf;
   3824     stat_update_fld = STAT_UPDATEf;
   3825     stat_fld = PLL_STATUSf;
   3826     switch (pll) {
   3827         case SOC_TD3_TS_PLL:
   3828             stat_ctrl_reg = TOP_TS_PLL_CTRL_4r;
   3829             stat_reg = TOP_TS_PLL_STATUSr;
   3830             break;
   3831         case SOC_TD3_BS_PLL0:
   3832             stat_ctrl_reg = TOP_BS_PLL0_CTRL_4r;
   3833             stat_reg = TOP_BS_PLL0_STATUSr;
   3834             break;
   3835         case SOC_TD3_BS_PLL1:
   3836             stat_ctrl_reg = TOP_BS_PLL1_CTRL_4r;
   3837             stat_reg = TOP_BS_PLL1_STATUSr;
   3838             break;
   3839         default:
   3840             return SOC_E_PARAM;
   3841     }
   3842 
   3843     /* Configure the stat logic to read the DCO value */
   3844     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, stat_ctrl_reg, REG_PORT_ANY, 0,
   3845                                       &rval));
   3846     soc_reg_field_set(unit, stat_ctrl_reg, &rval, stat_sel_fld, 4); /* DCO */
   3847     soc_reg_field_set(unit, stat_ctrl_reg, &rval, stat_mode_fld, 3); /* avg */
   3848     soc_reg_field_set(unit, stat_ctrl_reg, &rval, stat_rst_fld, 1);
   3849     soc_reg_field_set(unit, stat_ctrl_reg, &rval, stat_update_fld, 0);
   3850     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, stat_ctrl_reg, REG_PORT_ANY, 0,
   3851                                       rval));
   3852 
   3853     /* Take out of reset */
   3854     soc_reg_field_set(unit, stat_ctrl_reg, &rval, stat_rst_fld, 0);
   3855     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, stat_ctrl_reg, REG_PORT_ANY, 0,
   3856                                       rval));
   3857 
   3858     /* Initiate a capture */
   3859     soc_reg_field_set(unit, stat_ctrl_reg, &rval, stat_update_fld, 1);
   3860     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, stat_ctrl_reg, REG_PORT_ANY, 0,
   3861                                       rval));
   3862 
   3863     sal_usleep(10 * MILLISECOND_USEC);
   3864 
   3865     /* Get the DCO code */
   3866     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, stat_reg, REG_PORT_ANY, 0,
   3867                                       &rval));
   3868     *dco_code = soc_reg_field_get(unit, stat_reg, rval, stat_fld);
   3869 
   3870     /* Clear the capture state */
   3871     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, stat_ctrl_reg, REG_PORT_ANY, 0,
   3872                                       &rval));
   3873     soc_reg_field_set(unit, stat_ctrl_reg, &rval, stat_update_fld, 0);
   3874     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, stat_ctrl_reg, REG_PORT_ANY, 0,
   3875                                       rval));
   3876 
   3877     return SOC_E_NONE;
   3878 }
   3879 
   3880 /* Linearly scale the DCO code as a function of the VCO's frequency */
   3881 int
   3882 _soc_td3_pll_dco_normalize(uint32 *dco_code, uint32 ref_freq, uint32 ndiv)
   3883 {
   3884     static const int int_ref_freq = 50000000;
   3885 
   3886     *dco_code <<= 20;
   3887     if (ref_freq <= 0) {
   3888         *dco_code /=  (int_ref_freq / 100000 * ndiv);
   3889     } else {
   3890         *dco_code /= (ref_freq / 100000 * ndiv);
   3891     }
   3892 
   3893     return SOC_E_NONE;
   3894 }
   3895 
   3896 int soc_td3_frequency_init(int unit)
   3897 {
   3898     static const int freq_list[]     = { 1525, 1425, 1325, 1012, 850 };
   3899     static const int freq_sel_list[] = {    2,    3,    4,    6,   7 };
   3900 
   3901     const char *str_ratio[] = { "2:3", "1:1" };
   3902     char *config_str;
   3903     static const int dpp_ratio_x10_list[] = {
   3904         15, /* core clk : pp clk ratio is 3:2 (default) */
   3905         10  /* core clk : pp clk ratio is 1:1 */
   3906     };
   3907 
   3908     soc_field_t fields[3];
   3909     uint32 values[3];
   3910     soc_info_t *si = &SOC_INFO(unit);
   3911 
   3912     int index, list_len, frequency, freq_sel=2;
   3913 
   3914     soc_trident3_max_frequency_get(unit, BCM56870_DEVICE_ID, -1, -1, &si->frequency);
   3915     frequency = soc_property_get(unit, spn_CORE_CLOCK_FREQUENCY, -1);
   3916 
   3917     /* Frequency is not selected.., so we go default setting. Nothing to do. */
   3918     if (frequency == -1) {
   3919         return (SOC_E_NONE);
   3920     }
   3921 
   3922     /* Frequency is more than max allowed, use max value. */
   3923     if (frequency > si->frequency) {
   3924         LOG_CLI((BSL_META_U(unit,
   3925                             "*** Input core clock frequency %dMHz is not "
   3926                             "supported, (max allowed : %dMHz!\n"),
   3927                              frequency, si->frequency));
   3928 
   3929         frequency = si->frequency;
   3930     }
   3931 
   3932     /* Check if Core CLK frequency is correct */
   3933     list_len = COUNTOF(freq_list);
   3934     for (index = 0; index < list_len; index++) {
   3935         if (freq_list[index] <= si->frequency &&
   3936             frequency == freq_list[index]) {
   3937             si->frequency          = frequency;
   3938             si->dpp_clk_ratio_x10  = (frequency > CCLK_FREQ_1012MHZ)?
   3939                                             dpp_ratio_x10_list[0] :
   3940                                             dpp_ratio_x10_list[1];
   3941             freq_sel  = freq_sel_list[index];
   3942             break;
   3943         }
   3944     }
   3945 
   3946     if (index >= list_len) {
   3947         LOG_CLI((BSL_META_U(unit,
   3948                             "*** Input core clock frequency %dMHz is not "
   3949                             "supported!\n"), frequency));
   3950         return (SOC_E_PARAM);
   3951     }
   3952 
   3953     /* Check if user specified dpp ratio and validate it */
   3954     config_str = soc_property_get_str(unit, spn_DPP_CLOCK_RATIO);
   3955     if (config_str) {
   3956         list_len = COUNTOF(dpp_ratio_x10_list);
   3957         for (index = 0; index < list_len; index++) {
   3958             if (!sal_strcmp(config_str, str_ratio[index])) {
   3959                 break;
   3960             }
   3961         }
   3962         if (index < list_len &&
   3963             !(si->frequency > 1012 && dpp_ratio_x10_list[index] == 10)) {
   3964             /* ratio 1:1 with core freq larger than 1125MHz is not supported */
   3965             si->dpp_clk_ratio_x10 = dpp_ratio_x10_list[index];
   3966         } else {
   3967             LOG_CLI((BSL_META_U(unit,
   3968                                 "*** Input dpp clock frequency ratio %s is not "
   3969                                 "supported with core frequency %d!\n"),
   3970                      config_str, si->frequency));
   3971             return (SOC_E_PARAM);
   3972         }
   3973     }
   3974 
   3975     fields[0] = CORE_CLK_0_FREQ_SELf;
   3976     values[0] = freq_sel;
   3977     fields[1] = SW_CORE_CLK_0_SEL_ENf;
   3978     values[1] = 1;
   3979     fields[2] = DPP_CLK_RATIO_SELf;
   3980     values[2] = (si->dpp_clk_ratio_x10 == 10)? 3 : 1;
   3981 
   3982     SOC_IF_ERROR_RETURN
   3983         (soc_reg_fields32_modify(unit, TOP_CORE_CLK_FREQ_SELr,
   3984                                  REG_PORT_ANY, 3, fields, values));
   3985     return (SOC_E_NONE);
   3986 }
   3987 
   3988 int
   3989 _soc_trident3_init_hash_control_reset(int unit) {
   3990 
   3991     soc_mem_field32_set(unit, EGR_VLAN_XLATE_1_HASH_CONTROLm,
   3992           &egr_vlan_1_hash_control, HASH_TABLE_BANK_CONFIGf, 0xf);
   3993     SOC_IF_ERROR_RETURN
   3994         (WRITE_EGR_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   3995                                              &egr_vlan_1_hash_control));
   3996 
   3997     soc_mem_field32_set(unit, EGR_VLAN_XLATE_2_HASH_CONTROLm,
   3998           &egr_vlan_2_hash_control, HASH_TABLE_BANK_CONFIGf, 0);
   3999     SOC_IF_ERROR_RETURN
   4000         (WRITE_EGR_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4001                                              &egr_vlan_2_hash_control));
   4002 
   4003     SOC_IF_ERROR_RETURN
   4004         (WRITE_EGR_VP_VLAN_MEMBERSHIP_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4005                                      &egr_vp_vlan_mbm_hash_control));
   4006 
   4007     soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm,
   4008           &exact_match_hash_control, HASH_TABLE_BANK_CONFIGf, 0x0);
   4009     SOC_IF_ERROR_RETURN
   4010         (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4011                                              &exact_match_hash_control));
   4012 
   4013     SOC_IF_ERROR_RETURN
   4014         (WRITE_ING_DNAT_ADDRESS_TYPE_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4015                                      &ing_dnat_hash_control));
   4016 
   4017     SOC_IF_ERROR_RETURN
   4018         (WRITE_ING_VP_VLAN_MEMBERSHIP_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4019                                      &ing_vp_vlan_mbm_hash_control));
   4020 
   4021     soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm,
   4022             &l2_entry_hash_control, HASH_TABLE_BANK_CONFIGf, 0x3);
   4023     SOC_IF_ERROR_RETURN
   4024         (WRITE_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4025                                              &l2_entry_hash_control));
   4026 
   4027     soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm,
   4028           &l3_entry_hash_control, HASH_TABLE_BANK_CONFIGf, 0xffc);
   4029     SOC_IF_ERROR_RETURN
   4030         (WRITE_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4031                                              &l3_entry_hash_control));
   4032 
   4033     soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm,
   4034           &mpls_entry_hash_control, HASH_TABLE_BANK_CONFIGf, 0x0);
   4035     SOC_IF_ERROR_RETURN
   4036         (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4037                                              &mpls_entry_hash_control));
   4038 
   4039     SOC_IF_ERROR_RETURN
   4040         (WRITE_SUBPORT_ID_TO_SGPP_MAP_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4041                               &subport_hash_control));
   4042 
   4043     soc_mem_field32_set(unit, VLAN_XLATE_1_HASH_CONTROLm,
   4044           &vlan_1_hash_control, HASH_TABLE_BANK_CONFIGf, 0xff);
   4045     SOC_IF_ERROR_RETURN
   4046         (WRITE_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4047                                              &vlan_1_hash_control));
   4048 
   4049     soc_mem_field32_set(unit, VLAN_XLATE_2_HASH_CONTROLm,
   4050           &vlan_2_hash_control, HASH_TABLE_BANK_CONFIGf, 0x0);
   4051     SOC_IF_ERROR_RETURN
   4052         (WRITE_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4053                                              &vlan_2_hash_control));
   4054 
   4055     SOC_IF_ERROR_RETURN
   4056         (WRITE_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4057                               &uft_shared_banks_control));
   4058 
   4059     SOC_IF_ERROR_RETURN
   4060         (WRITE_IP_UAT_16K_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4061                               &ip_uat_16k_shared_banks_control));
   4062 
   4063     SOC_IF_ERROR_RETURN
   4064         (WRITE_IP_UAT_8K_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4065                               &ip_uat_8k_shared_banks_control));
   4066 
   4067     SOC_IF_ERROR_RETURN
   4068         (WRITE_EP_UAT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   4069                               &ep_uat_shared_banks_control));
   4070      return SOC_E_NONE;
   4071 }
   4072 
   4073 int
   4074 soc_trident3_chip_reset(int unit)
   4075 {
   4076 #define _SOC_TD3_BSPLL_COUNT    2
   4077 #define _SOC_TD3_PLL_CFG_FIELDS 4
   4078 #define _SOC_TD3_TEMP_MAX       130
   4079 #define _SOC_TD3_DEF_TEMP_MAX   90
   4080 #if 0
   4081 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT)
   4082     int num_overlay_ecmp_rh_flowset_entries;
   4083     int ecmp_levels = 1;
   4084 #endif
   4085 #endif
   4086 
   4087     soc_reg_t reg;
   4088     int index, parity_enable;
   4089     uint32 to_usec, temp_mask;
   4090     uint32 rval, temp_thr;
   4091     uint32 dco_code, dco_code_target;
   4092     int ref_freq;
   4093     char blank = 0;
   4094     static const soc_pll_16_param_t ts_pll_params[] = {
   4095         /* 25MHz external reference clock */
   4096         {25000000, 25, 2, 10, 3, 10, 1, 200, {10, 20, 32, 10, 200, 40}},
   4097         /* 50MHz external reference clock */
   4098         {50000000, 50, 2, 10, 3, 10, 1, 100, {10,  0,  0,  0, 200, 40}},
   4099         /* 50MHz internal reference clock from core PLL */
   4100         {       0, 50, 2, 10, 3, 10, 1, 100, {10,  0,  0,  0, 200, 40}}
   4101     };
   4102     static const soc_pll_16_param_t bs_pll_params[] = {
   4103         /* 12.8MHz external reference clock */
   4104         {12800000, 1, 2, 10, 3, 10, 1, 200, {128, 0, 0, 0, 0, 0}},
   4105         /* 20MHz external reference clock */
   4106         {20000000, 1, 2, 10, 3, 10, 1, 125, {125, 0, 0, 0, 0, 0}},
   4107         /* 25MHz external reference clock */
   4108         {25000000, 1, 2, 10, 3, 10, 1, 100, {125, 0, 0, 0, 0, 0}},
   4109         /* 32MHz external reference clock */
   4110         {32000000, 1, 2, 10, 3, 10, 1,  80, {128, 0, 0, 0, 0, 0}},
   4111         /* 50MHz external reference clock */
   4112         {50000000, 1, 2, 10, 3, 10, 1,  50, {125, 0, 0, 0, 0, 0}},
   4113         /* 50MHz internal reference clock from core PLL */
   4114         {       0, 0, 2, 10, 3, 10, 1,  50, {125, 0, 0, 0, 0, 0}}
   4115     };
   4116     static const int auto_ref = -1;
   4117     static const uint32 dco_poison = 0xffff;
   4118 
   4119     static const soc_reg_t temp_thr_reg[] = {
   4120         TOP_PVTMON_0_INTR_THRESHOLDr,  TOP_PVTMON_1_INTR_THRESHOLDr,
   4121         TOP_PVTMON_2_INTR_THRESHOLDr,  TOP_PVTMON_3_INTR_THRESHOLDr,
   4122         TOP_PVTMON_4_INTR_THRESHOLDr,  TOP_PVTMON_5_INTR_THRESHOLDr,
   4123         TOP_PVTMON_6_INTR_THRESHOLDr,  TOP_PVTMON_7_INTR_THRESHOLDr,
   4124         TOP_PVTMON_8_INTR_THRESHOLDr,  TOP_PVTMON_9_INTR_THRESHOLDr,
   4125         TOP_PVTMON_10_INTR_THRESHOLDr, TOP_PVTMON_11_INTR_THRESHOLDr
   4126     };
   4127     static const char *temp_thr_prop[] = {
   4128         "temp0_threshold", "temp1_threshold", "temp2_threshold",
   4129         "temp3_threshold", "temp4_threshold", "temp5_threshold",
   4130         "temp6_threshold", "temp7_threshold", "temp8_threshold",
   4131         "temp9_threshold", "temp10_threshold","temp11_threshold"
   4132     };
   4133 
   4134     to_usec = SAL_BOOT_QUICKTURN ? (250 * MILLISECOND_USEC) :
   4135                                    (10 * MILLISECOND_USEC);
   4136 
   4137     /*
   4138      * SBUS ring and block number:
   4139      * ring 0: IP(1), LBPORT0(54), LBPORT1(51), LBPORT2(52), LBPORT3(53)
   4140      * ring 1: EP(2)
   4141      * ring 2: MMU_XPE(3), MMU_SC(4), MMU_GLB(5)
   4142      * ring 3: PM7(22), PM6(21), PM5(20), PM4(19), PM3(18), PM2(17), PM1(16),
   4143      *         PM0(15), PM31(46), PM30(45), PM29(44), PM28(43), PM27(42),
   4144      *         PM26(41), PM25(40), PM24(39), CLPORT32(55)
   4145      * ring 4: PM32(11), PM8(23), PM9(24), PM10(25), PM11(26), PM12(27),
   4146      *         PM13(28), PM14(29), PM15(30), PM16(31), PM17(32), PM18(33),
   4147      *         PM19(34), PM20(35), PM21(36), PM22(37), PM23(38)
   4148      * ring 5: OTPC(6), AVS(59), TOP(7), SER(8)
   4149      */
   4150 
   4151 
   4152 #ifdef BCM_CMICX_SUPPORT
   4153     if (soc_feature(unit, soc_feature_cmicx)) {
   4154         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_0_7_OFFSET,0x52222100);
   4155         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_8_15_OFFSET,0x30053005);
   4156         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_16_23_OFFSET,0x43333333);
   4157         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_24_31_OFFSET,0x64444444);
   4158         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_32_39_OFFSET,0x76666666);
   4159         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_40_47_OFFSET,0x07777777);
   4160         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_48_55_OFFSET,0x00000000);
   4161         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_56_63_OFFSET,0x00005000);
   4162         soc_pci_write(unit, CMIC_TOP_SBUS_TIMEOUT_OFFSET,0x5000);
   4163     }
   4164 #endif
   4165 
   4166     /* Reset all mHost processors */
   4167     SOC_IF_ERROR_RETURN(WRITE_MHOST_0_CR5_RST_CTRLr(unit, 0));
   4168     SOC_IF_ERROR_RETURN(WRITE_MHOST_1_CR5_RST_CTRLr(unit, 0));
   4169     /*Reset the common UARTs */
   4170     SOC_IF_ERROR_RETURN(WRITE_IPROCPERIPH_UART0_UART_SRRr(unit, 1));
   4171     SOC_IF_ERROR_RETURN(WRITE_IPROCPERIPH_UART1_UART_SRRr(unit, 1));
   4172 
   4173     sal_usleep(to_usec);
   4174 
   4175 #if 1
   4176     SOC_IF_ERROR_RETURN(soc_td3_frequency_init(unit));
   4177 #endif
   4178 
   4179     /* Bring up TS PLL */
   4180     ref_freq = soc_property_get(unit, spn_PTP_TS_PLL_FREF, auto_ref);
   4181     index = (ref_freq == auto_ref) ? (COUNTOF(ts_pll_params) - 1) : 0;
   4182     dco_code_target = dco_poison;
   4183 
   4184     for (; index < COUNTOF(ts_pll_params); index++) {
   4185         if (ref_freq != auto_ref &&
   4186                 ts_pll_params[index].ref_freq != ref_freq) {
   4187             continue;
   4188         }
   4189 
   4190         /* Place in reset */
   4191         SOC_IF_ERROR_RETURN
   4192             (soc_reg_field32_modify(unit, TOP_SOFT_RESET_REG_2r, REG_PORT_ANY,
   4193                                     TOP_TS_PLL_RST_Lf, 0));
   4194 
   4195         /* Set N-divider value */
   4196         SOC_IF_ERROR_RETURN
   4197             (soc_reg_field32_modify(unit, TOP_TS_PLL_CTRL_0r, REG_PORT_ANY,
   4198                                     NDIV_INTf, ts_pll_params[index].ndiv));
   4199 
   4200         /* Select internal or external clock source */
   4201         SOC_IF_ERROR_RETURN
   4202             (soc_reg_field32_modify(unit, TOP_TS_PLL_CTRL_2r, REG_PORT_ANY,
   4203                             REFCLK_SOURCE_SELf,
   4204                             ts_pll_params[index].ref_freq == 0 ? 0 : 1));
   4205 
   4206         /* Set new reference frequency info */
   4207         SOC_IF_ERROR_RETURN
   4208             (soc_reg_field32_modify(unit, TOP_TS_PLL_CTRL_3r, REG_PORT_ANY,
   4209                             FREFEFF_INFOf,
   4210                             ts_pll_params[index].ref_freq_info));
   4211 
   4212         /* Take out of reset */
   4213         SOC_IF_ERROR_RETURN
   4214             (soc_reg_field32_modify(unit, TOP_SOFT_RESET_REG_2r, REG_PORT_ANY,
   4215                                     TOP_TS_PLL_RST_Lf, 1));
   4216 
   4217         /* Give time to lock */
   4218         sal_usleep(to_usec);
   4219 
   4220         /* Check PLL lock status */
   4221         reg = TOP_TS_PLL_STATUSr;
   4222         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4223         if (SAL_BOOT_SIMULATION ||
   4224                 soc_reg_field_get(unit, reg, rval, PLL_LOCKf)) {
   4225             if (ref_freq == auto_ref && dco_code_target == dco_poison) {
   4226                 /* If auto freq, get DCO value for later comparison */
   4227                 SOC_IF_ERROR_RETURN(
   4228                     _soc_trident3_pll_dco_code_get(unit, SOC_TD3_TS_PLL,
   4229                                                     &dco_code_target));
   4230                 _soc_td3_pll_dco_normalize(&dco_code_target,
   4231                                             ts_pll_params[index].ref_freq,
   4232                                             ts_pll_params[index].ndiv);
   4233 
   4234                 /* Start iterating over all of the available frequencies */
   4235                 index = -1;
   4236             } else if (ref_freq == auto_ref) {
   4237                 /* Make sure the current DCO code is close to the target */
   4238                 SOC_IF_ERROR_RETURN(
   4239                     _soc_trident3_pll_dco_code_get(unit, SOC_TD3_TS_PLL,
   4240                                                     &dco_code));
   4241 
   4242                 _soc_td3_pll_dco_normalize(&dco_code,
   4243                                             ts_pll_params[index].ref_freq,
   4244                                             ts_pll_params[index].ndiv);
   4245 
   4246                 if (dco_code >= (dco_code_target - 400) &&
   4247                         dco_code <= (dco_code_target + 400)) {
   4248                     if (ts_pll_params[index].ref_freq) {
   4249                         LOG_WARN(BSL_LS_SOC_COMMON,
   4250                             (BSL_META_U(unit,
   4251                                 "TS_PLL locked on unit %d using "
   4252                                 "%d.%dMHz external reference clock\n"
   4253                                 "Recommended to add \"%s=%u\" "
   4254                                 "config variable\n"),
   4255                                 unit,
   4256                                 ts_pll_params[index].ref_freq / 1000000,
   4257                                 ts_pll_params[index].ref_freq / 100000 % 10,
   4258                                 spn_PTP_TS_PLL_FREF,
   4259                                 ts_pll_params[index].ref_freq));
   4260                     } else {
   4261                         LOG_WARN(BSL_LS_SOC_COMMON,
   4262                             (BSL_META_U(unit, "TS_PLL locked on unit %d using "
   4263                                 "internal reference clock\n"), unit));
   4264                     }
   4265                     break;
   4266                 } else {
   4267                     continue;
   4268                 }
   4269             } else {
   4270                 /* PLL locked at desired frequency */
   4271                 break;
   4272             }
   4273         } else if (ref_freq != auto_ref) {
   4274             /* Not able to lock at desired frequency */
   4275             LOG_ERROR(BSL_LS_SOC_COMMON,
   4276                 (BSL_META_U(unit,
   4277                     "TS_PLL failed to lock on unit %d "
   4278                     "status = 0x%08x\n"), unit, rval));
   4279             return SOC_E_INIT;
   4280         }
   4281     }
   4282 
   4283     /* Bring up BS0 PLL */
   4284     ref_freq = soc_property_suffix_num_get(unit, 0, spn_PTP_BS_FREF,
   4285                                            &blank, auto_ref);
   4286     index = (ref_freq == auto_ref) ? (COUNTOF(bs_pll_params) - 1) : 0;
   4287     dco_code_target = dco_poison;
   4288 
   4289     for (; index < COUNTOF(bs_pll_params); index++) {
   4290         if (ref_freq != auto_ref &&
   4291                 bs_pll_params[index].ref_freq != ref_freq) {
   4292             continue;
   4293         }
   4294 
   4295         /* Place in reset */
   4296         SOC_IF_ERROR_RETURN
   4297             (soc_reg_field32_modify(unit, TOP_SOFT_RESET_REG_2r, REG_PORT_ANY,
   4298                                     TOP_BS_PLL0_RST_Lf, 0));
   4299 
   4300         /* Set N-divider value */
   4301         SOC_IF_ERROR_RETURN
   4302             (soc_reg_field32_modify(unit, TOP_BS_PLL0_CTRL_0r, REG_PORT_ANY,
   4303                                     NDIV_INTf, bs_pll_params[index].ndiv));
   4304 
   4305         /* Select internal or external clock source */
   4306         SOC_IF_ERROR_RETURN
   4307             (soc_reg_field32_modify(unit, TOP_BS_PLL0_CTRL_2r, REG_PORT_ANY,
   4308                             REFCLK_SOURCE_SELf,
   4309                             bs_pll_params[index].ref_freq == 0 ? 0 : 1));
   4310 
   4311         /* Set new reference frequency info */
   4312         SOC_IF_ERROR_RETURN
   4313             (soc_reg_field32_modify(unit, TOP_BS_PLL0_CTRL_3r, REG_PORT_ANY,
   4314                             FREFEFF_INFOf,
   4315                             bs_pll_params[index].ref_freq_info));
   4316 
   4317         /* Take out of reset */
   4318         SOC_IF_ERROR_RETURN
   4319             (soc_reg_field32_modify(unit, TOP_SOFT_RESET_REG_2r, REG_PORT_ANY,
   4320                                     TOP_BS_PLL0_RST_Lf, 1));
   4321 
   4322         /* Give time to lock */
   4323         sal_usleep(to_usec);
   4324 
   4325         /* Check PLL lock status */
   4326         reg = TOP_TS_PLL_STATUSr;
   4327         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4328         if (SAL_BOOT_SIMULATION ||
   4329                 soc_reg_field_get(unit, reg, rval, PLL_LOCKf)) {
   4330             if (ref_freq == auto_ref && dco_code_target == dco_poison) {
   4331                 /* If auto freq, get DCO value for later comparison */
   4332                 SOC_IF_ERROR_RETURN(
   4333                     _soc_trident3_pll_dco_code_get(unit, SOC_TD3_BS_PLL0,
   4334                                                     &dco_code_target));
   4335                 _soc_td3_pll_dco_normalize(&dco_code_target,
   4336                                             bs_pll_params[index].ref_freq,
   4337                                             bs_pll_params[index].ndiv);
   4338 
   4339                 /* Start iterating over all of the available frequencies */
   4340                 index = -1;
   4341             } else if (ref_freq == auto_ref) {
   4342                 /* Make sure the current DCO code is close to the target */
   4343                 SOC_IF_ERROR_RETURN(
   4344                     _soc_trident3_pll_dco_code_get(unit, SOC_TD3_BS_PLL0,
   4345                                                     &dco_code));
   4346                 _soc_td3_pll_dco_normalize(&dco_code,
   4347                                             bs_pll_params[index].ref_freq,
   4348                                             bs_pll_params[index].ndiv);
   4349 
   4350                 /* LOG_WARN(BSL_LS_SOC_COMMON,
   4351                     (BSL_META_U(unit,
   4352                         "BS_PLL0: %d %d %d\n"),
   4353                         bs_pll_params[index].ref_freq,
   4354                         dco_code,
   4355                         dco_code_target)); */
   4356 
   4357                 if (dco_code >= (dco_code_target - 400) &&
   4358                         dco_code <= (dco_code_target + 400)) {
   4359                     if (bs_pll_params[index].ref_freq) {
   4360                         LOG_WARN(BSL_LS_SOC_COMMON,
   4361                             (BSL_META_U(unit,
   4362                                 "BS_PLL0 locked on unit %d using "
   4363                                 "%d.%dMHz external reference clock\n"
   4364                                 "Recommended to add \"%s_0=%u\" "
   4365                                 "config variable\n"),
   4366                                 unit,
   4367                                 bs_pll_params[index].ref_freq / 1000000,
   4368                                 bs_pll_params[index].ref_freq / 100000 % 10,
   4369                                 spn_PTP_BS_FREF,
   4370                                 bs_pll_params[index].ref_freq));
   4371                     } else {
   4372                         LOG_WARN(BSL_LS_SOC_COMMON,
   4373                             (BSL_META_U(unit, "BS_PLL0 locked on unit %d using "
   4374                                 "internal reference clock\n"), unit));
   4375                     }
   4376                     break;
   4377                 } else {
   4378                     continue;
   4379                 }
   4380             } else {
   4381                 /* PLL locked at desired frequency */
   4382                 break;
   4383             }
   4384         } else if (ref_freq != auto_ref) {
   4385             /* Not able to lock at desired frequency */
   4386             LOG_ERROR(BSL_LS_SOC_COMMON,
   4387                 (BSL_META_U(unit,
   4388                     "BS_PLL0 failed to lock on unit %d "
   4389                     "status = 0x%08x\n"), unit, rval));
   4390             return SOC_E_INIT;
   4391         }
   4392     }
   4393 
   4394     /* Bring up BS1 PLL */
   4395     ref_freq = soc_property_suffix_num_get(unit, 1, spn_PTP_BS_FREF,
   4396                                            &blank, auto_ref);
   4397     index = (ref_freq == auto_ref) ? (COUNTOF(bs_pll_params) - 1) : 0;
   4398     dco_code_target = dco_poison;
   4399 
   4400     for (; index < COUNTOF(bs_pll_params); index++) {
   4401         if (ref_freq != auto_ref &&
   4402                 bs_pll_params[index].ref_freq != ref_freq) {
   4403             continue;
   4404         }
   4405 
   4406         /* Place in reset */
   4407         SOC_IF_ERROR_RETURN
   4408             (soc_reg_field32_modify(unit, TOP_SOFT_RESET_REG_2r, REG_PORT_ANY,
   4409                                     TOP_BS_PLL1_RST_Lf, 0));
   4410 
   4411         /* Set N-divider value */
   4412         SOC_IF_ERROR_RETURN
   4413             (soc_reg_field32_modify(unit, TOP_BS_PLL1_CTRL_0r, REG_PORT_ANY,
   4414                                     NDIV_INTf, bs_pll_params[index].ndiv));
   4415 
   4416         /* Select internal or external clock source */
   4417         SOC_IF_ERROR_RETURN
   4418             (soc_reg_field32_modify(unit, TOP_BS_PLL1_CTRL_2r, REG_PORT_ANY,
   4419                             REFCLK_SOURCE_SELf,
   4420                             bs_pll_params[index].ref_freq == 0 ? 0 : 1));
   4421 
   4422         /* Set new reference frequency info */
   4423         SOC_IF_ERROR_RETURN
   4424             (soc_reg_field32_modify(unit, TOP_BS_PLL1_CTRL_3r, REG_PORT_ANY,
   4425                             FREFEFF_INFOf,
   4426                             bs_pll_params[index].ref_freq_info));
   4427 
   4428         /* Take out of reset */
   4429         SOC_IF_ERROR_RETURN
   4430             (soc_reg_field32_modify(unit, TOP_SOFT_RESET_REG_2r, REG_PORT_ANY,
   4431                                     TOP_BS_PLL1_RST_Lf, 1));
   4432 
   4433         /* Give time to lock */
   4434         sal_usleep(to_usec);
   4435 
   4436         /* Check PLL lock status */
   4437         reg = TOP_TS_PLL_STATUSr;
   4438         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4439         if (SAL_BOOT_SIMULATION ||
   4440                 soc_reg_field_get(unit, reg, rval, PLL_LOCKf)) {
   4441             if (ref_freq == auto_ref && dco_code_target == dco_poison) {
   4442                 /* If auto freq, get DCO value for later comparison */
   4443                 SOC_IF_ERROR_RETURN(
   4444                     _soc_trident3_pll_dco_code_get(unit, SOC_TD3_BS_PLL1,
   4445                                                     &dco_code_target));
   4446                 _soc_td3_pll_dco_normalize(&dco_code_target,
   4447                                             bs_pll_params[index].ref_freq,
   4448                                             bs_pll_params[index].ndiv);
   4449 
   4450                 /* Start iterating over all of the available frequencies */
   4451                 index = -1;
   4452             } else if (ref_freq == auto_ref) {
   4453                 /* Make sure the current DCO code is close to the target */
   4454                 SOC_IF_ERROR_RETURN(
   4455                     _soc_trident3_pll_dco_code_get(unit, SOC_TD3_BS_PLL1,
   4456                                                     &dco_code));
   4457                 _soc_td3_pll_dco_normalize(&dco_code,
   4458                                             bs_pll_params[index].ref_freq,
   4459                                             bs_pll_params[index].ndiv);
   4460 
   4461                 if (dco_code >= (dco_code_target - 400) &&
   4462                         dco_code <= (dco_code_target + 400)) {
   4463                     if (bs_pll_params[index].ref_freq) {
   4464                         LOG_WARN(BSL_LS_SOC_COMMON,
   4465                             (BSL_META_U(unit,
   4466                                 "BS_PLL1 locked on unit %d using "
   4467                                 "%d.%dMHz external reference clock\n"
   4468                                 "Recommended to add \"%s_1=%u\" "
   4469                                 "config variable\n"),
   4470                                 unit,
   4471                                 bs_pll_params[index].ref_freq / 1000000,
   4472                                 bs_pll_params[index].ref_freq / 100000 % 10,
   4473                                 spn_PTP_BS_FREF,
   4474                                 bs_pll_params[index].ref_freq));
   4475                     } else {
   4476                         LOG_WARN(BSL_LS_SOC_COMMON,
   4477                             (BSL_META_U(unit, "BS_PLL1 locked on unit %d using "
   4478                                 "internal reference clock\n"), unit));
   4479                     }
   4480                     break;
   4481                 } else {
   4482                     continue;
   4483                 }
   4484             } else {
   4485                 /* PLL locked at desired frequency */
   4486                 break;
   4487             }
   4488         } else if (ref_freq != auto_ref) {
   4489             /* Not able to lock at desired frequency */
   4490             LOG_ERROR(BSL_LS_SOC_COMMON,
   4491                 (BSL_META_U(unit,
   4492                     "BS_PLL1 failed to lock on unit %d "
   4493                     "status = 0x%08x\n"), unit, rval));
   4494             return SOC_E_INIT;
   4495         }
   4496     }
   4497 
   4498     /* De-assert TS PLL, BS PLL0/1 post reset and bring AVS out of reset */
   4499     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   4500     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   4501                        TOP_TS_PLL_POST_RST_Lf, 1);
   4502     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   4503                        TOP_BS_PLL0_POST_RST_Lf, 1);
   4504     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   4505                        TOP_BS_PLL1_POST_RST_Lf, 1);
   4506     soc_reg_field_set(unit,TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf, 1);
   4507     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   4508 
   4509     sal_usleep(to_usec);
   4510 
   4511     /* Enable high temperature interrupt monitoring.
   4512      * Default on: pvtmon[0-7] (enable all pvtmons). */
   4513     temp_mask = soc_property_get(unit, "temp_monitor_select",
   4514                                  ((1 << COUNTOF(temp_thr_reg)) - 1));
   4515     /* The above is a 8 bit mask to indicate which temp sensor to hook up to
   4516      * the interrupt. */
   4517     rval = 0;
   4518     for (index = 0; index <COUNTOF(temp_thr_reg); index++) {
   4519         uint32 trval;
   4520 
   4521         /* Temp = 434.10 - o_ADC_data * 0.53504
   4522          * data = (434.10 - temp)/0.53504 = (434100-(temp*1000))/535
   4523          * Note: Since this is a high temp value we can safely assume it to
   4524          * always be a +ive number. This is in degrees celcius.
   4525          */
   4526         temp_thr = soc_property_get(unit, temp_thr_prop[index],
   4527                                     _SOC_TD3_DEF_TEMP_MAX);
   4528         if (temp_thr > _SOC_TD3_TEMP_MAX) {
   4529             LOG_ERROR(BSL_LS_SOC_COMMON,
   4530                       (BSL_META_U(unit,
   4531                           "Unsupported temp value %d !! Max %d. Using %d.\n"),
   4532                           temp_thr, _SOC_TD3_TEMP_MAX, _SOC_TD3_DEF_TEMP_MAX));
   4533             temp_thr = _SOC_TD3_DEF_TEMP_MAX;
   4534         }
   4535         /* Convert temperature to config data */
   4536         temp_thr = (434100-(temp_thr*1000))/535;
   4537         SOC_IF_ERROR_RETURN
   4538             (soc_reg32_get(unit, temp_thr_reg[index], REG_PORT_ANY, 0, &trval));
   4539         soc_reg_field_set(unit, temp_thr_reg[index], &trval, MIN_THRESHOLDf,
   4540                           temp_thr);
   4541         SOC_IF_ERROR_RETURN
   4542             (soc_reg32_set(unit, temp_thr_reg[index], REG_PORT_ANY, 0, trval));
   4543         if (temp_mask & (1 << index)) {
   4544             rval |= (1 << ((index * 2) + 1)); /*2 bits per pvtmon, using min*/
   4545         }
   4546     }
   4547     soc_td3_temp_mon_mask[unit] = temp_mask;
   4548 
   4549     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_INTR_MASKr(unit, rval));
   4550     /* Enable temp mon interrupt */
   4551 #ifdef BCM_CMICX_SUPPORT
   4552     if (soc_feature(unit, soc_feature_cmicx)) {
   4553         
   4554         /* (void)soc_cmicm_intr3_enable(unit, 0x4); PVTMON_INTR bit 2 */
   4555     }
   4556 #endif
   4557 
   4558     /* Bring port blocks out of reset */
   4559     rval = 0;
   4560     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_PM32_RST_Lf, 1);
   4561     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_TS_RST_Lf, 1);
   4562     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval));
   4563     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_3r(unit, 0xffffffff));
   4564     sal_usleep(to_usec);
   4565 
   4566     /* Bring IP, EP, and MMU blocks out of reset */
   4567     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REGr(unit, &rval));
   4568     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_IP_RST_Lf, 1);
   4569     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_EP_RST_Lf, 1);
   4570     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_MMU_RST_Lf, 1);
   4571     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval));
   4572 
   4573     parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE);
   4574     if (parity_enable) {
   4575         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, IDB_SER_CONTROLr,
   4576                                                    REG_PORT_ANY,
   4577                                                    IS_TDM_ECC_ENf,1));
   4578         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, IDB_SER_CONTROLr,
   4579                                                    REG_PORT_ANY,
   4580                                                    CA_CPU_ECC_ENABLEf,1));
   4581         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, IDB_SER_CONTROLr,
   4582                                                    REG_PORT_ANY,
   4583                                                    CA_LPBK_ECC_ENABLEf,1));
   4584     }
   4585 
   4586     sal_usleep(to_usec);
   4587     SOC_IF_ERROR_RETURN(soc_trident3_init_idb_memory(unit));
   4588     SOC_IF_ERROR_RETURN(_soc_trident3_init_hash_control_reset(unit));
   4589     SOC_IF_ERROR_RETURN(soc_trident3_uft_uat_config(unit));
   4590 
   4591     if (!SOC_IS_RELOADING(unit) && !SOC_WARM_BOOT(unit)) {
   4592         SOC_IF_ERROR_RETURN(soc_trident3_clear_all_memory(unit));
   4593     }
   4594 
   4595     if (soc_feature(unit, soc_feature_turbo_boot)) {
   4596         uint32 def_val = 0;
   4597 
   4598         if (!(SOC_CONTROL(unit)->soc_flags & SOC_F_ALL_MODULES_INITED)) {
   4599             def_val = 1;
   4600         }
   4601         if (soc_property_get(unit, "clear_on_hw_resetting", def_val)) {
   4602             SOC_HW_RESET_START(unit);
   4603         }
   4604     }
   4605 
   4606     return SOC_E_NONE;
   4607 }
   4608 
   4609 
   4610 
   4611 int
   4612 soc_trident3_port_reset(int unit)
   4613 {
   4614     int blk, port;
   4615     uint32 rval;
   4616     uint64 rval64;
   4617     int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100;
   4618 
   4619     if (soc_feature(unit, soc_feature_pm_refclk_master)) {
   4620         soc_info_t *si = &SOC_INFO(unit);
   4621         if (!SHR_BITNULL_RANGE(si->pm_ref_master_bitmap, 0,
   4622                                  SOC_MAX_NUM_BLKS)) {
   4623             soc_xgxs_reset_master_tsc(unit);
   4624         }
   4625     }
   4626 
   4627     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
   4628         port = SOC_BLOCK_PORT(unit, blk);
   4629 
   4630         SOC_IF_ERROR_RETURN(READ_CLPORT_MAC_CONTROLr(unit, port, &rval));
   4631         soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1);
   4632         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, port, rval));
   4633         sal_udelay(10);
   4634         soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0);
   4635         if (soc_reg_field_valid(unit, CLPORT_MAC_CONTROLr, SYS_16B_INTF_MODEf) &&
   4636             soc_feature(unit, soc_feature_clmac_16byte_interface_mode)) {
   4637             soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, SYS_16B_INTF_MODEf, 1);
   4638         }
   4639         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, port, rval));
   4640     }
   4641 
   4642     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   4643         port = SOC_BLOCK_PORT(unit, blk);
   4644 
   4645         SOC_IF_ERROR_RETURN(soc_reg_get(unit, XLPORT_XGXS0_CTRL_REGr,
   4646                                         port, 0, &rval64));
   4647         soc_reg64_field32_set(unit, XLPORT_XGXS0_CTRL_REGr, &rval64,
   4648                                         REFSELf, 3);
   4649         SOC_IF_ERROR_RETURN(soc_reg_set(unit, XLPORT_XGXS0_CTRL_REGr,
   4650                                         port, 0, rval64));
   4651 
   4652         SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_CONTROLr(unit, port, &rval));
   4653         soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1);
   4654         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval));
   4655         sal_udelay(10);
   4656         soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0);
   4657         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval));
   4658     }
   4659 
   4660     /* Power off CLPORT blocks */
   4661     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
   4662         port = SOC_BLOCK_PORT(unit, blk);
   4663         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 1));
   4664     }
   4665     sal_usleep(sleep_usec + 10000);
   4666     /* Power on CLPORT blocks */
   4667     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
   4668         port = SOC_BLOCK_PORT(unit, blk);
   4669         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 0));
   4670     }
   4671 
   4672     /* Power off XLPORT blocks */
   4673     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   4674         port = SOC_BLOCK_PORT(unit, blk);
   4675         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 1));
   4676     }
   4677     sal_usleep(sleep_usec + 10000);
   4678     /* Power off XLPORT blocks */
   4679     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   4680         port = SOC_BLOCK_PORT(unit, blk);
   4681         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 0));
   4682     }
   4683     return SOC_E_NONE;
   4684 }
   4685 
   4686 int
   4687 soc_trident3_port_speed_update(int unit, soc_port_t port, int speed)
   4688 {
   4689     soc_info_t *si;
   4690     soc_reg_t reg;
   4691     soc_field_t field;
   4692     uint32 rval, fval, mode;
   4693     uint64 rval64;
   4694     uint32 entry[SOC_MAX_MEM_WORDS];
   4695     int pipe, phy_port;
   4696     int p, count = 1, ports[2] = {-1, -1};
   4697 #if defined(BCM_TD3_ASF_EXCLUDE)
   4698     int class;
   4699 #else
   4700     int rv;
   4701 #endif
   4702 
   4703     static soc_field_t egr_reset_fields[] = {
   4704         PM0_RESETf, PM1_RESETf, PM2_RESETf, PM3_RESETf,
   4705         PM4_RESETf, PM5_RESETf, PM6_RESETf, PM7_RESETf
   4706     };
   4707 
   4708     si = &SOC_INFO(unit);
   4709     phy_port = si->port_l2p_mapping[port];
   4710 #if 0
   4711     mmu_port = si->port_p2m_mapping[phy_port];
   4712 #endif
   4713     pipe = si->port_pipe[port];
   4714 
   4715     /* Special handling for single lane and tri mode ports */
   4716     if (si->port_num_lanes[port] < 4) {
   4717         /* Get the current mode */
   4718         SOC_IF_ERROR_RETURN(READ_CLPORT_MODE_REGr(unit, port, &rval));
   4719         mode = soc_reg_field_get(unit, CLPORT_MODE_REGr, rval,
   4720                                  XPORT0_CORE_PORT_MODEf);
   4721 
   4722         /* Figure out the number of ports that will be affected */
   4723         switch (mode) {
   4724         case SOC_TD3_PORT_MODE_QUAD:
   4725             count = 2;
   4726             break;
   4727         case SOC_TD3_PORT_MODE_TRI_012:
   4728             count = SOC_PORT_BINDEX(unit, phy_port) > 1 ? 1 : 2;
   4729             break;
   4730         case SOC_TD3_PORT_MODE_TRI_023:
   4731             count = SOC_PORT_BINDEX(unit, phy_port) > 1 ? 2 : 1;
   4732             break;
   4733         default:
   4734             break;
   4735         }
   4736 
   4737         /* Setup the list of ports to be updated */
   4738         if (SOC_PORT_BINDEX(unit, phy_port) % 2) {
   4739             ports[1] = port;
   4740             ports[0] = si->port_l2p_mapping[phy_port-1];
   4741         } else {
   4742             ports[0] = port; /* This will handle 2xdual lane mode as well */
   4743             ports[1] = si->port_l2p_mapping[phy_port+1];
   4744         }
   4745     } else {
   4746         ports[0] = port;
   4747     }
   4748 
   4749     /* Update MMU and EP credits */
   4750     /* De-assert EGR_ENABLE */
   4751     sal_memset(&entry, 0, sizeof(entry));
   4752     for (p = 0; p < count; p++) {
   4753         if (ports[p] < 0) {
   4754             continue;
   4755         }
   4756         SOC_IF_ERROR_RETURN
   4757             (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, si->port_l2p_mapping[ports[p]], &entry));
   4758     }
   4759 
   4760     /* Clear MMU port credit before Resetting egress */
   4761     reg = MMU_PORT_CREDITr;
   4762     for (p = 0; p < count; p++) {
   4763         if (ports[p] < 0) {
   4764             continue;
   4765         }
   4766         rval = 0;
   4767         soc_reg_field_set(unit, reg, &rval, INITIALIZEf, 1);
   4768         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, ports[p], 0, rval));
   4769         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, ports[p], 0, 0));
   4770     }
   4771 
   4772 #if defined(BCM_TD3_ASF_EXCLUDE)
   4773     if (IS_CL_PORT(unit, port)) {
   4774         /* Update cut-through speed class */
   4775         SOC_IF_ERROR_RETURN(READ_ASF_EPORT_CFGr(unit, port, &rval));
   4776         if (soc_reg_field_get(unit, ASF_EPORT_CFGr, rval, ENABLEf)) {
   4777             _soc_trident3_speed_to_ct_class_mapping(unit, speed, &class);
   4778 
   4779             rval = 0;
   4780             soc_reg_field_set(unit, ASF_IPORT_CFGr, &rval, ASF_PORT_SPEEDf,
   4781                               class);
   4782             SOC_IF_ERROR_RETURN(WRITE_ASF_IPORT_CFGr(unit, port, rval));
   4783 
   4784             sal_memset(entry, 0, sizeof(egr_ip_cut_thru_class_entry_t));
   4785             soc_mem_field32_set(unit, EGR_IP_CUT_THRU_CLASSm, entry,
   4786                                 CUT_THRU_CLASSf, class);
   4787             SOC_IF_ERROR_RETURN
   4788                 (soc_mem_write(unit, EGR_IP_CUT_THRU_CLASSm, MEM_BLOCK_ALL,
   4789                                port, entry));
   4790         }
   4791     }
   4792 #endif
   4793 
   4794     /* Updtae HSP port multicast T2OQ setting */
   4795 #if 0
   4796     if (SOC_PBMP_MEMBER(si->eq_pbm, port)) {
   4797         int inst;
   4798         static soc_field_t t2oq_fields[] = {
   4799             IS_MC_T2OQ_PORT0f, IS_MC_T2OQ_PORT1f
   4800         };
   4801         reg = MMU_SCFG_TOQ_MC_CFG1r;
   4802         inst = (pipe >> 1) | SOC_REG_ADDR_INSTANCE_MASK;
   4803         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval));
   4804         field = t2oq_fields[pipe & 0x01];
   4805         fval = soc_reg_field_get(unit, reg, rval, field);
   4806         if (speed >= 40000) {
   4807             fval |= 1 << (mmu_port & 0x0f);
   4808         } else {
   4809             fval &= ~(1 << (mmu_port & 0x0f));
   4810         }
   4811         soc_reg_field_set(unit, reg, &rval, field, fval);
   4812         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   4813     }
   4814 #endif
   4815 
   4816 #if !defined(BCM_TD3_ASF_EXCLUDE)
   4817     if (soc_feature(unit, soc_feature_asf_multimode)) {
   4818         rv = soc_td3_port_asf_mode_set(unit, port,
   4819                  speed, _SOC_TD3_ASF_MODE_CFG_UPDATE);
   4820         if ((SOC_E_NONE != rv) && (SOC_E_UNAVAIL != rv)) {
   4821             return rv;
   4822         }
   4823     }
   4824 #endif
   4825 
   4826     /* Reset egress hardware resource */
   4827     reg = SOC_REG_UNIQUE_ACC(unit, EGR_PORT_BUFFER_SFT_RESET_0r)[pipe];
   4828     field = egr_reset_fields[si->port_serdes[port] % 8];
   4829     if (4 == si->port_num_lanes[port]) {
   4830         /* reset all 4 lanes */
   4831         fval = 4;
   4832     } else if (SOC_PORT_BINDEX(unit, phy_port) < 2) { /* reset lanes 0 and 1 */
   4833         fval = 1;
   4834     } else { /* reset lanes 2 and 3 */
   4835         fval = 2;
   4836     }
   4837     SOC_IF_ERROR_RETURN
   4838         (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64));
   4839     soc_reg64_field32_set(unit, reg, &rval64, field, fval);
   4840     SOC_IF_ERROR_RETURN(soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval64));
   4841     soc_reg64_field32_set(unit, reg, &rval64, field, 0);
   4842     SOC_IF_ERROR_RETURN(soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval64));
   4843 
   4844     /* Enable egress */
   4845     sal_memset(entry, 0, sizeof(egr_enable_entry_t));
   4846     soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 1);
   4847     for (p = 0; p < count; p++) {
   4848         if (ports[p] < 0) {
   4849             continue;
   4850         }
   4851         SOC_IF_ERROR_RETURN
   4852             (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, si->port_l2p_mapping[ports[p]], entry));
   4853     }
   4854     return SOC_E_NONE;
   4855 }
   4856 
   4857 int
   4858 soc_trident3_xpe_base_index_check(int unit, int base_type, int xpe,
   4859                                   int base_index, char *msg)
   4860 {
   4861     soc_info_t *si;
   4862     int pipe;
   4863     uint32 map;
   4864     char *base_name;
   4865 
   4866     si = &SOC_INFO(unit);
   4867 
   4868     if (xpe == -1 || base_index == -1) {
   4869         return SOC_E_NONE;
   4870     }
   4871 
   4872     if (xpe < NUM_XPE(unit) && si->xpe_ipipe_map[xpe] == 0) {
   4873         if (msg) {
   4874             LOG_CLI((BSL_META_U(unit,
   4875                                 "%s: XPE%d is not in config\n"),
   4876                      msg, xpe));
   4877         }
   4878         return SOC_E_PARAM;
   4879     }
   4880 
   4881     switch (base_type) {
   4882     case 0: /* IPORT */
   4883     case 1: /* EPORT */
   4884         base_name = base_type == 0 ? "IPORT" : "EPORT";
   4885         pipe = si->port_pipe[base_index];
   4886         if (pipe == -1) {
   4887             if (msg) {
   4888                 LOG_CLI((BSL_META_U(unit,
   4889                                     "%s: %s%d is not in config\n"),
   4890                          msg, base_name, base_index));
   4891             }
   4892         } else if (xpe < NUM_XPE(unit)) { /* Unique access type */
   4893             map = base_type == 0 ?
   4894                 si->ipipe_xpe_map[pipe] : si->epipe_xpe_map[pipe];
   4895             if (map & (1 << xpe)) {
   4896                 break;
   4897             }
   4898             if (msg != NULL) {
   4899                 LOG_CLI((BSL_META_U(unit,
   4900                                     "%s: %s%d is not in XPE%d\n"),
   4901                          msg, base_name, base_index, xpe));
   4902             }
   4903         } else {
   4904             break;
   4905         }
   4906         return SOC_E_PARAM;
   4907     case 2: /* IPIPE */
   4908     case 3: /* EPIPE */
   4909         if (base_type == 2) {
   4910             base_name = "IPIPE";
   4911             map = si->ipipe_xpe_map[base_index];
   4912         } else {
   4913             base_name = "EPIPE";
   4914             map = si->epipe_xpe_map[base_index];
   4915         }
   4916         if (map == 0) {
   4917             if (msg) {
   4918                 LOG_CLI((BSL_META_U(unit,
   4919                                     "%s: %s%d is not in config\n"),
   4920                          msg, base_name, base_index));
   4921             }
   4922         } else if (xpe < NUM_XPE(unit)) { /* Unique access type */
   4923             if (map & (1 << xpe)) {
   4924                 break;
   4925             }
   4926             if (msg != NULL) {
   4927                 LOG_CLI((BSL_META_U(unit,
   4928                                     "%s: %s%d is not in XPE%d\n"),
   4929                          msg, base_name, base_index, xpe));
   4930             }
   4931         } else {
   4932             break;
   4933         }
   4934         return SOC_E_PARAM;
   4935     case 4: /* CHIP */
   4936         break;
   4937     case 5: /* XPE */
   4938         if (si->xpe_ipipe_map[base_index] != 0) {
   4939             break;
   4940         }
   4941         if (msg != NULL) {
   4942             LOG_CLI((BSL_META_U(unit,
   4943                                 "%s: XPE%d is not in config\n"),
   4944                      msg, base_index));
   4945         }
   4946         return SOC_E_PARAM;
   4947     case 6: /* SLICE */
   4948         if (si->sc_ipipe_map[base_index] == 0) {
   4949                 LOG_CLI((BSL_META_U(unit,
   4950                                     "%s: SLICE%d is not in config\n"),
   4951                          msg, base_index));
   4952         } else if (xpe < NUM_XPE(unit)) { /* Unique access type */
   4953             if (xpe & 1) { /* XPE 1 and 3 are in slice 1 */
   4954                 if (base_index == 1) {
   4955                     break;
   4956                 }
   4957             } else { /* XPE 0 and 2 are in slice 0 */
   4958                 if (base_index == 0) {
   4959                     break;
   4960                 }
   4961             }
   4962             if (msg != NULL) {
   4963                 LOG_CLI((BSL_META_U(unit,
   4964                                     "%s: XPE%d is not in SLICE%d\n"),
   4965                          msg, xpe, base_index));
   4966             }
   4967         } else {
   4968             break;
   4969         }
   4970         return SOC_E_PARAM;
   4971     case 7: /* LAYER */
   4972         if (xpe & 2) { /* XPE 2 and 3 are in layer 1 */
   4973             if (base_index == 1) {
   4974                 break;
   4975             }
   4976         } else { /* XPE 0 and 1 are in layer 0 */
   4977             if (base_index == 0) {
   4978                 break;
   4979             }
   4980         }
   4981         if (msg) {
   4982             LOG_CLI((BSL_META_U(unit,
   4983                                 "%s: XPE%d is not in LAYER%d\n"),
   4984                      msg, xpe, base_index));
   4985         }
   4986         return SOC_E_PARAM;
   4987     }
   4988 
   4989     return SOC_E_NONE;
   4990 }
   4991 
   4992 int soc_trident3_get_alpm_banks(int unit)
   4993 {
   4994     return num_shared_alpm_banks[unit];
   4995 }
   4996 
   4997 int soc_trident3_set_alpm_banks(int unit, int banks)
   4998 {
   4999     num_shared_alpm_banks[unit] = banks;
   5000     return 0;
   5001 }
   5002 
   5003 int soc_trident3_alpm_mode_get(int unit)
   5004 {
   5005     return _soc_alpm_mode[unit];
   5006 }
   5007 
   5008 int soc_trident3_mem_basetype_get(int unit, soc_mem_t mem)
   5009 {
   5010     int base_type;
   5011 
   5012     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   5013     return base_type;
   5014 }
   5015 
   5016 int soc_trident3_mem_is_xpe(int unit, soc_mem_t mem)
   5017 {
   5018     int block_info_index;
   5019 
   5020     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
   5021 
   5022     if (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_XPE) {
   5023         return 1;
   5024     } else {
   5025         return 0;
   5026     }
   5027 }
   5028 
   5029 /* Function to check if given XPE/PIPE combo matches for the given mem's base
   5030  * type definition.
   5031  */
   5032 int
   5033 soc_trident3_mem_xpe_pipe_check(int unit, soc_mem_t mem, int xpe, int pipe)
   5034 {
   5035     int rv = SOC_E_NONE;
   5036     int block_info_index, base_type;
   5037 
   5038     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
   5039     if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_XPE) {
   5040         return SOC_E_PARAM;
   5041     }
   5042 
   5043     base_type = soc_trident3_mem_basetype_get(unit, mem);
   5044     rv = soc_trident3_xpe_base_index_check(unit, base_type, xpe, pipe, NULL);
   5045 
   5046     if (rv == SOC_E_PARAM) {
   5047         rv = SOC_E_UNAVAIL;
   5048     }
   5049 
   5050     return rv;
   5051 }
   5052 
   5053 STATIC int
   5054 _soc_trident3_xpe_reg_check(int unit, soc_reg_t reg, int xpe, int base_index)
   5055 {
   5056     int acc_type, base_type;
   5057 
   5058     if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_XPE)) {
   5059         LOG_CLI((BSL_META_U(unit,
   5060                             "%s is not XPE register\n"), SOC_REG_NAME(unit, reg)));
   5061         return SOC_E_PARAM;
   5062     }
   5063 
   5064     if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */
   5065         if (xpe == -1 || xpe >= NUM_XPE(unit)) {
   5066             LOG_CLI((BSL_META_U(unit,
   5067                                 "%s bad XPE value %d\n"),
   5068                      SOC_REG_NAME(unit, reg), xpe));
   5069             return SOC_E_PARAM;
   5070         }
   5071     } else {
   5072         acc_type = SOC_REG_ACC_TYPE(unit, reg);
   5073         if (acc_type < NUM_XPE(unit)) { /* UNIQUE per XPE register */
   5074             if (xpe != acc_type) {
   5075                 LOG_CLI((BSL_META_U(unit,
   5076                                     "Ovveride XPE value %d with ACC_TYPE of %s\n"),
   5077                          xpe, SOC_REG_NAME(unit, reg)));
   5078             }
   5079             xpe = acc_type;
   5080         } else { /* non-UNIQUE register */
   5081             return SOC_E_NONE;
   5082         }
   5083     }
   5084     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   5085 
   5086     return soc_trident3_xpe_base_index_check(unit, base_type, xpe, base_index,
   5087                                              SOC_REG_NAME(unit, reg));
   5088 }
   5089 
   5090 #if 0
   5091 STATIC int
   5092 _soc_trident3_xpe_mem_check(int unit, soc_mem_t mem, int xpe, int base_index)
   5093 {
   5094     int block_info_index, acc_type, base_type;
   5095 
   5096     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
   5097     if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_XPE) {
   5098         LOG_CLI((BSL_META_U(unit,
   5099                             "%s is not XPE register\n"), SOC_MEM_NAME(unit, mem)));
   5100         return SOC_E_PARAM;
   5101     }
   5102 
   5103     if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { /* UNIQUE base memory */
   5104         if (xpe == -1 || xpe >= NUM_XPE(unit)) {
   5105             LOG_CLI((BSL_META_U(unit,
   5106                                 "%s bad XPE value %d\n"),
   5107                      SOC_MEM_NAME(unit, mem), xpe));
   5108             return SOC_E_PARAM;
   5109         }
   5110     } else {
   5111         acc_type = SOC_MEM_ACC_TYPE(unit, mem);
   5112         if (acc_type < NUM_XPE(unit)) { /* UNIQUE per XPE memory */
   5113             if (xpe != acc_type) {
   5114                 LOG_CLI((BSL_META_U(unit,
   5115                                     "Ovveride XPE value %d with ACC_TYPE of %s\n"),
   5116                          xpe, SOC_MEM_NAME(unit, mem)));
   5117                 xpe = acc_type;
   5118             }
   5119         } else { /* non-UNIQUE memory */
   5120             return SOC_E_NONE;
   5121         }
   5122     }
   5123     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   5124 
   5125     return soc_trident3_xpe_base_index_check(unit, base_type, xpe, base_index,
   5126                                              SOC_MEM_NAME(unit, mem));
   5127 }
   5128 #endif
   5129 
   5130 /*
   5131  * Parameters for soc_trident3_xpe_reg_access and soc_trident3_xpe_mem_access:
   5132  *
   5133  *    base unique  reg/  xpe   write action          read action
   5134  *   index  type   mem
   5135  *    ==== ====== ===== ===   ================      =================
   5136  * #1   -1  no     -     -    all XPEs/pipes        first pipe in the first XPE
   5137  * #2   -1  yes   base   -1   (same as #1)
   5138  * #3   -1  yes   base  0-3   all pipes in the XPE  first pipe in the XPE
   5139  * #4   -1  yes  xpe0-3  -    (same as #3)
   5140  * #5  0-3  no     -     -    applicable XPEs       first XPE has the pipe
   5141  * #6  0-3  yes   base   -1   (same as #5)
   5142  * #7  0-3  yes   base  0-3   the XPE/pipe          the XPE/pipe
   5143  * #8  0-3  yes  xpe0-3  -    (same as #7)
   5144  *
   5145  * - S/W will loop through base types (i.e. pipes) if base_index==-1
   5146  * - S/W will loop through applicable XPEs if xpe==-1 on unique access type
   5147  *   base view (H/W will do the loop for other access types)
   5148  * - base_index will be ignored if the table does not have multiple sections
   5149  *   for example ACC_TYPE==UNIQUE BASE_TYPE==XPE
   5150  */
   5151 STATIC int
   5152 _soc_trident3_xpe_reg_access(int unit, soc_reg_t reg, int xpe, int base_index,
   5153                              int index, uint64 *data, int write)
   5154 {
   5155     soc_info_t *si;
   5156     soc_reg_t orig_reg;
   5157     int port;
   5158     int base_type, break_after_first;
   5159     int base_index_count;
   5160     uint32 base_index_map, xpe_map=0;
   5161     soc_pbmp_t base_index_pbmp;
   5162     uint32 inst;
   5163 
   5164     si = &SOC_INFO(unit);
   5165     orig_reg = reg;
   5166     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   5167     break_after_first = TRUE;
   5168 
   5169     if (xpe >= 0 && base_index >= 0) {
   5170         SOC_IF_ERROR_RETURN
   5171             (_soc_trident3_xpe_reg_check(unit, reg, xpe, base_index));
   5172     }
   5173 
   5174     switch (base_type) {
   5175     case 0: /* IPORT */
   5176     case 1: /* EPORT */
   5177         if (xpe >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
   5178             reg = SOC_REG_UNIQUE_ACC(unit, reg)[xpe];
   5179         }
   5180 
   5181         if (base_index == -1) {
   5182             SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit));
   5183         } else {
   5184             /* This argument is logical port, same as soc_reg_get/set */
   5185             SOC_PBMP_PORT_SET(base_index_pbmp, base_index);
   5186         }
   5187 
   5188         SOC_PBMP_ITER(base_index_pbmp, port) {
   5189             /* Loop through XPE(s) only on UNIQUE type base register */
   5190             if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   5191                 if (base_index < -1) {
   5192                     return SOC_E_PARAM;
   5193                 } else if (base_index == -1) {
   5194                     xpe_map = 0xf;
   5195                 } else {
   5196                     xpe_map = base_type == 0 ?
   5197                         si->ipipe_xpe_map[base_index] :
   5198                         si->epipe_xpe_map[base_index];
   5199                 }
   5200                 if (write) {
   5201                     break_after_first = FALSE;
   5202                 }
   5203             }
   5204             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   5205                 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   5206                     if (!(xpe_map & (1 << xpe))) {
   5207                         continue;
   5208                     }
   5209                     reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe];
   5210                 }
   5211                 if (write) {
   5212                     SOC_IF_ERROR_RETURN
   5213                         (soc_reg_set(unit, reg, port, index, *data));
   5214                 } else {
   5215                     SOC_IF_ERROR_RETURN
   5216                         (soc_reg_get(unit, reg, port, index, data));
   5217                 }
   5218                 if (break_after_first) {
   5219                     break;
   5220                 }
   5221             }
   5222         }
   5223         break;
   5224     case 2: /* IPIPE */
   5225     case 3: /* EPIPE */
   5226         if (xpe >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
   5227             reg = SOC_REG_UNIQUE_ACC(unit, reg)[xpe];
   5228         }
   5229 
   5230         soc_trident3_pipe_map_get(unit, &base_index_map);
   5231         if (base_index != -1) {
   5232             base_index_map &= 1 << base_index;
   5233             if (base_index_map == 0) {
   5234                 return SOC_E_PARAM;
   5235             }
   5236         }
   5237 
   5238         for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) {
   5239             if (!(base_index_map & (1 << base_index))) {
   5240                 continue;
   5241             }
   5242             /* Loop through XPE(s) only on UNIQUE type base register */
   5243             if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   5244                 xpe_map = base_type == 2 ?
   5245                     si->ipipe_xpe_map[base_index] :
   5246                     si->epipe_xpe_map[base_index];
   5247                 if (write) {
   5248                     break_after_first = FALSE;
   5249                 }
   5250             }
   5251             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   5252                 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   5253                     if (!(xpe_map & (1 << xpe))) {
   5254                         continue;
   5255                     }
   5256                     reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe];
   5257                 }
   5258                 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   5259                 if (write) {
   5260                     SOC_IF_ERROR_RETURN
   5261                         (soc_reg_set(unit, reg, inst, index, *data));
   5262                 } else {
   5263                     SOC_IF_ERROR_RETURN
   5264                         (soc_reg_get(unit, reg, inst, index, data));
   5265                 }
   5266                 if (break_after_first) {
   5267                     break;
   5268                 }
   5269             }
   5270         }
   5271         break;
   5272     case 4: /* CHIP */
   5273         if (write) {
   5274             SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data));
   5275         } else {
   5276             SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data));
   5277         }
   5278         break;
   5279     case 5: /* XPE */
   5280         if (xpe >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
   5281             reg = SOC_REG_UNIQUE_ACC(unit, reg)[xpe];
   5282         }
   5283 
   5284         if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL ||
   5285             SOC_REG_ACC_TYPE(unit, reg) < NUM_XPE(unit)) {
   5286             base_index_map = 1;
   5287         } else if (base_index == -1) {
   5288             base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   5289         } else {
   5290             base_index_map = 1 << base_index;
   5291         }
   5292 
   5293         /* Loop through XPE(s) only on UNIQUE type base register */
   5294         if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   5295             xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   5296             break_after_first = FALSE;
   5297         }
   5298 
   5299         for (base_index = 0; base_index < NUM_XPE(unit); base_index++) {
   5300             if (!(base_index_map & (1 << base_index))) {
   5301                 continue;
   5302             }
   5303             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   5304                 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   5305                     if (!(xpe_map & (1 << xpe))) {
   5306                         continue;
   5307                     }
   5308                     reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe];
   5309                 }
   5310                 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   5311                 if (write) {
   5312                     SOC_IF_ERROR_RETURN
   5313                         (soc_reg_set(unit, reg, inst, index, *data));
   5314                 } else {
   5315                     SOC_IF_ERROR_RETURN
   5316                         (soc_reg_get(unit, reg, inst, index, data));
   5317                 }
   5318                 if (break_after_first) {
   5319                     break;
   5320                 }
   5321             }
   5322         }
   5323         break;
   5324     case 6: /* SLICE */
   5325     case 7: /* LAYER */
   5326         /* No unique access type for such base_type */
   5327         if (base_index == -1) {
   5328             base_index_map = base_type == 6 ? si->ipipe_sc_map[0] : 0x3;
   5329         } else {
   5330             base_index_map = 1 << base_index;
   5331         }
   5332 
   5333         base_index_count = base_type == 6 ? NUM_SLICE(unit) : NUM_LAYER(unit);
   5334         for (base_index = 0; base_index < base_index_count; base_index++) {
   5335             if (!(base_index_map & (1 << base_index))) {
   5336                 continue;
   5337             }
   5338             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   5339             if (write) {
   5340                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   5341             } else {
   5342                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   5343             }
   5344         }
   5345         break;
   5346     /* No default case as base_type can have value only between 0-7 */
   5347     }
   5348 
   5349     return SOC_E_NONE;
   5350 }
   5351 #if 0
   5352 STATIC int
   5353 _soc_trident3_xpe_mem_access(int unit, soc_mem_t mem, int xpe, int base_index,
   5354                              int copyno, int offset_in_section,
   5355                              void *entry_data, int write)
   5356 {
   5357     soc_info_t *si;
   5358     soc_mem_t orig_mem;
   5359     int index, section_size;
   5360     int base_type, break_after_first;
   5361     uint32 base_index_map, xpe_map=0;
   5362 
   5363     si = &SOC_INFO(unit);
   5364     orig_mem = mem;
   5365     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   5366     section_size = SOC_MEM_INFO(unit, mem).section_size;
   5367     break_after_first = TRUE;
   5368 
   5369     if (xpe >= 0 && base_index >= 0) {
   5370         SOC_IF_ERROR_RETURN
   5371             (_soc_trident3_xpe_mem_check(unit, mem, xpe, base_index));
   5372     }
   5373 
   5374     switch (base_type) {
   5375     case 2: /* IPIPE */
   5376     case 3: /* EPIPE */
   5377         if (xpe >= 0 && SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) {
   5378             mem = SOC_MEM_UNIQUE_ACC(unit, mem)[xpe];
   5379         }
   5380 
   5381         /* All tables with such base_type should have multiple sections */
   5382         soc_trident3_pipe_map_get(unit, &base_index_map);
   5383         if (base_index != -1) {
   5384             base_index_map &= 1 << base_index;
   5385             if (base_index_map == 0) {
   5386                 return SOC_E_PARAM;
   5387             }
   5388         }
   5389 
   5390         for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) {
   5391             if (!(base_index_map & (1 << base_index))) {
   5392                 continue;
   5393             }
   5394             /* Loop through XPE(s) only on UNIQUE type base memory */
   5395             if (SOC_MEM_UNIQUE_ACC(unit, orig_mem) != NULL) {
   5396                 xpe_map = base_type == 2 ?
   5397                     si->ipipe_xpe_map[base_index] :
   5398                     si->epipe_xpe_map[base_index];
   5399                 if (write) {
   5400                     break_after_first = FALSE;
   5401                 }
   5402             }
   5403             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   5404                 if (SOC_MEM_UNIQUE_ACC(unit, orig_mem) != NULL) {
   5405                     if (!(xpe_map & (1 << xpe))) {
   5406                         continue;
   5407                     }
   5408                     mem = SOC_MEM_UNIQUE_ACC(unit, orig_mem)[xpe];
   5409                 }
   5410                 index = base_index * section_size + offset_in_section;
   5411                 if (write) {
   5412                     SOC_IF_ERROR_RETURN
   5413                         (soc_mem_write(unit, mem, copyno, index, entry_data));
   5414                 } else {
   5415                     SOC_IF_ERROR_RETURN
   5416                         (soc_mem_read(unit, mem, copyno, index, entry_data));
   5417                 }
   5418                 if (break_after_first) {
   5419                     break;
   5420                 }
   5421             }
   5422         }
   5423         break;
   5424     case 4: /* CHIP */
   5425         index = offset_in_section;
   5426         if (write) {
   5427             SOC_IF_ERROR_RETURN
   5428                 (soc_mem_write(unit, mem, copyno, index, entry_data));
   5429         } else {
   5430             SOC_IF_ERROR_RETURN
   5431                 (soc_mem_read(unit, mem, copyno, index, entry_data));
   5432         }
   5433         break;
   5434     case 5: /* XPE */
   5435         if (xpe >= 0 && SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) {
   5436             mem = SOC_MEM_UNIQUE_ACC(unit, mem)[xpe];
   5437         }
   5438 
   5439         if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL ||
   5440             SOC_MEM_ACC_TYPE(unit, mem) < NUM_XPE(unit)) {
   5441             /* Single section table handling for unique acc_type */
   5442             base_index_map = 1;
   5443         } else if (base_index == -1) {
   5444             base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   5445         } else {
   5446             base_index_map = 1 << base_index;
   5447         }
   5448 
   5449         /* Loop through XPE(s) only on UNIQUE type base memory */
   5450         if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) {
   5451             xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   5452             break_after_first = FALSE;
   5453         }
   5454 
   5455         for (base_index = 0; base_index < NUM_XPE(unit); base_index++) {
   5456             if (!(base_index_map & (1 << base_index))) {
   5457                 continue;
   5458             }
   5459             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   5460                 if (SOC_MEM_UNIQUE_ACC(unit, orig_mem) != NULL) {
   5461                     if (!(xpe_map & (1 << xpe))) {
   5462                         continue;
   5463                     }
   5464                     mem = SOC_MEM_UNIQUE_ACC(unit, orig_mem)[xpe];
   5465                 }
   5466                 index = base_index * section_size + offset_in_section;
   5467                 if (write) {
   5468                     SOC_IF_ERROR_RETURN
   5469                         (soc_mem_write(unit, mem, copyno, index, entry_data));
   5470                 } else {
   5471                     SOC_IF_ERROR_RETURN
   5472                         (soc_mem_read(unit, mem, copyno, index, entry_data));
   5473                 }
   5474                 if (break_after_first) {
   5475                     break;
   5476                 }
   5477             }
   5478         }
   5479         break;
   5480     case 6: /* SLICE */
   5481         /* No unique access type for such base_type */
   5482         if (base_index == -1) {
   5483             base_index_map = si->ipipe_sc_map[0];
   5484         } else {
   5485             base_index_map = 1 << base_index;
   5486         }
   5487 
   5488         for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) {
   5489             if (!(base_index_map & (1 << base_index))) {
   5490                 continue;
   5491             }
   5492             index = base_index * section_size + offset_in_section;
   5493             if (write) {
   5494                 SOC_IF_ERROR_RETURN
   5495                     (soc_mem_write(unit, mem, copyno, index, entry_data));
   5496             } else {
   5497                 SOC_IF_ERROR_RETURN
   5498                     (soc_mem_read(unit, mem, copyno, index, entry_data));
   5499             }
   5500         }
   5501         break;
   5502     case 0: /* IPORT */
   5503     case 1: /* EPORT */
   5504     case 7: /* LAYER */
   5505     default:
   5506         return SOC_E_INTERNAL;
   5507     }
   5508 
   5509     return SOC_E_NONE;
   5510 }
   5511 #endif
   5512 int
   5513 soc_trident3_sc_base_index_check(int unit, int base_type, int sc,
   5514                                  int base_index, char *msg)
   5515 {
   5516     soc_info_t *si;
   5517     int pipe;
   5518     uint32 map;
   5519     char *base_name;
   5520 
   5521     si = &SOC_INFO(unit);
   5522 
   5523     if (sc == -1 || base_index == -1) {
   5524         return SOC_E_NONE;
   5525     }
   5526 
   5527     if (sc < NUM_SLICE(unit) && si->sc_ipipe_map[sc] == 0) {
   5528         if (msg) {
   5529             LOG_CLI((BSL_META_U(unit,
   5530                                 "%s: SC%d is not in config\n"),
   5531                      msg, sc));
   5532         }
   5533         return SOC_E_PARAM;
   5534     }
   5535 
   5536     switch (base_type) {
   5537     case 0: /* IPORT */
   5538     case 1: /* EPORT */
   5539         base_name = base_type == 0 ? "IPORT" : "EPORT";
   5540         pipe = si->port_pipe[base_index];
   5541         if (pipe == -1) {
   5542             if (msg) {
   5543                 LOG_CLI((BSL_META_U(unit,
   5544                                     "%s: %s%d is not in config\n"),
   5545                          msg, base_name, base_index));
   5546             }
   5547         } else if (sc < NUM_SLICE(unit)) { /* Unique access type */
   5548             map = base_type == 0 ?
   5549                 si->ipipe_sc_map[pipe] : si->epipe_sc_map[pipe];
   5550             if (map & (1 << sc)) {
   5551                 break;
   5552             }
   5553             if (msg != NULL) {
   5554                 LOG_CLI((BSL_META_U(unit,
   5555                                     "%s: %s%d is not in SC%d\n"),
   5556                          msg, base_name, base_index, sc));
   5557             }
   5558         } else {
   5559             break;
   5560         }
   5561         return SOC_E_PARAM;
   5562     case 2: /* IPIPE */
   5563     case 3: /* EPIPE */
   5564         if (base_type == 2) {
   5565             base_name = "IPIPE";
   5566             map = si->ipipe_sc_map[base_index];
   5567         } else {
   5568             base_name = "EPIPE";
   5569             map = si->epipe_sc_map[base_index];
   5570         }
   5571         if (map == 0) {
   5572             if (msg) {
   5573                 LOG_CLI((BSL_META_U(unit,
   5574                                     "%s: %s%d is not in config\n"),
   5575                          msg, base_name, base_index));
   5576             }
   5577         } else if (sc < NUM_SLICE(unit)) { /* Unique access type */
   5578             if (map & (1 << sc)) {
   5579                 break;
   5580             }
   5581             if (msg != NULL) {
   5582                 LOG_CLI((BSL_META_U(unit,
   5583                                     "%s: %s%d is not in SC%d\n"),
   5584                          msg, base_name, base_index, sc));
   5585             }
   5586         } else {
   5587             break;
   5588         }
   5589         return SOC_E_PARAM;
   5590     case 4: /* CHIP */
   5591         break;
   5592     case 5: /* XPE */
   5593         if (si->xpe_ipipe_map[base_index] == 0) {
   5594             if (msg != NULL) {
   5595                 LOG_CLI((BSL_META_U(unit,
   5596                                     "%s: XPE%d is not in config\n"),
   5597                          msg, base_index));
   5598             }
   5599         } else if (sc < NUM_SLICE(unit)) { /* Unique access type */
   5600             if (sc == 0) { /* XPE 0 and 2 are in slice 0 */
   5601                 if (base_index == 0 || base_index == 2) {
   5602                     break;
   5603                 }
   5604             } else { /* XPE 1 and 3 are in slice 1 */
   5605                 if (base_index == 1 || base_index == 3) {
   5606                     break;
   5607                 }
   5608             }
   5609             if (msg != NULL) {
   5610                 LOG_CLI((BSL_META_U(unit,
   5611                                     "%s: XPE%d is not in SLICE%d\n"),
   5612                          msg, base_index, sc));
   5613             }
   5614         } else {
   5615             break;
   5616         }
   5617         return SOC_E_PARAM;
   5618     case 6: /* SLICE */
   5619     case 7: /* LAYER, not used */
   5620         break;
   5621     }
   5622 
   5623     return SOC_E_NONE;
   5624 }
   5625 
   5626 STATIC int
   5627 _soc_trident3_sc_reg_check(int unit, soc_reg_t reg, int sc, int base_index)
   5628 {
   5629     int acc_type, base_type;
   5630 
   5631     if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_SC)) {
   5632         LOG_CLI((BSL_META_U(unit,
   5633                             "%s is not SC register\n"), SOC_REG_NAME(unit, reg)));
   5634         return SOC_E_PARAM;
   5635     }
   5636 
   5637     if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */
   5638         if (sc == -1 || sc >= NUM_SLICE(unit)) {
   5639             LOG_CLI((BSL_META_U(unit,
   5640                                 "%s bad SC value %d\n"),
   5641                      SOC_REG_NAME(unit, reg), sc));
   5642             return SOC_E_PARAM;
   5643         }
   5644     } else {
   5645         acc_type = SOC_REG_ACC_TYPE(unit, reg);
   5646         if (acc_type < NUM_SLICE(unit)) { /* UNIQUE per SC register */
   5647             if (sc != acc_type) {
   5648                 LOG_CLI((BSL_META_U(unit,
   5649                                     "Ovveride SC value %d with ACC_TYPE of %s\n"),
   5650                          sc, SOC_REG_NAME(unit, reg)));
   5651             }
   5652             sc = acc_type;
   5653         } else { /* non-UNIQUE register */
   5654             return SOC_E_NONE;
   5655         }
   5656     }
   5657     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   5658 
   5659     return soc_trident3_sc_base_index_check(unit, base_type, sc, base_index,
   5660                                             SOC_REG_NAME(unit, reg));
   5661 }
   5662 
   5663 #if 0
   5664 STATIC int
   5665 _soc_trident3_sc_mem_check(int unit, soc_mem_t mem, int sc, int base_index)
   5666 {
   5667     int block_info_index, acc_type, base_type;
   5668 
   5669     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
   5670     if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_SC) {
   5671         LOG_CLI((BSL_META_U(unit,
   5672                             "%s is not SC register\n"), SOC_MEM_NAME(unit, mem)));
   5673         return SOC_E_PARAM;
   5674     }
   5675 
   5676     if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { /* UNIQUE base memory */
   5677         if (sc == -1 || sc >= NUM_SLICE(unit)) {
   5678             LOG_CLI((BSL_META_U(unit,
   5679                                 "%s bad SC value %d\n"),
   5680                      SOC_MEM_NAME(unit, mem), sc));
   5681             return SOC_E_PARAM;
   5682         }
   5683     } else {
   5684         acc_type = SOC_MEM_ACC_TYPE(unit, mem);
   5685         if (acc_type < NUM_SLICE(unit)) { /* UNIQUE per SC memory */
   5686             if (sc != acc_type) {
   5687                 LOG_CLI((BSL_META_U(unit,
   5688                                     "Ovveride SC value %d with ACC_TYPE of %s\n"),
   5689                          sc, SOC_MEM_NAME(unit, mem)));
   5690                 sc = acc_type;
   5691             }
   5692         } else { /* non-UNIQUE memory */
   5693             return SOC_E_NONE;
   5694         }
   5695     }
   5696     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   5697 
   5698     return soc_trident3_sc_base_index_check(unit, base_type, sc, base_index,
   5699                                             SOC_MEM_NAME(unit, mem));
   5700 }
   5701 #endif
   5702 
   5703 STATIC int
   5704 _soc_trident3_sc_reg_access(int unit, soc_reg_t reg, int sc, int base_index,
   5705                             int index, uint64 *data, int write)
   5706 {
   5707     soc_info_t *si;
   5708     int port;
   5709     int base_type;
   5710     uint32 base_index_map;
   5711     soc_pbmp_t base_index_pbmp;
   5712     uint32 inst;
   5713 
   5714     si = &SOC_INFO(unit);
   5715     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   5716 
   5717     if (sc >= 0 && base_index >= 0) {
   5718         SOC_IF_ERROR_RETURN
   5719             (_soc_trident3_sc_reg_check(unit, reg, sc, base_index));
   5720     }
   5721 
   5722     switch (base_type) {
   5723     case 0: /* IPORT */
   5724     case 1: /* EPORT */
   5725         /* No unique access type for such base_type */
   5726         if (base_index == -1) {
   5727             SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit));
   5728         } else {
   5729             /* This argument is logical port, same as soc_reg_get/set */
   5730             SOC_PBMP_PORT_SET(base_index_pbmp, base_index);
   5731         }
   5732 
   5733         SOC_PBMP_ITER(base_index_pbmp, port) {
   5734             if (write) {
   5735                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, index, *data));
   5736             } else {
   5737                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, index, data));
   5738             }
   5739         }
   5740         break;
   5741     case 2: /* IPIPE */
   5742     case 3: /* EPIPE */
   5743         /* No unique access type for such base_type */
   5744         soc_trident3_pipe_map_get(unit, &base_index_map);
   5745         if (base_index != -1) {
   5746             base_index_map &= 1 << base_index;
   5747             if (base_index_map == 0) {
   5748                 return SOC_E_PARAM;
   5749             }
   5750         }
   5751 
   5752         for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) {
   5753             if (!(base_index_map & (1 << base_index))) {
   5754                 continue;
   5755             }
   5756             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   5757             if (write) {
   5758                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   5759             } else {
   5760                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   5761             }
   5762         }
   5763         break;
   5764     case 4: /* CHIP */
   5765         if (write) {
   5766             SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data));
   5767         } else {
   5768             SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data));
   5769         }
   5770         break;
   5771     case 5: /* XPE */
   5772         /* No unique access type for such base_type */
   5773         if (base_index == -1) {
   5774             base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   5775         } else {
   5776             base_index_map = 1 << base_index;
   5777         }
   5778 
   5779         for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) {
   5780             if (!(base_index_map & (1 << base_index))) {
   5781                 continue;
   5782             }
   5783             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   5784             if (write) {
   5785                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   5786             } else {
   5787                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   5788             }
   5789         }
   5790         break;
   5791     case 6: /* SLICE */
   5792         if (sc >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
   5793             reg = SOC_REG_UNIQUE_ACC(unit, reg)[sc];
   5794         }
   5795         if (base_index == -1) {
   5796             base_index_map = si->ipipe_sc_map[0];;
   5797         } else {
   5798             base_index_map = 1 << base_index;
   5799         }
   5800         for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) {
   5801             if (!(base_index_map & (1 << base_index))) {
   5802                 continue;
   5803             }
   5804             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   5805             if (write) {
   5806                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   5807             } else {
   5808                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   5809             }
   5810         }
   5811         break;
   5812     case 7: /* LAYER */
   5813     default:
   5814         return SOC_E_INTERNAL;
   5815     }
   5816 
   5817     return SOC_E_NONE;
   5818 }
   5819 #if 0
   5820 STATIC int
   5821 _soc_trident3_sc_mem_access(int unit, soc_mem_t mem, int sc, int base_index,
   5822                             int copyno, int offset_in_section, void *entry_data,
   5823                             int write)
   5824 {
   5825     soc_info_t *si;
   5826     soc_mem_t orig_mem;
   5827     int index, section_size;
   5828     int base_type, break_after_first;
   5829     uint32 base_index_map, sc_map=0;
   5830 
   5831     si = &SOC_INFO(unit);
   5832     orig_mem = mem;
   5833     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   5834     section_size = SOC_MEM_INFO(unit, mem).section_size;
   5835     break_after_first = TRUE;
   5836 
   5837     if (sc >= 0 && base_index >= 0) {
   5838         SOC_IF_ERROR_RETURN
   5839             (_soc_trident3_sc_mem_check(unit, mem, sc, base_index));
   5840     }
   5841 
   5842     switch (base_type) {
   5843     case 2: /* IPIPE */
   5844     case 3: /* EPIPE */
   5845         if (sc >= 0 && SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) {
   5846             mem = SOC_MEM_UNIQUE_ACC(unit, mem)[sc];
   5847         }
   5848 
   5849         /* All tables with such base_type should have multiple sections */
   5850         soc_trident3_pipe_map_get(unit, &base_index_map);
   5851         if (base_index != -1) {
   5852             base_index_map &= 1 << base_index;
   5853             if (base_index_map == 0) {
   5854                 return SOC_E_PARAM;
   5855             }
   5856         }
   5857 
   5858         for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) {
   5859             if (!(base_index_map & (1 << base_index))) {
   5860                 continue;
   5861             }
   5862             /* Loop through SC(s) only on UNIQUE type base memory */
   5863             if (SOC_MEM_UNIQUE_ACC(unit, orig_mem) != NULL) {
   5864                 sc_map = base_type == 2 ?
   5865                     si->ipipe_sc_map[base_index] :
   5866                     si->epipe_sc_map[base_index];
   5867                 if (write) {
   5868                     break_after_first = FALSE;
   5869                 }
   5870             }
   5871             for (sc = 0; sc < NUM_SLICE(unit); sc++) {
   5872                 if (SOC_MEM_UNIQUE_ACC(unit, orig_mem) != NULL) {
   5873                     if (!(sc_map & (1 << sc))) {
   5874                         continue;
   5875                     }
   5876                     mem = SOC_MEM_UNIQUE_ACC(unit, orig_mem)[sc];
   5877                 }
   5878                 index = base_index * section_size + offset_in_section;
   5879                 if (write) {
   5880                     SOC_IF_ERROR_RETURN
   5881                         (soc_mem_write(unit, mem, copyno, index, entry_data));
   5882                 } else {
   5883                     SOC_IF_ERROR_RETURN
   5884                         (soc_mem_read(unit, mem, copyno, index, entry_data));
   5885                 }
   5886                 if (break_after_first) {
   5887                     break;
   5888                 }
   5889             }
   5890         }
   5891         break;
   5892     case 5: /* XPE */
   5893         /* No unique access type for such base_type */
   5894         if (base_index == -1) {
   5895             base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   5896         } else {
   5897             base_index_map = 1 << base_index;
   5898         }
   5899 
   5900         for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) {
   5901             if (!(base_index_map & (1 << base_index))) {
   5902                 continue;
   5903             }
   5904             index = base_index * section_size + offset_in_section;
   5905             if (write) {
   5906                 SOC_IF_ERROR_RETURN
   5907                     (soc_mem_write(unit, mem, copyno, index, entry_data));
   5908             } else {
   5909                 SOC_IF_ERROR_RETURN
   5910                     (soc_mem_read(unit, mem, copyno, index, entry_data));
   5911             }
   5912         }
   5913         break;
   5914     case 6: /* SLICE */
   5915         /* No unique access type for such base_type */
   5916         if (base_index == -1) {
   5917             base_index_map = si->ipipe_sc_map[0];
   5918         } else {
   5919             base_index_map = 1 << base_index;
   5920         }
   5921         for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) {
   5922             if (!(base_index_map & (1 << base_index))) {
   5923                 continue;
   5924             }
   5925             index = base_index * section_size + offset_in_section;
   5926             if (write) {
   5927                 SOC_IF_ERROR_RETURN
   5928                     (soc_mem_write(unit, mem, copyno, index, entry_data));
   5929             } else {
   5930                 SOC_IF_ERROR_RETURN
   5931                     (soc_mem_read(unit, mem, copyno, index, entry_data));
   5932             }
   5933         }
   5934         break;
   5935     case 0: /* IPORT */
   5936     case 1: /* EPORT */
   5937     case 4: /* CHIP */
   5938     case 7: /* LAYER */
   5939     default:
   5940         return SOC_E_INTERNAL;
   5941     }
   5942 
   5943     return SOC_E_NONE;
   5944 }
   5945 #endif
   5946 
   5947 int
   5948 soc_trident3_sed_base_index_check(int unit, int base_type, int sed,
   5949                                  int base_index, char *msg)
   5950 {
   5951     soc_info_t *si;
   5952     int pipe;
   5953     uint32 map;
   5954     char *base_name;
   5955 
   5956     si = &SOC_INFO(unit);
   5957 
   5958     if (sed == -1 || base_index == -1) {
   5959         return SOC_E_NONE;
   5960     }
   5961 
   5962     if (sed < NUM_SED(unit) && si->sed_ipipe_map[sed] == 0) {
   5963         if (msg) {
   5964             LOG_CLI((BSL_META_U(unit,
   5965                                 "%s: SED%d is not in config\n"),
   5966                      msg, sed));
   5967         }
   5968         return SOC_E_PARAM;
   5969     }
   5970 
   5971     switch (base_type) {
   5972     case 0: /* IPORT */
   5973     case 1: /* EPORT */
   5974         base_name = base_type == 0 ? "IPORT" : "EPORT";
   5975         pipe = si->port_pipe[base_index];
   5976         if (pipe == -1) {
   5977             if (msg) {
   5978                 LOG_CLI((BSL_META_U(unit,
   5979                                     "%s: %s%d is not in config\n"),
   5980                          msg, base_name, base_index));
   5981             }
   5982         } else if (sed < NUM_SED(unit)) { /* Unique access type */
   5983             map = base_type == 0 ?
   5984                 si->ipipe_sed_map[pipe] : si->epipe_sed_map[pipe];
   5985             if (map & (1 << sed)) {
   5986                 break;
   5987             }
   5988             if (msg != NULL) {
   5989                 LOG_CLI((BSL_META_U(unit,
   5990                                     "%s: %s%d is not in SED%d\n"),
   5991                          msg, base_name, base_index, sed));
   5992             }
   5993         } else {
   5994             break;
   5995         }
   5996         return SOC_E_PARAM;
   5997     case 2: /* IPIPE */
   5998     case 3: /* EPIPE */
   5999         if (base_type == 2) {
   6000             base_name = "IPIPE";
   6001             map = si->ipipe_sed_map[base_index];
   6002         } else {
   6003             base_name = "EPIPE";
   6004             map = si->epipe_sed_map[base_index];
   6005         }
   6006         if (map == 0) {
   6007             if (msg) {
   6008                 LOG_CLI((BSL_META_U(unit,
   6009                                     "%s: %s%d is not in config\n"),
   6010                          msg, base_name, base_index));
   6011             }
   6012         } else if (sed < NUM_SED(unit)) { /* Unique access type */
   6013             if (map & (1 << sed)) {
   6014                 break;
   6015             }
   6016             if (msg != NULL) {
   6017                 LOG_CLI((BSL_META_U(unit,
   6018                                     "%s: %s%d is not in SED%d\n"),
   6019                          msg, base_name, base_index, sed));
   6020             }
   6021         } else {
   6022             break;
   6023         }
   6024         return SOC_E_PARAM;
   6025     case 4: /* CHIP */
   6026         break;
   6027     case 5: /* XPE */
   6028         if (si->xpe_ipipe_map[base_index] == 0) {
   6029             if (msg != NULL) {
   6030                 LOG_CLI((BSL_META_U(unit,
   6031                                     "%s: XPE%d is not in config\n"),
   6032                          msg, base_index));
   6033             }
   6034         } else if (sed < NUM_SED(unit)) { /* Unique access type */
   6035             if (sed == 0) { /* XPE 0 and 2 are in slice 0 */
   6036                 if (base_index == 0 || base_index == 2) {
   6037                     break;
   6038                 }
   6039             } else { /* XPE 1 and 3 are in slice 1 */
   6040                 if (base_index == 1 || base_index == 3) {
   6041                     break;
   6042                 }
   6043             }
   6044             if (msg != NULL) {
   6045                 LOG_CLI((BSL_META_U(unit,
   6046                                     "%s: XPE%d is not in SLICE%d\n"),
   6047                          msg, base_index, sed));
   6048             }
   6049         } else {
   6050             break;
   6051         }
   6052         return SOC_E_PARAM;
   6053     case 6: /* SLICE */
   6054     case 7: /* LAYER, not used */
   6055         break;
   6056     }
   6057 
   6058     return SOC_E_NONE;
   6059 }
   6060 
   6061 STATIC int
   6062 _soc_trident3_sed_reg_check(int unit, soc_reg_t reg, int sed, int base_index)
   6063 {
   6064     int acc_type, base_type;
   6065 
   6066     if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_SED)) {
   6067         LOG_CLI((BSL_META_U(unit,
   6068                             "%s is not SED register\n"), SOC_REG_NAME(unit, reg)));
   6069         return SOC_E_PARAM;
   6070     }
   6071 
   6072     if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */
   6073         if (sed == -1 || sed >= NUM_SED(unit)) {
   6074             LOG_CLI((BSL_META_U(unit,
   6075                                 "%s bad SED value %d\n"),
   6076                      SOC_REG_NAME(unit, reg), sed));
   6077             return SOC_E_PARAM;
   6078         }
   6079     } else {
   6080         acc_type = SOC_REG_ACC_TYPE(unit, reg);
   6081         if (acc_type < NUM_SED(unit)) { /* UNIQUE per SED register */
   6082             if (sed != acc_type) {
   6083                 LOG_CLI((BSL_META_U(unit,
   6084                                     "Override SED value %d with ACC_TYPE of %s\n"),
   6085                          sed, SOC_REG_NAME(unit, reg)));
   6086             }
   6087             sed = acc_type;
   6088         } else { /* non-UNIQUE register */
   6089             return SOC_E_NONE;
   6090         }
   6091     }
   6092     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   6093 
   6094     return soc_trident3_sed_base_index_check(unit, base_type, sed, base_index,
   6095                                             SOC_REG_NAME(unit, reg));
   6096 }
   6097 STATIC int
   6098 _soc_trident3_sed_reg_access(int unit, soc_reg_t reg, int sed, int base_index,
   6099                              int index, uint64 *data, int write)
   6100 {
   6101     soc_info_t *si;
   6102     soc_reg_t orig_reg;
   6103     int port;
   6104     int base_type, break_after_first;
   6105     int base_index_count;
   6106     uint32 base_index_map;
   6107     soc_pbmp_t base_index_pbmp;
   6108     uint32 inst;
   6109 
   6110     si = &SOC_INFO(unit);
   6111     orig_reg = reg;
   6112     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   6113     break_after_first = TRUE;
   6114 
   6115     if (sed >= 0 && base_index >= 0) {
   6116         SOC_IF_ERROR_RETURN
   6117             (_soc_trident3_sed_reg_check(unit, reg, sed, base_index));
   6118     }
   6119 
   6120     switch (base_type) {
   6121     case 0: /* IPORT */
   6122     case 1: /* EPORT */
   6123         if (base_index == -1) {
   6124             SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit));
   6125         } else {
   6126             /* This argument is logical port, same as soc_reg_get/set */
   6127             SOC_PBMP_PORT_SET(base_index_pbmp, base_index);
   6128         }
   6129 
   6130         SOC_PBMP_ITER(base_index_pbmp, port) {
   6131             if (write) {
   6132                 SOC_IF_ERROR_RETURN
   6133                     (soc_reg_set(unit, reg, port, index, *data));
   6134             } else {
   6135                 SOC_IF_ERROR_RETURN
   6136                     (soc_reg_get(unit, reg, port, index, data));
   6137             }
   6138         }
   6139         break;
   6140     case 2: /* IPIPE */
   6141     case 3: /* EPIPE */
   6142         if (sed >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
   6143             reg = SOC_REG_UNIQUE_ACC(unit, reg)[sed];
   6144         }
   6145 
   6146         soc_trident3_pipe_map_get(unit, &base_index_map);
   6147         if (base_index != -1) {
   6148             base_index_map &= 1 << base_index;
   6149             if (base_index_map == 0) {
   6150                 return SOC_E_PARAM;
   6151             }
   6152         }
   6153 
   6154         for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) {
   6155             if (!(base_index_map & (1 << base_index))) {
   6156                 continue;
   6157             }
   6158             if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   6159                 reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[sed];
   6160             }
   6161             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   6162             if (write) {
   6163                 SOC_IF_ERROR_RETURN
   6164                     (soc_reg_set(unit, reg, inst, index, *data));
   6165             } else {
   6166                 SOC_IF_ERROR_RETURN
   6167                     (soc_reg_get(unit, reg, inst, index, data));
   6168             }
   6169             if (break_after_first) {
   6170                 break;
   6171             }
   6172         }
   6173         break;
   6174     case 4: /* CHIP */
   6175         if (write) {
   6176             SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data));
   6177         } else {
   6178             SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data));
   6179         }
   6180         break;
   6181     case 5: /* XPE */
   6182         if (base_index == -1) {
   6183             base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   6184         } else {
   6185             base_index_map = 1 << base_index;
   6186         }
   6187         for (base_index = 0; base_index < NUM_XPE(unit); base_index++) {
   6188             if (!(base_index_map & (1 << base_index))) {
   6189                 continue;
   6190             }
   6191             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   6192             if (write) {
   6193                 SOC_IF_ERROR_RETURN
   6194                     (soc_reg_set(unit, reg, inst, index, *data));
   6195             } else {
   6196                 SOC_IF_ERROR_RETURN
   6197                     (soc_reg_get(unit, reg, inst, index, data));
   6198             }
   6199         }
   6200         break;
   6201     case 6: /* SLICE */
   6202     case 7: /* LAYER */
   6203         /* No unique access type for such base_type */
   6204         if (base_index == -1) {
   6205             base_index_map = base_type == 6 ? si->ipipe_sc_map[0] : 0x3;
   6206         } else {
   6207             base_index_map = 1 << base_index;
   6208         }
   6209 
   6210         base_index_count = base_type == 6 ? NUM_SLICE(unit) : NUM_LAYER(unit);
   6211         for (base_index = 0; base_index < base_index_count; base_index++) {
   6212             if (!(base_index_map & (1 << base_index))) {
   6213                 continue;
   6214             }
   6215             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   6216             if (write) {
   6217                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   6218             } else {
   6219                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   6220             }
   6221         }
   6222         break;
   6223     /* No default case as base_type can have value only between 0-7 */
   6224     }
   6225 
   6226     return SOC_E_NONE;
   6227 }
   6228 
   6229 
   6230 int
   6231 soc_trident3_xpe_reg32_set(int unit, soc_reg_t reg, int xpe, int base_index,
   6232                            int index, uint32 data)
   6233 {
   6234     uint64 data64;
   6235 
   6236     COMPILER_64_SET(data64, 0, data);
   6237     SOC_IF_ERROR_RETURN(_soc_trident3_xpe_reg_access(unit, reg, xpe, base_index,
   6238                                                      index, &data64, TRUE));
   6239 
   6240     return SOC_E_NONE;
   6241 }
   6242 
   6243 int
   6244 soc_trident3_xpe_reg32_get(int unit, soc_reg_t reg, int xpe, int base_index,
   6245                            int index, uint32 *data)
   6246 {
   6247     uint64 data64;
   6248 
   6249     COMPILER_64_SET(data64, 0, *data);
   6250     SOC_IF_ERROR_RETURN(_soc_trident3_xpe_reg_access(unit, reg, xpe, base_index,
   6251                                                      index, &data64, FALSE));
   6252     *data = COMPILER_64_LO(data64);
   6253 
   6254     return SOC_E_NONE;
   6255 }
   6256 
   6257 int
   6258 soc_trident3_xpe_reg_set(int unit, soc_reg_t reg, int xpe, int base_index,
   6259                          int index, uint64 data)
   6260 {
   6261     return _soc_trident3_xpe_reg_access(unit, reg, xpe, base_index,
   6262                                         index, &data, TRUE);
   6263 }
   6264 
   6265 int
   6266 soc_trident3_xpe_reg_get(int unit, soc_reg_t reg, int xpe, int base_index,
   6267                          int index, uint64 *data)
   6268 {
   6269     return _soc_trident3_xpe_reg_access(unit, reg, xpe, base_index,
   6270                                         index, data, FALSE);
   6271 }
   6272 #if 0
   6273 int
   6274 soc_trident3_xpe_mem_write(int unit, soc_mem_t mem, int xpe, int base_index,
   6275                            int copyno, int offset_in_section, void *entry_data)
   6276 {
   6277     return _soc_trident3_xpe_mem_access(unit, mem, xpe, base_index, copyno,
   6278                                         offset_in_section, entry_data, TRUE);
   6279 }
   6280 
   6281 int
   6282 soc_trident3_xpe_mem_read(int unit, soc_mem_t mem, int xpe, int base_index,
   6283                           int copyno, int offset_in_section, void *entry_data)
   6284 {
   6285     return _soc_trident3_xpe_mem_access(unit, mem, xpe, base_index, copyno,
   6286                                         offset_in_section, entry_data, FALSE);
   6287 }
   6288 #endif
   6289 int
   6290 soc_trident3_sc_reg32_set(int unit, soc_reg_t reg, int sc, int base_index,
   6291                           int index, uint32 data)
   6292 {
   6293     uint64 data64;
   6294 
   6295     COMPILER_64_SET(data64, 0, data);
   6296     SOC_IF_ERROR_RETURN(_soc_trident3_sc_reg_access(unit, reg, sc, base_index,
   6297                                                     index, &data64, TRUE));
   6298 
   6299     return SOC_E_NONE;
   6300 }
   6301 
   6302 int
   6303 soc_trident3_sc_reg32_get(int unit, soc_reg_t reg, int sc, int base_index,
   6304                           int index, uint32 *data)
   6305 {
   6306     uint64 data64;
   6307 
   6308     COMPILER_64_SET(data64, 0, *data);
   6309     SOC_IF_ERROR_RETURN(_soc_trident3_sc_reg_access(unit, reg, sc, base_index,
   6310                                                     index, &data64, FALSE));
   6311     *data = COMPILER_64_LO(data64);
   6312 
   6313     return SOC_E_NONE;
   6314 }
   6315 
   6316 int
   6317 soc_trident3_sc_reg_set(int unit, soc_reg_t reg, int sc, int base_index,
   6318                         int index, uint64 data)
   6319 {
   6320     return _soc_trident3_sc_reg_access(unit, reg, sc, base_index,
   6321                                        index, &data, TRUE);
   6322 }
   6323 
   6324 int
   6325 soc_trident3_sc_reg_get(int unit, soc_reg_t reg, int sc, int base_index,
   6326                         int index, uint64 *data)
   6327 {
   6328     return _soc_trident3_sc_reg_access(unit, reg, sc, base_index,
   6329                                        index, data, FALSE);
   6330 }
   6331 #if 0
   6332 int
   6333 soc_trident3_sc_mem_write(int unit, soc_mem_t mem, int sc, int base_index,
   6334                           int copyno, int offset_in_section, void *entry_data)
   6335 {
   6336     return _soc_trident3_sc_mem_access(unit, mem, sc, base_index, copyno,
   6337                                        offset_in_section, entry_data, TRUE);
   6338 }
   6339 
   6340 int
   6341 soc_trident3_sc_mem_read(int unit, soc_mem_t mem, int sc, int base_index,
   6342                          int copyno, int offset_in_section, void *entry_data)
   6343 {
   6344     return _soc_trident3_sc_mem_access(unit, mem, sc, base_index, copyno,
   6345                                        offset_in_section, entry_data, FALSE);
   6346 }
   6347 #endif
   6348 
   6349 int
   6350 soc_trident3_sed_reg32_set(int unit, soc_reg_t reg, int sed, int base_index,
   6351                           int index, uint32 data)
   6352 {
   6353     uint64 data64;
   6354 
   6355     COMPILER_64_SET(data64, 0, data);
   6356     SOC_IF_ERROR_RETURN(_soc_trident3_sed_reg_access(unit, reg, sed, base_index,
   6357                                                     index, &data64, TRUE));
   6358 
   6359     return SOC_E_NONE;
   6360 }
   6361 
   6362 int
   6363 soc_trident3_sed_reg32_get(int unit, soc_reg_t reg, int sed, int base_index,
   6364                           int index, uint32 *data)
   6365 {
   6366     uint64 data64;
   6367 
   6368     COMPILER_64_SET(data64, 0, *data);
   6369     SOC_IF_ERROR_RETURN(_soc_trident3_sed_reg_access(unit, reg, sed, base_index,
   6370                                                     index, &data64, FALSE));
   6371     *data = COMPILER_64_LO(data64);
   6372 
   6373     return SOC_E_NONE;
   6374 }
   6375 
   6376 int
   6377 soc_trident3_sed_reg_set(int unit, soc_reg_t reg, int sed, int base_index,
   6378                         int index, uint64 data)
   6379 {
   6380     return _soc_trident3_sed_reg_access(unit, reg, sed, base_index,
   6381                                        index, &data, TRUE);
   6382 }
   6383 
   6384 int
   6385 soc_trident3_sed_reg_get(int unit, soc_reg_t reg, int sed, int base_index,
   6386                         int index, uint64 *data)
   6387 {
   6388     return _soc_trident3_sed_reg_access(unit, reg, sed, base_index,
   6389                                        index, data, FALSE);
   6390 }
   6391 
   6392 
   6393 #if defined(BCM_TD3_ASF_EXCLUDE)
   6394 int
   6395 soc_trident3_cut_through_update(int unit, soc_port_t port, int enable)
   6396 {
   6397     soc_info_t *si;
   6398     _soc_trident3_tdm_temp_t *tdm;
   6399     int pipe, class, index;
   6400     uint32 entry[SOC_MAX_MEM_WORDS];
   6401     int *start_count;
   6402     static int start_count_saf[13] =
   6403         { 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 };
   6404     static int start_count_linerate[13] =
   6405         { 18, 27, 27, 21, 21, 18, 18, 12, 12, 12, 12, 15, 15 };
   6406     static int start_count_oversub_2_1[13] =
   6407         { 18, 57, 57, 51, 51, 45, 45, 39, 39, 33, 33, 33, 33 };
   6408     static int start_count_oversub_3_2[13] =
   6409         { 18, 45, 45, 39, 39, 36, 36, 27, 27, 24, 24, 24, 24 };
   6410 
   6411     si = &SOC_INFO(unit);
   6412     tdm = SOC_CONTROL(unit)->tdm_info;
   6413 
   6414     if (enable) {
   6415         if (SOC_PBMP_MEMBER(si->oversub_pbm, port)) {
   6416             pipe = si->port_pipe[port];
   6417             if (tdm->ovs_ratio_x1000[pipe][0] + tdm->ovs_ratio_x1000[pipe][1] > 1500) {
   6418                 /* More than 3:2 oversubscription ratio */
   6419                 start_count = start_count_oversub_2_1;
   6420             } else {
   6421                 start_count = start_count_oversub_3_2;
   6422             }
   6423         } else {
   6424             start_count = start_count_linerate;
   6425         }
   6426     } else {
   6427         start_count = start_count_saf;
   6428     }
   6429 
   6430     sal_memset(entry, 0, sizeof(egr_xmit_start_count_entry_t));
   6431     for (class = 0; class < 13; class++) {
   6432         soc_mem_field32_set(unit, EGR_XMIT_START_COUNTm, entry, THRESHOLDf,
   6433                             start_count[class]);
   6434         index = (port % 66) * 16 + class;
   6435         SOC_IF_ERROR_RETURN
   6436             (WRITE_EGR_XMIT_START_COUNTm(unit, MEM_BLOCK_ALL, index, entry));
   6437     }
   6438 
   6439     return SOC_E_NONE;
   6440 }
   6441 #endif
   6442 
   6443 int
   6444 _soc_trident3_init_mmu_memory(int unit)
   6445 {
   6446     uint32 rval = 0;
   6447     int alloc_size;
   6448 
   6449     if (_fwd_ctrl_lock[unit] == NULL) {
   6450         _fwd_ctrl_lock[unit] = sal_mutex_create("_fwd_ctrl_lock");
   6451     }
   6452     if (_fwd_ctrl_lock[unit] == NULL) {
   6453         return SOC_E_MEMORY;
   6454     }
   6455 
   6456     if (_soc_td3_mmu_traffic_ctrl[unit] == NULL) {
   6457         alloc_size = sizeof(_soc_td3_mmu_traffic_ctrl_t);
   6458         _soc_td3_mmu_traffic_ctrl[unit] =
   6459             sal_alloc(alloc_size,"_soc_td3_mmu_traffic_ctrl");
   6460         if (_soc_td3_mmu_traffic_ctrl[unit] == NULL) {
   6461             return SOC_E_MEMORY;
   6462         }
   6463         sal_memset(_soc_td3_mmu_traffic_ctrl[unit], 0, alloc_size);
   6464     }
   6465 
   6466     /* Initialize MMU memory */
   6467     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, 0));
   6468     soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, PARITY_ENf, 1);
   6469     /* Need to assert PARITY_EN before setting INIT_MEM to start memory initialization */
   6470     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   6471     soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, INIT_MEMf, 1);
   6472     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   6473     soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, INIT_MEMf, 0);
   6474     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   6475     sal_usleep(20);
   6476     soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, PARITY_ENf, 0);
   6477     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   6478     return SOC_E_NONE;
   6479 }
   6480 
   6481 int
   6482 soc_trident3_clear_mmu_memory(int unit)
   6483 {
   6484 #define SOC_MMU_BASE_TYPE_IPORT 0
   6485 #define SOC_MMU_BASE_TYPE_EPORT 1
   6486 #define SOC_MMU_BASE_TYPE_IPIPE 2
   6487 #define SOC_MMU_BASE_TYPE_EPIPE 3
   6488 #define SOC_MMU_BASE_TYPE_CHIP 4
   6489 #define SOC_MMU_BASE_TYPE_XPE 5
   6490 #define SOC_MMU_BASE_TYPE_SC 6
   6491 #define SOC_MMU_BASE_TYPE_LAYER 7
   6492     int i, j, use_base_type_views, base_type, index, num_views;
   6493     uint32 entry[SOC_MAX_MEM_WORDS];
   6494     soc_mem_t mem;
   6495     static const struct {
   6496         soc_mem_t mem; /* base view */
   6497         int use_base_type_views; /* 1 means use xpe/sc/etc views */
   6498         int index; /* -1 means clear entire mem */
   6499     } mem_list[] = {
   6500         { MMU_CBPDATA0m, 1, 0 },
   6501         { MMU_CBPDATA32m, 1, 0 },
   6502         { MMU_CBPDATA64m, 1, 0 },
   6503         { MMU_CBPDATA96m, 1, 0 },
   6504         { MMU_CBPDATA128m, 1, 0 },
   6505         { MMU_CBPDATA160m, 1, 0 },
   6506         { MMU_CBPDATA192m, 1, 0 },
   6507         { MMU_CBPDATA224m, 1, 0 },
   6508         { MMU_CBPDATA256m, 1, 0 },
   6509         { MMU_CBPDATA288m, 1, 0 },
   6510         { INVALIDm, 0, -1 }
   6511     };
   6512     for (i = 0; mem_list[i].mem != INVALIDm; i++) {
   6513         mem = mem_list[i].mem;
   6514         if (!SOC_MEM_IS_VALID(unit, mem)) {
   6515             continue;
   6516         }
   6517 
   6518         index = mem_list[i].index;
   6519         use_base_type_views = mem_list[i].use_base_type_views;
   6520         if (use_base_type_views) {
   6521             base_type = soc_trident3_mem_basetype_get(unit, mem);
   6522             switch (base_type) {
   6523             case SOC_MMU_BASE_TYPE_XPE:
   6524                 num_views = NUM_XPE(unit);
   6525                 break;
   6526             case SOC_MMU_BASE_TYPE_SC:
   6527                 num_views = NUM_SLICE(unit);
   6528                 break;
   6529             case SOC_MMU_BASE_TYPE_LAYER:
   6530                 num_views = NUM_LAYER(unit);
   6531                 break;
   6532             case SOC_MMU_BASE_TYPE_IPIPE:
   6533             case SOC_MMU_BASE_TYPE_EPIPE:
   6534                 num_views = NUM_PIPE(unit);
   6535                 break;
   6536             default:
   6537                 num_views = -1; /* not supported */
   6538                 break;
   6539             }
   6540             if (num_views < 0) {
   6541                 LOG_ERROR(BSL_LS_SOC_COMMON,
   6542                           (BSL_META_U(unit,
   6543                                       "mmu_mem %s, base_type %d will not be"
   6544                                       "cleared \n"),
   6545                            SOC_MEM_NAME(unit,mem), base_type));
   6546                 continue;
   6547             }
   6548         } else {
   6549             num_views = 0; /* dont_care */
   6550         }
   6551 
   6552         sal_memset(entry, 0x0,
   6553                    soc_mem_entry_words(unit, mem) * sizeof(uint32));
   6554         if (use_base_type_views) {
   6555             for (j = 0; j < num_views; j++) {
   6556                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   6557                             (BSL_META_U(unit,
   6558                                         "mmu_mem %s, index %d will be "
   6559                                         "cleared \n"),
   6560                             SOC_MEM_NAME(unit, SOC_MEM_UNIQUE_ACC(unit, mem)[j]),
   6561                             index));
   6562                 if (index >= 0) {
   6563                     SOC_IF_ERROR_RETURN
   6564                         (soc_mem_write(unit,
   6565                                        SOC_MEM_UNIQUE_ACC(unit, mem)[j],
   6566                                        MEM_BLOCK_ALL, index, entry));
   6567                 } else {
   6568                     SOC_IF_ERROR_RETURN
   6569                         (soc_mem_clear(unit,
   6570                                        SOC_MEM_UNIQUE_ACC(unit, mem)[j],
   6571                                        COPYNO_ALL, TRUE));
   6572                 }
   6573             }
   6574         } else {
   6575             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   6576                         (BSL_META_U(unit,
   6577                                     "mmu_mem %s, index %d will be "
   6578                                     "cleared \n"),
   6579                         SOC_MEM_NAME(unit, mem), index));
   6580             if (index >= 0) {
   6581                 SOC_IF_ERROR_RETURN
   6582                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index,
   6583                                    entry));
   6584             } else {
   6585                 SOC_IF_ERROR_RETURN
   6586                     (soc_mem_clear(unit, mem, COPYNO_ALL, TRUE));
   6587             }
   6588         }
   6589     }
   6590     return SOC_E_NONE;
   6591 }
   6592 
   6593 STATIC int
   6594 _soc_trident3_port_mapping_init(int unit)
   6595 {
   6596     soc_info_t *si;
   6597     int port, phy_port, idb_port;
   6598     int num_port, num_phy_port;
   6599     soc_reg_t reg;
   6600     soc_mem_t mem;
   6601     uint32 rval;
   6602     uint32 entry[SOC_MAX_MEM_WORDS];
   6603     int pipe;
   6604 
   6605     /*
   6606      * 96 entries MMU_CHFC_SYSPORT_MAPPINGm.SYS_PORT
   6607      * 256 entries SYS_PORTMAPm.DEVICE_PORT_NUMBER
   6608      */
   6609 
   6610     si = &SOC_INFO(unit);
   6611 
   6612     num_port = soc_mem_index_count(unit, ING_DEVICE_PORTm) - 1;
   6613     num_phy_port = TD3_NUM_PHY_PORT;
   6614 
   6615     /* Ingress physical to device port mapping */
   6616     sal_memset(&entry, 0,
   6617                sizeof(ing_idb_to_device_port_number_mapping_table_entry_t));
   6618     for (phy_port = 0; phy_port < num_phy_port; phy_port++) {
   6619         port = si->port_p2l_mapping[phy_port];
   6620         if (port != -1) {
   6621             pipe = si->port_pipe[port];
   6622             idb_port = si->port_l2i_mapping[port];
   6623         } else if (phy_port >= 130) { /* loopback port (130 and 131 in TD3) */
   6624             pipe = phy_port - 130;
   6625             idb_port = 65;
   6626         } else if (phy_port == 129) { /* management port 0 (if not in use) */
   6627             pipe = 1;
   6628             idb_port = 64;
   6629         } else {
   6630             pipe = (phy_port - 1) / _TD3_PORTS_PER_PIPE;
   6631             idb_port = (phy_port -1 ) % _TD3_PORTS_PER_PIPE;
   6632         }
   6633         mem = SOC_MEM_UNIQUE_ACC
   6634             (unit, ING_IDB_TO_DEVICE_PORT_NUMBER_MAPPING_TABLEm)[pipe];
   6635         soc_mem_field32_set(unit, mem, &entry, DEVICE_PORT_NUMBERf,
   6636                             port == -1 ? 0xff : port);
   6637         SOC_IF_ERROR_RETURN
   6638             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, idb_port, &entry));
   6639     }
   6640 
   6641     /* Ingress GPP port to device port mapping */
   6642     mem = SYS_PORTMAPm;
   6643     sal_memset(&entry, 0, sizeof(sys_portmap_entry_t));
   6644     for (port = 0; port < num_port; port++) {
   6645         soc_mem_field32_set(unit, mem, &entry, DEVICE_PORT_NUMBERf, port);
   6646         SOC_IF_ERROR_RETURN
   6647             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, port, &entry));
   6648     }
   6649 
   6650     /* Ingress device port to GPP port mapping
   6651      * PORT_TAB.SRC_SYS_PORT_ID is programmed in the general port config
   6652      * init routine _bcm_fb_port_cfg_init()
   6653      */
   6654 
   6655     /* Egress device port to physical port mapping */
   6656     rval = 0;
   6657     reg = EGR_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGr;
   6658     PBMP_ALL_ITER(unit, port) {
   6659         soc_reg_field_set(unit, reg, &rval, PHYSICAL_PORT_NUMBERf,
   6660                           si->port_l2p_mapping[port]);
   6661         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   6662     }
   6663 
   6664     /* MMU port to physical port mapping */
   6665     rval = 0;
   6666     reg = MMU_PORT_TO_PHY_PORT_MAPPINGr;
   6667     PBMP_ALL_ITER(unit, port) {
   6668         soc_reg_field_set(unit, reg, &rval, PHY_PORTf,
   6669                           si->port_l2p_mapping[port]);
   6670         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   6671     }
   6672 
   6673     /* MMU port to system port mapping */
   6674     rval = 0;
   6675     reg = MMU_PORT_TO_SYSTEM_PORT_MAPPINGr;
   6676     PBMP_ALL_ITER(unit, port) {
   6677         soc_reg_field_set(unit, reg, &rval, SYSTEM_PORTf, port);
   6678         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   6679     }
   6680 
   6681     return SOC_E_NONE;
   6682 }
   6683 
   6684 /*
   6685  * Function:
   6686  *      soc_trident3_latency_config
   6687  * Purpose:
   6688  *      Configure latency in SLOT_PIPELINE_CONFIG register
   6689  * Parameters:
   6690  *      unit (IN)    - switch unit
   6691  * Returns:
   6692  *      SOC_E_*
   6693  */
   6694 
   6695 int
   6696 soc_trident3_latency_config(int unit)
   6697 {
   6698     soc_reg_t reg;
   6699     uint32 rval;
   6700     uint32 latency, pipe_latency_full = 467;
   6701     int frequency, dpp_clk_ratio_x10;
   6702     soc_info_t *si = &SOC_INFO(unit);
   6703 
   6704     frequency = soc_property_get(unit, spn_CORE_CLOCK_FREQUENCY, si->frequency);
   6705     dpp_clk_ratio_x10 = (frequency > CCLK_FREQ_1012MHZ)? 15:10;
   6706 
   6707     reg = SLOT_PIPELINE_CONFIGr;
   6708     rval = 0;
   6709     latency = (pipe_latency_full * dpp_clk_ratio_x10 / 10) - 6 + 5;
   6710     if ((dpp_clk_ratio_x10 == 15) && (pipe_latency_full % 2)) {
   6711         /*
   6712          * COVERITY
   6713          * pipe_latency_full is subject to change. This checker will not be True.
   6714          * It is kept intentionally as a defensive check for future development.
   6715          */
   6716         /* coverity[dead_error_line] */
   6717         latency += 1;   /* To round up. */
   6718     }
   6719     soc_reg_field_set(unit, reg, &rval, LATENCYf, latency);
   6720     soc_reg_field_set(unit, reg, &rval, WR_ENf, 1);
   6721     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   6722 
   6723     return SOC_E_NONE;
   6724 }
   6725 
   6726 
   6727 
   6728 #if 0
   6729 STATIC int
   6730 _soc_trident3_tdm_idb_oversub_group_set(int unit)
   6731 {
   6732     soc_info_t *si;
   6733     _soc_tomahawk_tdm_t *tdm;
   6734     uint32 pipe_map;
   6735     int block_info_idx;
   6736     soc_reg_t reg;
   6737     int pipe, clport, group, lane, slot, id, mode, ovs_class;
   6738     int port, phy_port, phy_port_base, idb_port;
   6739     int speed_max;
   6740     uint32 rval;
   6741     static const soc_reg_t grp_tbl_regs[] = {
   6742         IS_OVR_SUB_GRP0_TBLr, IS_OVR_SUB_GRP1_TBLr,
   6743         IS_OVR_SUB_GRP2_TBLr, IS_OVR_SUB_GRP3_TBLr,
   6744         IS_OVR_SUB_GRP4_TBLr, IS_OVR_SUB_GRP5_TBLr
   6745     };
   6746     static const soc_reg_t pblk_calendar_regs[] ={
   6747         IS_PBLK0_CALENDARr, IS_PBLK1_CALENDARr,
   6748         IS_PBLK2_CALENDARr, IS_PBLK3_CALENDARr,
   6749         IS_PBLK4_CALENDARr, IS_PBLK5_CALENDARr,
   6750         IS_PBLK6_CALENDARr, IS_PBLK7_CALENDARr
   6751     };
   6752     static int pblk_slots[SOC_TD3_PORT_RATIO_COUNT][7] = {
   6753         { 0, -1,  0,  0, -1,  0, -1 }, /* SOC_TD3_PORT_RATIO_SINGLE */
   6754         { 0, -1,  2,  0, -1,  2, -1 }, /* SOC_TD3_PORT_RATIO_DUAL_1_1 */
   6755         { 0,  0,  2,  0,  0,  2, -1 }, /* SOC_TD3_PORT_RATIO_DUAL_2_1 */
   6756         { 0,  2,  2,  0,  2,  2, -1 }, /* SOC_TD3_PORT_RATIO_DUAL_1_2 */
   6757         { 0, -1,  2,  0, -1,  3, -1 }, /* SOC_TD3_PORT_RATIO_TRI_023_2_1_1 */
   6758         { 0,  0,  2,  0,  0,  3, -1 }, /* SOC_TD3_PORT_RATIO_TRI_023_4_1_1 */
   6759         { 0, -1,  2,  1, -1,  2, -1 }, /* SOC_TD3_PORT_RATIO_TRI_012_1_1_2 */
   6760         { 0,  2,  2,  1,  2,  2, -1 }, /* SOC_TD3_PORT_RATIO_TRI_012_1_1_4 */
   6761         { 0, -1,  2,  1, -1,  3, -1 }  /* SOC_TD3_PORT_RATIO_QUAD */
   6762     };
   6763 
   6764     si = &SOC_INFO(unit);
   6765     tdm = SOC_CONTROL(unit)->tdm_info;
   6766 
   6767     soc_trident3_pipe_map_get(unit, &pipe_map);
   6768 
   6769     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   6770         if (!(pipe_map & (1 << pipe))) {
   6771             continue;
   6772         }
   6773 
   6774         for (group = 0; group < _OVS_GROUP_COUNT; group++) {
   6775             reg = SOC_REG_UNIQUE_ACC(unit, grp_tbl_regs[group])[pipe];
   6776             rval = 0;
   6777             for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
   6778                 phy_port = tdm->idb_ovs_tdm[pipe][group][slot];
   6779                 if (phy_port >= _SOC_TH_TDM_NUM_EXT_PORTS) {
   6780                     idb_port = 0x3f;
   6781                     id = -1;
   6782                 } else {
   6783                     port = si->port_p2l_mapping[phy_port];
   6784                     idb_port = si->port_l2i_mapping[port];
   6785                     id = si->port_serdes[port];
   6786                 }
   6787                 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id & 0x7);
   6788                 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port);
   6789                 SOC_IF_ERROR_RETURN
   6790                     (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
   6791             }
   6792         }
   6793     }
   6794 
   6795     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   6796         if (!(pipe_map & (1 << pipe))) {
   6797             continue;
   6798         }
   6799 
   6800         reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe];
   6801         for (group = 0; group < _OVS_GROUP_COUNT; group++) {
   6802             phy_port = tdm->idb_ovs_tdm[pipe][group][0];
   6803             if (phy_port >= _SOC_TH_TDM_NUM_EXT_PORTS) {
   6804                 continue;
   6805             }
   6806             port = si->port_p2l_mapping[phy_port];
   6807             speed_max = 25000 * si->port_num_lanes[port];
   6808             if (speed_max > si->port_speed_max[port]) {
   6809                 speed_max = si->port_speed_max[port];
   6810             }
   6811             _soc_trident3_speed_to_ovs_class_mapping(unit, speed_max,
   6812                                                      &ovs_class);
   6813             rval = 0;
   6814             soc_reg_field_set(unit, reg, &rval, SAME_SPACINGf, 4);
   6815             soc_reg_field_set(unit, reg, &rval, SPEEDf, ovs_class);
   6816             SOC_IF_ERROR_RETURN
   6817                 (soc_reg32_set(unit, reg, REG_PORT_ANY, group, rval));
   6818         }
   6819     }
   6820 
   6821     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   6822         port = SOC_BLOCK_PORT(unit, block_info_idx);
   6823         phy_port_base = PORT_BLOCK_BASE_PORT(port);
   6824         pipe = si->port_pipe[port];
   6825         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   6826 
   6827         mode = tdm->port_ratio[clport];
   6828         reg = SOC_REG_UNIQUE_ACC(unit, pblk_calendar_regs[clport & 0x7])[pipe];
   6829         rval = 0;
   6830         soc_reg_field_set(unit, reg, &rval, VALIDf, 1);
   6831         soc_reg_field_set(unit, reg, &rval, SPACINGf, 4);
   6832         for (slot = 0; slot < 7; slot++) {
   6833             lane = pblk_slots[mode][slot];
   6834             if (lane == -1) {
   6835                 SOC_IF_ERROR_RETURN
   6836                     (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, 0));
   6837                 continue;
   6838             }
   6839             port = si->port_p2l_mapping[phy_port_base + lane];
   6840             idb_port = si->port_l2i_mapping[port];
   6841             soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port);
   6842             SOC_IF_ERROR_RETURN
   6843                 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
   6844         }
   6845     }
   6846 
   6847     return SOC_E_NONE;
   6848 }
   6849 
   6850 STATIC int
   6851 _soc_trident3_tdm_idb_opportunistic_set(int unit, int enable)
   6852 {
   6853     soc_reg_t reg;
   6854     uint32 pipe_map;
   6855     int pipe;
   6856     uint32 rval;
   6857 
   6858     soc_trident3_pipe_map_get(unit, &pipe_map);
   6859 
   6860     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   6861         if (!(pipe_map & (1 << pipe))) {
   6862             continue;
   6863         }
   6864 
   6865         reg = SOC_REG_UNIQUE_ACC(unit, IS_CPU_LB_OPP_CFGr)[pipe];
   6866         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   6867         soc_reg_field_set(unit, reg, &rval, CPU_OPP_ENf, enable ? 1 : 0);
   6868         soc_reg_field_set(unit, reg, &rval, LB_OPP_ENf, enable ? 1 : 0);
   6869         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   6870 
   6871         reg = SOC_REG_UNIQUE_ACC(unit, IS_OPP_SCHED_CFGr)[pipe];
   6872         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   6873         soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, enable ? 1 : 0);
   6874         soc_reg_field_set(unit, reg, &rval, OPP2_PORT_ENf, enable ? 1 : 0);
   6875         soc_reg_field_set(unit, reg, &rval, OPP_OVR_SUB_ENf, enable ? 1 : 0);
   6876         soc_reg_field_set(unit, reg, &rval, DISABLE_PORT_NUMf, 0);
   6877         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   6878     }
   6879 
   6880     return SOC_E_NONE;
   6881 }
   6882 
   6883 STATIC int
   6884 _soc_trident3_tdm_idb_hsp_set(int unit)
   6885 {
   6886     soc_info_t *si;
   6887     soc_reg_t reg;
   6888     uint32 pipe_map;
   6889     int pipe;
   6890     int port, idb_port;
   6891     uint32 port_map[NUM_PIPE(unit)];
   6892     uint32 rval;
   6893 
   6894     si = &SOC_INFO(unit);
   6895 
   6896     soc_trident3_pipe_map_get(unit, &pipe_map);
   6897 
   6898     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   6899         port_map[pipe] = 0;
   6900     }
   6901     SOC_PBMP_ITER(si->eq_pbm, port) {
   6902         pipe = si->port_pipe[port];
   6903         idb_port = si->port_l2i_mapping[port];
   6904         port_map[pipe] |= 1 << idb_port;
   6905     }
   6906 
   6907     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   6908         if (!(pipe_map & (1 << pipe))) {
   6909             continue;
   6910         }
   6911 
   6912         reg = SOC_REG_UNIQUE_ACC(unit, IS_TDM_HSPr)[pipe];
   6913         soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[pipe]);
   6914         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   6915     }
   6916 
   6917     return SOC_E_NONE;
   6918 }
   6919 #endif
   6920 
   6921 
   6922 
   6923 #if 0
   6924 STATIC int
   6925 _soc_trident3_tdm_mmu_oversub_group_set(int unit)
   6926 {
   6927     soc_info_t *si;
   6928     _soc_tomahawk_tdm_t *tdm;
   6929     uint32 pipe_map;
   6930     int block_info_idx;
   6931     soc_reg_t reg;
   6932     int pipe, clport, group, lane, slot, id, mode, ovs_class;
   6933     int port, phy_port, phy_port_base, mmu_port, inst;
   6934     int speed_max;
   6935     uint32 rval;
   6936     static const soc_reg_t grp_tbl_regs[] = {
   6937         OVR_SUB_GRP0_TBLr, OVR_SUB_GRP1_TBLr,
   6938         OVR_SUB_GRP2_TBLr, OVR_SUB_GRP3_TBLr,
   6939         OVR_SUB_GRP4_TBLr, OVR_SUB_GRP5_TBLr
   6940     };
   6941     static const soc_reg_t pblk_calendar_regs[] = {
   6942         PBLK0_CALENDARr, PBLK1_CALENDARr, PBLK2_CALENDARr, PBLK3_CALENDARr,
   6943         PBLK4_CALENDARr, PBLK5_CALENDARr, PBLK6_CALENDARr, PBLK7_CALENDARr
   6944     };
   6945     static const int pblk_slots[SOC_TD3_PORT_RATIO_COUNT][7] = {
   6946         { 0, -1,  0,  0, -1,  0, -1 }, /* SOC_TD3_PORT_RATIO_SINGLE */
   6947         { 0, -1,  2,  0, -1,  2, -1 }, /* SOC_TD3_PORT_RATIO_DUAL_1_1 */
   6948         { 0,  0,  2,  0,  0,  2, -1 }, /* SOC_TD3_PORT_RATIO_DUAL_2_1 */
   6949         { 0,  2,  2,  0,  2,  2, -1 }, /* SOC_TD3_PORT_RATIO_DUAL_1_2 */
   6950         { 0, -1,  2,  0, -1,  3, -1 }, /* SOC_TD3_PORT_RATIO_TRI_023_2_1_1 */
   6951         { 0,  0,  2,  0,  0,  3, -1 }, /* SOC_TD3_PORT_RATIO_TRI_023_4_1_1 */
   6952         { 0, -1,  2,  1, -1,  2, -1 }, /* SOC_TD3_PORT_RATIO_TRI_012_1_1_2 */
   6953         { 0,  2,  2,  1,  2,  2, -1 }, /* SOC_TD3_PORT_RATIO_TRI_012_1_1_4 */
   6954         { 0, -1,  2,  1, -1,  3, -1 }  /* SOC_TD3_PORT_RATIO_QUAD */
   6955     };
   6956 
   6957     si = &SOC_INFO(unit);
   6958     tdm = SOC_CONTROL(unit)->tdm_info;
   6959 
   6960     soc_trident3_pipe_map_get(unit, &pipe_map);
   6961 
   6962     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   6963         if (!(pipe_map & (1 << pipe))) {
   6964             continue;
   6965         }
   6966 
   6967         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   6968         for (group = 0; group < _OVS_GROUP_COUNT; group++) {
   6969             reg = grp_tbl_regs[group];
   6970             rval = 0;
   6971             for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
   6972                 phy_port = tdm->mmu_ovs_tdm[pipe][group][slot];
   6973                 if (phy_port >= _SOC_TH_TDM_NUM_EXT_PORTS) {
   6974                     mmu_port = 0x3f;
   6975                     id = -1;
   6976                 } else {
   6977                     mmu_port = si->port_p2m_mapping[phy_port];
   6978                     port = si->port_p2l_mapping[phy_port];
   6979                     id = si->port_serdes[port];
   6980                 }
   6981                 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id & 0x7);
   6982                 soc_reg_field_set(unit, reg, &rval, PORT_NUMf,
   6983                                   mmu_port & 0x3f);
   6984                 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
   6985             }
   6986         }
   6987     }
   6988 
   6989     reg = OVR_SUB_GRP_CFGr;
   6990     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   6991         if (!(pipe_map & (1 << pipe))) {
   6992             continue;
   6993         }
   6994 
   6995         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   6996         for (group = 0; group < _OVS_GROUP_COUNT; group++) {
   6997             phy_port = tdm->mmu_ovs_tdm[pipe][group][0];
   6998             if (phy_port >= _SOC_TH_TDM_NUM_EXT_PORTS) {
   6999                 continue;
   7000             }
   7001             port = si->port_p2l_mapping[phy_port];
   7002             speed_max = 25000 * si->port_num_lanes[port];
   7003             if (speed_max > si->port_speed_max[port]) {
   7004                 speed_max = si->port_speed_max[port];
   7005             }
   7006             _soc_trident3_speed_to_ovs_class_mapping(unit, speed_max,
   7007                                                      &ovs_class);
   7008             rval = 0;
   7009             soc_reg_field_set(unit, reg, &rval, SAME_SPACINGf,
   7010                               speed_max >= 40000 ? 4 : 8);
   7011             soc_reg_field_set(unit, reg, &rval, SPEEDf, ovs_class);
   7012             SOC_IF_ERROR_RETURN
   7013                 (soc_reg32_set(unit, reg, inst, group, rval));
   7014         }
   7015     }
   7016 
   7017     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   7018         port = SOC_BLOCK_PORT(unit, block_info_idx);
   7019         phy_port_base = PORT_BLOCK_BASE_PORT(port);
   7020         speed_max = 25000 * si->port_num_lanes[port];
   7021         if (speed_max > si->port_speed_max[port]) {
   7022             speed_max = si->port_speed_max[port];
   7023         }
   7024         pipe = si->port_pipe[port];
   7025         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   7026         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   7027 
   7028         mode = tdm->port_ratio[clport];
   7029         reg = pblk_calendar_regs[clport & 0x7];
   7030         rval = 0;
   7031         soc_reg_field_set(unit, reg, &rval, VALIDf, 1);
   7032         soc_reg_field_set(unit, reg, &rval, SPACINGf,
   7033                           speed_max >= 40000 ? 4 : 8);
   7034         for (slot = 0; slot < 7; slot++) {
   7035             lane = pblk_slots[mode][slot];
   7036             if (lane == -1) {
   7037                 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, 0));
   7038                 continue;
   7039             }
   7040             mmu_port = si->port_p2m_mapping[phy_port_base + lane];
   7041             soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f);
   7042             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
   7043         }
   7044     }
   7045 
   7046     return SOC_E_NONE;
   7047 }
   7048 
   7049 STATIC int
   7050 _soc_trident3_tdm_mmu_opportunistic_set(int unit, int enable)
   7051 {
   7052     uint32 pipe_map;
   7053     soc_reg_t reg;
   7054     int pipe;
   7055     int inst;
   7056     uint32 rval;
   7057 
   7058     soc_trident3_pipe_map_get(unit, &pipe_map);
   7059 
   7060     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   7061         if (!(pipe_map & (1 << pipe))) {
   7062             continue;
   7063         }
   7064 
   7065         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   7066 
   7067         reg = CPU_LB_OPP_CFGr;
   7068         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval));
   7069         soc_reg_field_set(unit, reg, &rval, CPU_OPP_ENf, enable ? 1 : 0);
   7070         soc_reg_field_set(unit, reg, &rval, LB_OPP_ENf, enable ? 1 : 0);
   7071         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   7072 
   7073         reg = OPP_SCHED_CFGr;
   7074         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval));
   7075         soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, enable ? 1 : 0);
   7076         soc_reg_field_set(unit, reg, &rval, OPP2_PORT_ENf, enable ? 1 : 0);
   7077         soc_reg_field_set(unit, reg, &rval, OPP_OVR_SUB_ENf, enable ? 1 : 0);
   7078         soc_reg_field_set(unit, reg, &rval, DISABLE_PORT_NUMf, 0);
   7079         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   7080     }
   7081 
   7082     return SOC_E_NONE;
   7083 }
   7084 
   7085 STATIC int
   7086 _soc_trident3_tdm_mmu_hsp_set(int unit)
   7087 {
   7088     soc_info_t *si;
   7089     uint32 pipe_map;
   7090     soc_reg_t reg;
   7091     int pipe;
   7092     int port, phy_port, mmu_port, inst;
   7093     uint32 port_map[NUM_PIPE(unit)];
   7094     uint32 rval;
   7095 
   7096     si = &SOC_INFO(unit);
   7097 
   7098     soc_trident3_pipe_map_get(unit, &pipe_map);
   7099 
   7100     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   7101         port_map[pipe] = 0;
   7102     }
   7103     SOC_PBMP_ITER(si->eq_pbm, port) {
   7104         pipe = si->port_pipe[port];
   7105         phy_port = si->port_l2p_mapping[port];
   7106         mmu_port = si->port_p2m_mapping[phy_port];
   7107         port_map[pipe] |= 1 << (mmu_port & 0x1f);
   7108     }
   7109 
   7110     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   7111         if (!(pipe_map & (1 << pipe))) {
   7112             continue;
   7113         }
   7114 
   7115         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   7116 
   7117         reg = TDM_HSPr;
   7118         soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[pipe]);
   7119         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   7120     }
   7121 
   7122     return SOC_E_NONE;
   7123 }
   7124 #endif
   7125 
   7126 int
   7127 soc_trident3_hash_init(int unit)
   7128 {
   7129 /* Robust Hash initialization */
   7130 #ifdef SOC_ROBUST_HASH
   7131 subport_id_to_sgpp_map_key_attributes_entry_t sgpp_map_attr;
   7132 
   7133     /* Initialize Robust Hash Global Datastructure */
   7134     if (soc_feature(unit, soc_feature_robust_hash)) {
   7135         uint32 seed = 0;
   7136         uint32 hash_control_entry[4];
   7137 
   7138         if (NULL == ROBUSTHASH(unit)) {
   7139             ROBUSTHASH(unit) = sal_alloc(sizeof(soc_robust_hash_db_t),
   7140                                          "soc_robust_hash");
   7141             if (ROBUSTHASH(unit) == NULL) {
   7142                 return SOC_E_MEMORY;
   7143             }
   7144             sal_memset(ROBUSTHASH(unit), 0, sizeof(soc_robust_hash_db_t));
   7145         }
   7146 
   7147         /* L2 Robust Hash Init */
   7148 
   7149         sal_memset(hash_control_entry, 0, sizeof(hash_control_entry));
   7150 
   7151         /* Disable robust hash for L2 - this config variable is used only
   7152          * for debug purposes*/
   7153         if ((soc_property_get(unit, "robust_hash_disable_l2", 0)) == 1) {
   7154             SOC_IF_ERROR_RETURN
   7155                 (READ_L2_ENTRY_HASH_CONTROLm
   7156                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7157                 soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm ,
   7158                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7159             SOC_IF_ERROR_RETURN
   7160                 (WRITE_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7161                                                 hash_control_entry));
   7162             ROBUSTHASH(unit)->l2.enable = 0;
   7163         } else {
   7164             /* Enable robust hashing */
   7165             SOC_IF_ERROR_RETURN
   7166                 (READ_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7167                                              hash_control_entry));
   7168             soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm,
   7169                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7170             SOC_IF_ERROR_RETURN
   7171                 (WRITE_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7172                                                 hash_control_entry));
   7173             ROBUSTHASH(unit)->l2.enable = 1;
   7174 
   7175             /* Configure remap and action tables for L2 table */
   7176             ROBUSTHASH(unit)->l2.remap_tab[0] = L2_ENTRY_REMAP_TABLE_Am;
   7177             ROBUSTHASH(unit)->l2.remap_tab[1] = L2_ENTRY_REMAP_TABLE_Bm;
   7178             ROBUSTHASH(unit)->l2.action_tab[0] = L2_ENTRY_ACTION_TABLE_Am;
   7179             ROBUSTHASH(unit)->l2.action_tab[1] = L2_ENTRY_ACTION_TABLE_Bm;
   7180 
   7181             /* Initialize seed for robust hash */
   7182             seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_L2, 16777213);
   7183 
   7184             SOC_IF_ERROR_RETURN
   7185                 (soc_robust_hash_table_set(unit,
   7186                                            &(ROBUSTHASH(unit)->l2),
   7187                                            seed));
   7188         }
   7189 
   7190         /* L3 Robust Hash Init */
   7191 
   7192         sal_memset(hash_control_entry, 0, sizeof(hash_control_entry));
   7193 
   7194         /* Disable robust hash for L3 - this config variable is used only
   7195          * for debug purposes*/
   7196         if ((soc_property_get(unit, "robust_hash_disable_l3", 0)) == 1) {
   7197             SOC_IF_ERROR_RETURN
   7198                 (READ_L3_ENTRY_HASH_CONTROLm
   7199                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7200                 soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm ,
   7201                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7202             SOC_IF_ERROR_RETURN
   7203                 (WRITE_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7204                                                 hash_control_entry));
   7205             ROBUSTHASH(unit)->l3.enable = 0;
   7206         } else {
   7207             /* Enable robust hashing */
   7208             SOC_IF_ERROR_RETURN
   7209                 (READ_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7210                                              hash_control_entry));
   7211             soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm,
   7212                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7213             SOC_IF_ERROR_RETURN
   7214                 (WRITE_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7215                                                 hash_control_entry));
   7216             ROBUSTHASH(unit)->l3.enable = 1;
   7217 
   7218             /* Configure remap and action tables for L3 table */
   7219             ROBUSTHASH(unit)->l3.remap_tab[0] = L3_ENTRY_REMAP_TABLE_Am;
   7220             ROBUSTHASH(unit)->l3.remap_tab[1] = L3_ENTRY_REMAP_TABLE_Bm;
   7221             ROBUSTHASH(unit)->l3.action_tab[0] = L3_ENTRY_ACTION_TABLE_Am;
   7222             ROBUSTHASH(unit)->l3.action_tab[1] = L3_ENTRY_ACTION_TABLE_Bm;
   7223 
   7224             /* Initialize seed for robust hash */
   7225             seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_L3, 16777213);
   7226 
   7227             SOC_IF_ERROR_RETURN
   7228                 (soc_robust_hash_table_set(unit,
   7229                                            &(ROBUSTHASH(unit)->l3),
   7230                                            seed));
   7231         }
   7232 
   7233         /* Exact Match Robust Hash Init */
   7234 
   7235         sal_memset
   7236             (hash_control_entry, 0, sizeof(hash_control_entry));
   7237 
   7238         /* Disable robust hash for EM - this config variable is used only
   7239          * for debug purposes*/
   7240         if ((soc_property_get
   7241                 (unit, "robust_hash_disable_exact_match", 0)) == 1) {
   7242             SOC_IF_ERROR_RETURN
   7243                 (READ_EXACT_MATCH_HASH_CONTROLm
   7244                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7245                 soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm ,
   7246                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7247             SOC_IF_ERROR_RETURN
   7248                 (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7249                                                 hash_control_entry));
   7250             ROBUSTHASH(unit)->exact_match.enable = 0;
   7251         } else {
   7252             /* Enable robust hashing */
   7253             SOC_IF_ERROR_RETURN
   7254                 (READ_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7255                                                 hash_control_entry));
   7256             soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm,
   7257                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7258             SOC_IF_ERROR_RETURN
   7259                 (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7260                                                  hash_control_entry));
   7261             ROBUSTHASH(unit)->exact_match.enable = 1;
   7262 
   7263             /* Configure remap and action tables for EM table */
   7264             ROBUSTHASH(unit)->exact_match.remap_tab[0] = EXACT_MATCH_REMAP_TABLE_Am;
   7265             ROBUSTHASH(unit)->exact_match.remap_tab[1] = EXACT_MATCH_REMAP_TABLE_Bm;
   7266             ROBUSTHASH(unit)->exact_match.action_tab[0] = EXACT_MATCH_ACTION_TABLE_Am;
   7267             ROBUSTHASH(unit)->exact_match.action_tab[1] = EXACT_MATCH_ACTION_TABLE_Bm;
   7268 
   7269             /* Initialize seed for robust hash */
   7270             seed = soc_property_get
   7271                     (unit, spn_ROBUST_HASH_SEED_EXACT_MATCH, 16777213);
   7272 
   7273             SOC_IF_ERROR_RETURN
   7274                 (soc_robust_hash_table_set(unit,
   7275                                            &(ROBUSTHASH(unit)->exact_match),
   7276                                            seed));
   7277         }
   7278 
   7279         /* Vlan Xlate 1 Robust Hash Init */
   7280 
   7281         sal_memset
   7282             (hash_control_entry, 0, sizeof(hash_control_entry));
   7283 
   7284         /* Disable robust hash for Vlan Xlate 1 - this config variable is used
   7285          * only for debug purposes*/
   7286         if ((soc_property_get
   7287                 (unit, "robust_hash_disable_vlan1", 0)) == 1) {
   7288             SOC_IF_ERROR_RETURN
   7289                 (READ_VLAN_XLATE_1_HASH_CONTROLm
   7290                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7291                 soc_mem_field32_set(unit, VLAN_XLATE_1_HASH_CONTROLm ,
   7292                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7293             SOC_IF_ERROR_RETURN
   7294                 (WRITE_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7295                                                   hash_control_entry));
   7296             ROBUSTHASH(unit)->ing_xlate_1.enable = 0;
   7297         } else {
   7298             /* Enable robust hashing */
   7299             SOC_IF_ERROR_RETURN
   7300                 (READ_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7301                                                  hash_control_entry));
   7302             soc_mem_field32_set(unit, VLAN_XLATE_1_HASH_CONTROLm,
   7303                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7304             SOC_IF_ERROR_RETURN
   7305                 (WRITE_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7306                                                   hash_control_entry));
   7307             ROBUSTHASH(unit)->ing_xlate_1.enable = 1;
   7308 
   7309             /* Configure remap and action tables for VLAN XLATE 1 table */
   7310             ROBUSTHASH(unit)->ing_xlate_1.remap_tab[0] = VLAN_XLATE_1_REMAP_TABLE_Am;
   7311             ROBUSTHASH(unit)->ing_xlate_1.remap_tab[1] = VLAN_XLATE_1_REMAP_TABLE_Bm;
   7312             ROBUSTHASH(unit)->ing_xlate_1.action_tab[0] = VLAN_XLATE_1_ACTION_TABLE_Am;
   7313             ROBUSTHASH(unit)->ing_xlate_1.action_tab[1] = VLAN_XLATE_1_ACTION_TABLE_Bm;
   7314 
   7315             /* Initialize seed for robust hash */
   7316             seed = soc_property_get
   7317                     (unit, spn_ROBUST_HASH_SEED_VLAN_1, 16777213);
   7318 
   7319             SOC_IF_ERROR_RETURN
   7320                 (soc_robust_hash_table_set(unit,
   7321                                            &(ROBUSTHASH(unit)->ing_xlate_1),
   7322                                            seed));
   7323         }
   7324 
   7325         /* Vlan Xlate 2 Robust Hash Init */
   7326 
   7327         sal_memset
   7328             (hash_control_entry, 0, sizeof(hash_control_entry));
   7329 
   7330         /* Disable robust hash for Vlan Xlate 2 - this config variable is used
   7331          * only for debug purposes*/
   7332         if ((soc_property_get
   7333                 (unit, "robust_hash_disable_vlan2", 0)) == 1) {
   7334             SOC_IF_ERROR_RETURN
   7335                 (READ_VLAN_XLATE_2_HASH_CONTROLm
   7336                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7337                 soc_mem_field32_set(unit, VLAN_XLATE_2_HASH_CONTROLm ,
   7338                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7339             SOC_IF_ERROR_RETURN
   7340                 (WRITE_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7341                                                   hash_control_entry));
   7342             ROBUSTHASH(unit)->ing_xlate_2.enable = 0;
   7343         } else {
   7344             /* Enable robust hashing */
   7345             SOC_IF_ERROR_RETURN
   7346                 (READ_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7347                                                  hash_control_entry));
   7348             soc_mem_field32_set(unit, VLAN_XLATE_2_HASH_CONTROLm,
   7349                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7350             SOC_IF_ERROR_RETURN
   7351                 (WRITE_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7352                                                   hash_control_entry));
   7353             ROBUSTHASH(unit)->ing_xlate_2.enable = 1;
   7354 
   7355             /* Configure remap and action tables for VLAN XLATE 2 table */
   7356             ROBUSTHASH(unit)->ing_xlate_2.remap_tab[0] = VLAN_XLATE_2_REMAP_TABLE_Am;
   7357             ROBUSTHASH(unit)->ing_xlate_2.remap_tab[1] = VLAN_XLATE_2_REMAP_TABLE_Bm;
   7358             ROBUSTHASH(unit)->ing_xlate_2.action_tab[0] = VLAN_XLATE_2_ACTION_TABLE_Am;
   7359             ROBUSTHASH(unit)->ing_xlate_2.action_tab[1] = VLAN_XLATE_2_ACTION_TABLE_Bm;
   7360 
   7361             /* Initialize seed for robust hash */
   7362             seed = soc_property_get
   7363                     (unit, spn_ROBUST_HASH_SEED_VLAN_2, 16777213);
   7364 
   7365             SOC_IF_ERROR_RETURN
   7366                 (soc_robust_hash_table_set(unit,
   7367                                            &(ROBUSTHASH(unit)->ing_xlate_2),
   7368                                            seed));
   7369         }
   7370 
   7371         /* Egr Vlan Xlate 1 Robust Hash Init */
   7372 
   7373         sal_memset
   7374             (hash_control_entry, 0, sizeof(hash_control_entry));
   7375 
   7376         /* Disable robust hash for Egr Vlan Xlate 1 - this config variable is
   7377          * used only for debug purposes*/
   7378         if ((soc_property_get
   7379                 (unit, "robust_hash_disable_egress_vlan1", 0)) == 1) {
   7380             SOC_IF_ERROR_RETURN
   7381                 (READ_EGR_VLAN_XLATE_1_HASH_CONTROLm
   7382                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7383                 soc_mem_field32_set(unit, EGR_VLAN_XLATE_1_HASH_CONTROLm ,
   7384                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7385             SOC_IF_ERROR_RETURN
   7386                 (WRITE_EGR_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7387                                                         hash_control_entry));
   7388             ROBUSTHASH(unit)->egr_xlate_1.enable = 0;
   7389         } else {
   7390             /* Enable robust hashing */
   7391             SOC_IF_ERROR_RETURN
   7392                 (READ_EGR_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7393                                                      hash_control_entry));
   7394             soc_mem_field32_set(unit, EGR_VLAN_XLATE_1_HASH_CONTROLm,
   7395                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7396             SOC_IF_ERROR_RETURN
   7397                 (WRITE_EGR_VLAN_XLATE_1_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7398                                                       hash_control_entry));
   7399             ROBUSTHASH(unit)->egr_xlate_1.enable = 1;
   7400 
   7401             /* Configure remap and action tables for EGR VLAN XLATE 1 table */
   7402             ROBUSTHASH(unit)->egr_xlate_1.remap_tab[0] = EGR_VLAN_XLATE_1_REMAP_TABLE_Am;
   7403             ROBUSTHASH(unit)->egr_xlate_1.remap_tab[1] = EGR_VLAN_XLATE_1_REMAP_TABLE_Bm;
   7404             ROBUSTHASH(unit)->egr_xlate_1.action_tab[0] = EGR_VLAN_XLATE_1_ACTION_TABLE_Am;
   7405             ROBUSTHASH(unit)->egr_xlate_1.action_tab[1] = EGR_VLAN_XLATE_1_ACTION_TABLE_Bm;
   7406 
   7407             /* Initialize seed for robust hash */
   7408             seed = soc_property_get
   7409                     (unit, spn_ROBUST_HASH_SEED_EGRESS_VLAN_1, 16777213);
   7410 
   7411             SOC_IF_ERROR_RETURN
   7412                 (soc_robust_hash_table_set(unit,
   7413                                            &(ROBUSTHASH(unit)->egr_xlate_1),
   7414                                            seed));
   7415         }
   7416 
   7417         /* Egr Vlan Xlate 2 Robust Hash Init */
   7418 
   7419         sal_memset
   7420             (hash_control_entry, 0, sizeof(hash_control_entry));
   7421 
   7422         /* Disable robust hash for Egr Vlan Xlate 2 - this config variable is
   7423          * used only for debug purposes*/
   7424         if ((soc_property_get
   7425                 (unit, "robust_hash_disable_egress_vlan2", 0)) == 1) {
   7426             SOC_IF_ERROR_RETURN
   7427                 (READ_EGR_VLAN_XLATE_2_HASH_CONTROLm
   7428                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7429                 soc_mem_field32_set(unit, EGR_VLAN_XLATE_2_HASH_CONTROLm ,
   7430                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7431             SOC_IF_ERROR_RETURN
   7432                 (WRITE_EGR_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7433                                                         hash_control_entry));
   7434             ROBUSTHASH(unit)->egr_xlate_2.enable = 0;
   7435         } else {
   7436             /* Enable robust hashing */
   7437             SOC_IF_ERROR_RETURN
   7438                 (READ_EGR_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7439                                                      hash_control_entry));
   7440             soc_mem_field32_set(unit, EGR_VLAN_XLATE_2_HASH_CONTROLm,
   7441                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7442             SOC_IF_ERROR_RETURN
   7443                 (WRITE_EGR_VLAN_XLATE_2_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7444                                                       hash_control_entry));
   7445             ROBUSTHASH(unit)->egr_xlate_2.enable = 1;
   7446 
   7447             /* Configure remap and action tables for EGR VLAN XLATE 2 table */
   7448             ROBUSTHASH(unit)->egr_xlate_2.remap_tab[0] = EGR_VLAN_XLATE_2_REMAP_TABLE_Am;
   7449             ROBUSTHASH(unit)->egr_xlate_2.remap_tab[1] = EGR_VLAN_XLATE_2_REMAP_TABLE_Bm;
   7450             ROBUSTHASH(unit)->egr_xlate_2.action_tab[0] = EGR_VLAN_XLATE_2_ACTION_TABLE_Am;
   7451             ROBUSTHASH(unit)->egr_xlate_2.action_tab[1] = EGR_VLAN_XLATE_2_ACTION_TABLE_Bm;
   7452 
   7453             /* Initialize seed for robust hash */
   7454             seed = soc_property_get
   7455                     (unit, spn_ROBUST_HASH_SEED_EGRESS_VLAN_2, 16777213);
   7456 
   7457             SOC_IF_ERROR_RETURN
   7458                 (soc_robust_hash_table_set(unit,
   7459                                            &(ROBUSTHASH(unit)->egr_xlate_2),
   7460                                            seed));
   7461         }
   7462         /* Ing vlan vp Robust Hash Init */
   7463 
   7464         sal_memset
   7465             (hash_control_entry, 0, sizeof(hash_control_entry));
   7466 
   7467         /* Disable robust hash for ing vp vlan - this config variable is
   7468          * used only for debug purposes*/
   7469         if ((soc_property_get
   7470                 (unit, "robust_hash_disable_ing_vp_vlan", 0)) == 1) {
   7471             SOC_IF_ERROR_RETURN
   7472                 (READ_ING_VP_VLAN_MEMBERSHIP_HASH_CONTROLm
   7473                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7474                 soc_mem_field32_set(unit, ING_VP_VLAN_MEMBERSHIP_HASH_CONTROLm ,
   7475                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7476             SOC_IF_ERROR_RETURN
   7477                 (WRITE_ING_VP_VLAN_MEMBERSHIP_HASH_CONTROLm
   7478                     (unit, MEM_BLOCK_ALL, 0, hash_control_entry));
   7479             ROBUSTHASH(unit)->ing_vp_vlan_member.enable = 0;
   7480         } else {
   7481             /* Enable robust hashing */
   7482             SOC_IF_ERROR_RETURN
   7483                 (READ_ING_VP_VLAN_MEMBERSHIP_HASH_CONTROLm(unit, MEM_BLOCK_ANY,
   7484                                                             0, hash_control_entry));
   7485             soc_mem_field32_set(unit, ING_VP_VLAN_MEMBERSHIP_HASH_CONTROLm,
   7486                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7487             SOC_IF_ERROR_RETURN
   7488                 (WRITE_ING_VP_VLAN_MEMBERSHIP_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7489                                                             hash_control_entry));
   7490             ROBUSTHASH(unit)->ing_vp_vlan_member.enable = 1;
   7491 
   7492             /* Configure remap and action tables for ing vp vlan table */
   7493             ROBUSTHASH(unit)->ing_vp_vlan_member.remap_tab[0] =
   7494                                         ING_VP_VLAN_MEMBERSHIP_REMAP_TABLE_Am;
   7495             ROBUSTHASH(unit)->ing_vp_vlan_member.remap_tab[1] =
   7496                                         ING_VP_VLAN_MEMBERSHIP_REMAP_TABLE_Bm;
   7497             ROBUSTHASH(unit)->ing_vp_vlan_member.action_tab[0] =
   7498                                         ING_VP_VLAN_MEMBERSHIP_ACTION_TABLE_Am;
   7499             ROBUSTHASH(unit)->ing_vp_vlan_member.action_tab[1] =
   7500                                         ING_VP_VLAN_MEMBERSHIP_ACTION_TABLE_Bm;
   7501 
   7502             seed = soc_property_get(unit,
   7503                                     spn_ROBUST_HASH_SEED_INGRESS_VP_VLAN,
   7504                                     16777213);
   7505 
   7506             SOC_IF_ERROR_RETURN
   7507                 (soc_robust_hash_table_set(unit,
   7508                                         &(ROBUSTHASH(unit)->ing_vp_vlan_member),
   7509                                         seed));
   7510         }
   7511 
   7512         /* Egr vlan vp Robust Hash Init */
   7513 
   7514         sal_memset
   7515             (hash_control_entry, 0, sizeof(hash_control_entry));
   7516         /* Disable robust hash for egr vp vlan - this config variable is
   7517          * used only for debug purposes*/
   7518         if ((soc_property_get
   7519                 (unit, "robust_hash_disable_egr_vp_vlan", 0)) == 1) {
   7520             SOC_IF_ERROR_RETURN
   7521                 (READ_EGR_VP_VLAN_MEMBERSHIP_HASH_CONTROLm
   7522                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7523                 soc_mem_field32_set(unit, EGR_VP_VLAN_MEMBERSHIP_HASH_CONTROLm ,
   7524                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7525             SOC_IF_ERROR_RETURN
   7526                 (WRITE_EGR_VP_VLAN_MEMBERSHIP_HASH_CONTROLm
   7527                     (unit, MEM_BLOCK_ALL, 0, hash_control_entry));
   7528             ROBUSTHASH(unit)->egr_vp_vlan_member.enable = 0;
   7529         } else {
   7530             /* Enable robust hashing */
   7531             SOC_IF_ERROR_RETURN
   7532                 (READ_EGR_VP_VLAN_MEMBERSHIP_HASH_CONTROLm(unit, MEM_BLOCK_ANY,
   7533                                                             0, hash_control_entry));
   7534             soc_mem_field32_set(unit, EGR_VP_VLAN_MEMBERSHIP_HASH_CONTROLm,
   7535                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7536             SOC_IF_ERROR_RETURN
   7537                 (WRITE_EGR_VP_VLAN_MEMBERSHIP_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7538                                                             hash_control_entry));
   7539             ROBUSTHASH(unit)->egr_vp_vlan_member.enable = 1;
   7540 
   7541             /* Configure remap and action tables for ing vp vlan table */
   7542             ROBUSTHASH(unit)->egr_vp_vlan_member.remap_tab[0] =
   7543                                         EGR_VP_VLAN_MEMBERSHIP_REMAP_TABLE_Am;
   7544             ROBUSTHASH(unit)->egr_vp_vlan_member.remap_tab[1] =
   7545                                         EGR_VP_VLAN_MEMBERSHIP_REMAP_TABLE_Bm;
   7546             ROBUSTHASH(unit)->egr_vp_vlan_member.action_tab[0] =
   7547                                         EGR_VP_VLAN_MEMBERSHIP_ACTION_TABLE_Am;
   7548             ROBUSTHASH(unit)->egr_vp_vlan_member.action_tab[1] =
   7549                                         EGR_VP_VLAN_MEMBERSHIP_ACTION_TABLE_Bm;
   7550 
   7551             seed = soc_property_get(unit,
   7552                                     spn_ROBUST_HASH_SEED_EGRESS_VP_VLAN,
   7553                                     16777213);
   7554 
   7555             SOC_IF_ERROR_RETURN
   7556                 (soc_robust_hash_table_set(unit,
   7557                                         &(ROBUSTHASH(unit)->egr_vp_vlan_member),
   7558                                         seed));
   7559         }
   7560 
   7561         /* Mpls Robust Hash Init */
   7562 
   7563         sal_memset
   7564             (hash_control_entry, 0, sizeof(hash_control_entry));
   7565 
   7566         /* Disable robust hash for mpls - this config variable is
   7567          * used only for debug purposes*/
   7568         if ((soc_property_get
   7569                 (unit, "robust_hash_disable_mpls", 0)) == 1) {
   7570             SOC_IF_ERROR_RETURN
   7571                 (READ_MPLS_ENTRY_HASH_CONTROLm
   7572                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7573                 soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm ,
   7574                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7575             SOC_IF_ERROR_RETURN
   7576                 (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7577                                                         hash_control_entry));
   7578             ROBUSTHASH(unit)->mpls_entry.enable = 0;
   7579         } else {
   7580             /* Enable robust hashing */
   7581             SOC_IF_ERROR_RETURN
   7582                 (READ_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7583                                                      hash_control_entry));
   7584             soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm,
   7585                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7586             SOC_IF_ERROR_RETURN
   7587                 (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7588                                                       hash_control_entry));
   7589             ROBUSTHASH(unit)->mpls_entry.enable = 1;
   7590 
   7591             /* Configure remap and action tables for MPLS ENTRY table */
   7592             ROBUSTHASH(unit)->mpls_entry.remap_tab[0] =
   7593                                                 MPLS_ENTRY_REMAP_TABLE_Am;
   7594             ROBUSTHASH(unit)->mpls_entry.remap_tab[1] =
   7595                                                 MPLS_ENTRY_REMAP_TABLE_Bm;
   7596             ROBUSTHASH(unit)->mpls_entry.action_tab[0] =
   7597                                                 MPLS_ENTRY_ACTION_TABLE_Am;
   7598             ROBUSTHASH(unit)->mpls_entry.action_tab[1] =
   7599                                                 MPLS_ENTRY_ACTION_TABLE_Bm;
   7600 
   7601             /* Initialize seed for robust hash */
   7602             seed = soc_property_get
   7603                     (unit, spn_ROBUST_HASH_SEED_MPLS, 16777213);
   7604 
   7605             SOC_IF_ERROR_RETURN
   7606                 (soc_robust_hash_table_set(unit,
   7607                                            &(ROBUSTHASH(unit)->mpls_entry),
   7608                                            seed));
   7609         }
   7610 
   7611     if (SOC_MEM_IS_VALID(unit, ING_DNAT_ADDRESS_TYPE_HASH_CONTROLm)) {
   7612         /*  Ing Dnat Address Robust Hash Init */
   7613 
   7614         sal_memset
   7615             (hash_control_entry, 0, sizeof(hash_control_entry));
   7616 
   7617         /* Disable robust hash for ing dnat address type - this config variable
   7618          * is used only for debug purposes*/
   7619         if ((soc_property_get
   7620                 (unit, "robust_hash_disable_ing_dnat_address", 0)) == 1) {
   7621             SOC_IF_ERROR_RETURN
   7622                 (READ_ING_DNAT_ADDRESS_TYPE_HASH_CONTROLm
   7623                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7624                 soc_mem_field32_set(unit, ING_DNAT_ADDRESS_TYPE_HASH_CONTROLm ,
   7625                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7626             SOC_IF_ERROR_RETURN
   7627                 (WRITE_ING_DNAT_ADDRESS_TYPE_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7628                                                            hash_control_entry));
   7629             ROBUSTHASH(unit)->ing_dnat_address.enable = 0;
   7630         } else {
   7631             /* Enable robust hashing */
   7632             SOC_IF_ERROR_RETURN
   7633                 (READ_ING_DNAT_ADDRESS_TYPE_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7634                                                           hash_control_entry));
   7635             soc_mem_field32_set(unit, ING_DNAT_ADDRESS_TYPE_HASH_CONTROLm,
   7636                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7637             SOC_IF_ERROR_RETURN
   7638                 (WRITE_ING_DNAT_ADDRESS_TYPE_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7639                                                            hash_control_entry));
   7640             ROBUSTHASH(unit)->ing_dnat_address.enable = 1;
   7641 
   7642             /* Configure remap and action tables for ING DNAT ADDRESS table */
   7643             ROBUSTHASH(unit)->ing_dnat_address.remap_tab[0] =
   7644                                             ING_DNAT_ADDRESS_TYPE_REMAP_TABLE_Am;
   7645             ROBUSTHASH(unit)->ing_dnat_address.remap_tab[1] =
   7646                                             ING_DNAT_ADDRESS_TYPE_REMAP_TABLE_Bm;
   7647             ROBUSTHASH(unit)->ing_dnat_address.action_tab[0] =
   7648                                             ING_DNAT_ADDRESS_TYPE_ACTION_TABLE_Am;
   7649             ROBUSTHASH(unit)->ing_dnat_address.action_tab[1] =
   7650                                             ING_DNAT_ADDRESS_TYPE_ACTION_TABLE_Bm;
   7651 
   7652             /* Initialize seed for robust hash */
   7653             seed = soc_property_get
   7654                     (unit, spn_ROBUST_HASH_SEED_ING_DNAT_ADDRESS, 16777213);
   7655 
   7656             SOC_IF_ERROR_RETURN
   7657                 (soc_robust_hash_table_set(unit,
   7658                                            &(ROBUSTHASH(unit)->ing_dnat_address),
   7659                                            seed));
   7660         }
   7661     }
   7662 
   7663     if (SOC_MEM_IS_VALID(unit, SUBPORT_ID_TO_SGPP_MAP_HASH_CONTROLm)) {
   7664         /*  Subport id to sgpp map Robust Hash Init */
   7665 
   7666         sal_memset(hash_control_entry, 0, sizeof(hash_control_entry));
   7667 
   7668         /* Disable robust hash for subport id to sgpp map - this config
   7669          * variable is used only for debug purposes */
   7670         if ((soc_property_get
   7671                 (unit, "robust_hash_disable_subport_id_sgpp_map", 0)) == 1) {
   7672             SOC_IF_ERROR_RETURN
   7673                 (READ_SUBPORT_ID_TO_SGPP_MAP_HASH_CONTROLm
   7674                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   7675                 soc_mem_field32_set(unit, SUBPORT_ID_TO_SGPP_MAP_HASH_CONTROLm ,
   7676                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   7677             SOC_IF_ERROR_RETURN
   7678                 (WRITE_SUBPORT_ID_TO_SGPP_MAP_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7679                                                             hash_control_entry));
   7680             ROBUSTHASH(unit)->subport_id_sgpp_map.enable = 0;
   7681         } else {
   7682             /* Enable robust hashing */
   7683              SOC_IF_ERROR_RETURN
   7684                 (READ_SUBPORT_ID_TO_SGPP_MAP_KEY_ATTRIBUTESm(unit, MEM_BLOCK_ANY, 0,
   7685                                                            &sgpp_map_attr));
   7686             soc_mem_field32_set(unit, SUBPORT_ID_TO_SGPP_MAP_KEY_ATTRIBUTESm,
   7687                                &sgpp_map_attr, KEY_WIDTHf, 0x5);
   7688             SOC_IF_ERROR_RETURN
   7689                 (WRITE_SUBPORT_ID_TO_SGPP_MAP_KEY_ATTRIBUTESm(unit, MEM_BLOCK_ALL, 0,
   7690                                                             &sgpp_map_attr));
   7691             SOC_IF_ERROR_RETURN
   7692                 (READ_SUBPORT_ID_TO_SGPP_MAP_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   7693                                                            hash_control_entry));
   7694             soc_mem_field32_set(unit, SUBPORT_ID_TO_SGPP_MAP_HASH_CONTROLm,
   7695                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   7696             SOC_IF_ERROR_RETURN
   7697                 (WRITE_SUBPORT_ID_TO_SGPP_MAP_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   7698                                                             hash_control_entry));
   7699             ROBUSTHASH(unit)->subport_id_sgpp_map.enable = 1;
   7700 
   7701             /* Configure remap and action tables for Subport id to sgpp map table */
   7702             ROBUSTHASH(unit)->subport_id_sgpp_map.remap_tab[0] =
   7703                                             SUBPORT_ID_TO_SGPP_MAP_REMAP_TABLE_Am;
   7704             ROBUSTHASH(unit)->subport_id_sgpp_map.remap_tab[1] =
   7705                                             SUBPORT_ID_TO_SGPP_MAP_REMAP_TABLE_Bm;
   7706             ROBUSTHASH(unit)->subport_id_sgpp_map.action_tab[0] =
   7707                                             SUBPORT_ID_TO_SGPP_MAP_ACTION_TABLE_Am;
   7708             ROBUSTHASH(unit)->subport_id_sgpp_map.action_tab[1] =
   7709                                             SUBPORT_ID_TO_SGPP_MAP_ACTION_TABLE_Bm;
   7710 
   7711             /* Initialize seed for robust hash */
   7712             seed = soc_property_get
   7713                     (unit, spn_ROBUST_HASH_SEED_SUBPORT_ID_TO_SGPP_MAP, 16777213);
   7714 
   7715             SOC_IF_ERROR_RETURN
   7716                 (soc_robust_hash_table_set(unit,
   7717                                            &(ROBUSTHASH(unit)->subport_id_sgpp_map),
   7718                                            seed));
   7719         }
   7720     }
   7721     }
   7722 #endif /* SOC_ROBUST_HASH */
   7723     return SOC_E_NONE;
   7724 }
   7725 
   7726 STATIC int _soc_trident3_tdm_init(int unit)
   7727 {
   7728 	soc_control_t *soc = SOC_CONTROL(unit);
   7729 	soc_info_t *si = &SOC_INFO(unit);
   7730 	soc_port_schedule_state_t *port_schedule_state;
   7731 	soc_port_map_type_t *in_portmap;
   7732 	int port, speed;
   7733 	int rv;
   7734 	if (soc->tdm_info == NULL) {
   7735 		soc->tdm_info = sal_alloc(sizeof(_soc_trident3_tdm_temp_t),
   7736 									"Trident3 TDM info");
   7737 		if (soc->tdm_info == NULL) {
   7738 			return SOC_E_MEMORY;
   7739 		}
   7740 		sal_memset(soc->tdm_info, 0, sizeof(_soc_trident3_tdm_temp_t));
   7741 	}
   7742 
   7743 #if defined(BCM_WARM_BOOT_SUPPORT)
   7744     if (SOC_WARM_BOOT(unit)) {
   7745         SOC_IF_ERROR_RETURN(
   7746             soc_td3_tdm_scache_recovery(unit));
   7747         return SOC_E_NONE;
   7748     } else {
   7749         SOC_IF_ERROR_RETURN(
   7750             soc_td3_tdm_scache_allocate(unit));
   7751     }
   7752 #endif
   7753 	port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t),
   7754                                     "Trident3 soc_port_schedule_state_t");
   7755 	if (port_schedule_state == NULL) {
   7756         return SOC_E_MEMORY;
   7757     }
   7758 	sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t));
   7759 	/* Core clock frequency */
   7760 	port_schedule_state->frequency = si->frequency;
   7761 
   7762 	/* Construct in_port_map */
   7763 	in_portmap = &port_schedule_state->in_port_map;
   7764 	PBMP_PORT_ITER(unit, port) {
   7765 		if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   7766 			continue;
   7767 		}
   7768 		if (IS_HG_PORT(unit, port)) {
   7769             speed = soc_port_speed_higig2eth(si->port_speed_max[port]);
   7770         } else {
   7771             speed = si->port_speed_max[port];
   7772         }
   7773         in_portmap->log_port_speed[port] = speed;
   7774         in_portmap->port_num_lanes[port] = si->port_num_lanes[port];
   7775 	}
   7776 	sal_memcpy(in_portmap->port_p2l_mapping, si->port_p2l_mapping,
   7777                 sizeof(int)*TRIDENT3_TDM_PHY_PORTS_PER_DEV);
   7778     sal_memcpy(in_portmap->port_l2p_mapping, si->port_l2p_mapping,
   7779                 sizeof(int)*_TD3_TDM_DEV_PORTS_PER_DEV);
   7780     sal_memcpy(in_portmap->port_p2m_mapping, si->port_p2m_mapping,
   7781                 sizeof(int)*TRIDENT3_TDM_PHY_PORTS_PER_DEV);
   7782     sal_memcpy(in_portmap->port_m2p_mapping, si->port_m2p_mapping,
   7783                 sizeof(int)*_TD3_TDM_MMU_PORTS_PER_DEV);
   7784     sal_memcpy(in_portmap->port_l2i_mapping, si->port_l2i_mapping,
   7785                 sizeof(int)*_TD3_TDM_DEV_PORTS_PER_DEV);
   7786     sal_memcpy(&in_portmap->physical_pbm, &si->physical_pbm, sizeof(pbmp_t));
   7787     sal_memcpy(&in_portmap->hg2_pbm, &si->hg.bitmap, sizeof(pbmp_t));
   7788     sal_memcpy(&in_portmap->management_pbm, &si->management_pbm,
   7789                 sizeof(pbmp_t));
   7790     sal_memcpy(&in_portmap->oversub_pbm, &si->oversub_pbm, sizeof(pbmp_t));
   7791 
   7792 	port_schedule_state->is_flexport = 0;
   7793 	rv = soc_td3_port_schedule_tdm_init(unit, port_schedule_state);
   7794 
   7795     rv = soc_td3_tdm_init(unit, port_schedule_state);
   7796 	if (rv != SOC_E_NONE) {
   7797         LOG_CLI((BSL_META_U(unit,
   7798             "Unsupported config for TDM calendar generation\n")));
   7799         sal_free(port_schedule_state);
   7800         return rv;
   7801     }
   7802 	rv = soc_td3_soc_tdm_update(unit, port_schedule_state);
   7803 
   7804     sal_free(port_schedule_state);
   7805 
   7806     return rv;
   7807 }
   7808 
   7809 /* For a given logical port, return the OBM id and the lane number */
   7810 int
   7811 soc_trident3_port_obm_info_get(int unit, soc_port_t port,
   7812                                int *obm_id, int *lane)
   7813 {
   7814     soc_info_t *si;
   7815     soc_port_t phy_port;
   7816     int clport, port_block_base;
   7817 
   7818     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
   7819         (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port))) {
   7820         return SOC_E_PARAM;
   7821     }
   7822     si = &SOC_INFO(unit);
   7823     phy_port = si->port_l2p_mapping[port];
   7824     port_block_base = PORT_BLOCK_BASE_PORT(port);
   7825     if (lane != NULL) {
   7826         *lane = (phy_port - port_block_base) % _TD3_PORTS_PER_PBLK;
   7827     }
   7828 
   7829     clport = si->port_serdes[port];
   7830     if ((obm_id != NULL) && (NUM_PIPE(unit) != 1)) {
   7831         *obm_id = clport & 0xF;
   7832     } else {
   7833         *obm_id = clport;
   7834     }
   7835     return SOC_E_NONE;
   7836 }
   7837 
   7838 extern int
   7839 (*_phy_tsce_firmware_set_helper[SOC_MAX_NUM_DEVICES])(int, int, uint8 *, int);
   7840 extern int
   7841 (*_phy_tscf_firmware_set_helper[SOC_MAX_NUM_DEVICES])(int, int, uint8 *, int);
   7842 
   7843 int
   7844 soc_trident3_tscx_firmware_set(int unit, int port, uint8 *array, int datalen)
   7845 {
   7846     soc_mem_t mem = IS_CL_PORT(unit, port) ?
   7847                     CLPORT_WC_UCMEM_DATAm : XLPORT_WC_UCMEM_DATAm;
   7848     soc_reg_t reg = IS_CL_PORT(unit, port) ?
   7849                     CLPORT_WC_UCMEM_CTRLr : XLPORT_WC_UCMEM_CTRLr;
   7850 
   7851     return soc_warpcore_firmware_set(unit, port, array, datalen, 0, mem, reg);
   7852 }
   7853 
   7854 #define TSC_REG_ADDR_TSCID_SET(_phy_reg, _phyad)    \
   7855                             ((_phy_reg) |= ((_phyad) & 0x1f) << 19)
   7856 
   7857 STATIC int
   7858 _soc_trident3_mdio_addr_to_port(uint32 phy_addr)
   7859 {
   7860     int bus, offset;
   7861 
   7862     /* Must be internal MDIO address */
   7863     if ((phy_addr & 0x80) == 0) {
   7864         return 0;
   7865     }
   7866 
   7867     /*
   7868      * Internal phy address:
   7869      * bus 0 phy 1 to 24 are mapped to Physical port 1 to 24
   7870      * bus 1 phy 1 to 16 are mapped to Physical port 25 to 40
   7871      * bus 2 phy 1 to 24 are mapped to Physical port 41 to 84
   7872      * bus 3 phy 1 to 24 are mapped to Physical port 85 to 88
   7873      * bus 4 phy 1 to 16 are mapped to Physical port 89 to 104
   7874      * bus 5 phy 1 to 24 are mapped to Physical port 105 to 128
   7875      * bus 6 phy 1 is mapped to Physical port 129 and
   7876      *       phy 3 is mapped to Physical port 131
   7877      */
   7878     bus = PHY_ID_BUS_NUM(phy_addr);
   7879     if (bus > 6) {
   7880         return 0;
   7881     }
   7882     switch (bus) {
   7883     case 0: offset = 0;
   7884         break;
   7885     case 1: offset = 24;
   7886         break;
   7887     case 2: offset = 40;
   7888         break;
   7889     case 3: offset = 84;
   7890         break;
   7891     case 4: offset = 88;
   7892         break;
   7893     case 5: offset = 104;
   7894         break;
   7895     case 6: offset = 128;
   7896         if ((phy_addr & 0x1f) == 2 || (phy_addr & 0x1f) > 3) {
   7897             return 0;
   7898         }
   7899         break;
   7900     default:
   7901         return 0;
   7902     }
   7903 
   7904     return (phy_addr & 0x1f) + offset;
   7905 }
   7906 
   7907 STATIC int
   7908 _soc_trident3_tscx_reg_read(int unit, uint32 phy_addr,
   7909                             uint32 phy_reg, uint32 *phy_data)
   7910 {
   7911     int rv, blk, port;
   7912     int phy_port = _soc_trident3_mdio_addr_to_port(phy_addr);
   7913 
   7914     port = SOC_INFO(unit).port_p2l_mapping[phy_port];
   7915     blk = SOC_PORT_BLOCK(unit, phy_port);
   7916     LOG_INFO(BSL_LS_SOC_MII,
   7917              (BSL_META_U(unit,
   7918                          "soc_trident3_tscx_reg_read[%d]: %d/%d/%d/%d\n"),
   7919               unit, phy_addr, phy_port, port, blk));
   7920     TSC_REG_ADDR_TSCID_SET(phy_reg, phy_addr);
   7921     rv = soc_sbus_tsc_reg_read(unit, port, blk, phy_addr,
   7922                                phy_reg, phy_data);
   7923     return rv;
   7924 }
   7925 
   7926 STATIC int
   7927 _soc_trident3_tscx_reg_write(int unit, uint32 phy_addr,
   7928                              uint32 phy_reg, uint32 phy_data)
   7929 {
   7930     int rv, blk, port;
   7931     int phy_port = _soc_trident3_mdio_addr_to_port(phy_addr);
   7932 
   7933     port = SOC_INFO(unit).port_p2l_mapping[phy_port];
   7934     blk = SOC_PORT_BLOCK(unit, phy_port);
   7935     LOG_INFO(BSL_LS_SOC_MII,
   7936              (BSL_META_U(unit,
   7937                          "soc_trident3_tscx_reg_write[%d]: %d/%d/%d/%d\n"),
   7938               unit, phy_addr, phy_port, port, blk));
   7939     TSC_REG_ADDR_TSCID_SET(phy_reg, phy_addr);
   7940     rv = soc_sbus_tsc_reg_write(unit, port, blk, phy_addr,
   7941                                 phy_reg, phy_data);
   7942     return rv;
   7943 }
   7944 
   7945 #ifdef BCM_CMICX_SUPPORT
   7946 STATIC int
   7947 _soc_td3_ledup_init(int unit)
   7948 {
   7949     soc_info_t *si = &SOC_INFO(unit);
   7950     int freq;
   7951     uint32 rval, clk_half_period, refresh_period;
   7952 
   7953     /* freq in KHz */
   7954     freq = (si->frequency) * 1000;
   7955 
   7956     /* For LED refresh period = 33 ms (about 30Hz)  */
   7957 
   7958     /* refresh period
   7959        = (required refresh period in sec)*(switch clock frequency in Hz)
   7960      */
   7961     refresh_period = (freq * 33);
   7962 
   7963     rval = 0;
   7964     soc_reg_field_set(unit, U0_LED_REFRESH_CTRLr, &rval,
   7965                       REFRESH_CYCLE_PERIODf, refresh_period);
   7966 
   7967     SOC_IF_ERROR_RETURN(WRITE_U0_LED_REFRESH_CTRLr(unit, rval));
   7968 
   7969     /* For LED clock period */
   7970     /* LEDCLK_HALF_PERIOD
   7971        = [(required LED clock period in sec)/2]*(M0SS clock frequency in Hz)
   7972 
   7973        Where M0SS freqency is 858MHz and
   7974        Typical LED clock period is 200ns(5MHz) = 2*10^-7
   7975      */
   7976     freq = 858 * 1000000;
   7977     clk_half_period = (freq + 2500000) / 5000000;
   7978     clk_half_period = clk_half_period / 2;
   7979 
   7980         rval = 0;
   7981     soc_reg_field_set(unit, U0_LED_CLK_DIV_CTRLr, &rval,
   7982                       LEDCLK_HALF_PERIODf, clk_half_period);
   7983 
   7984     SOC_IF_ERROR_RETURN(WRITE_U0_LED_CLK_DIV_CTRLr(unit, rval));
   7985 
   7986     /*  Fixed for TD3
   7987      *  When PM shift out the led data, it shift out lane 3 first,followed by lane 2, 1, and 0.
   7988      *  The LAST_PORT value to be the port number of sub-port 0. (124 for TD3)
   7989      */
   7990 
   7991     SOC_IF_ERROR_RETURN(READ_U0_LED_ACCU_CTRLr(unit, &rval));
   7992     soc_reg_field_set(unit, U0_LED_ACCU_CTRLr, &rval,
   7993                       LAST_PORTf, 124);
   7994     soc_reg_field_set(unit, U0_LED_ACCU_CTRLr, &rval,
   7995                       PORT_ENDIANNESSf, 1);
   7996     SOC_IF_ERROR_RETURN(WRITE_U0_LED_ACCU_CTRLr(unit, rval));
   7997 
   7998     /* Initialize M0s for LED and Firmware Link Scan*/
   7999     SOC_IF_ERROR_RETURN(soc_iproc_m0_init(unit));
   8000 
   8001     return SOC_E_NONE;
   8002 }
   8003 
   8004 #endif /* BCM_CMICX_SUPPORT */
   8005 
   8006 /*
   8007  * Function:
   8008  *      _soc_trident3_mmu_ep_credit_reset
   8009  * Purpose:
   8010  *      Initalize EP credits in MMU so EP is in charge
   8011  *      of distributing the correct number of credits.
   8012  * Parameters:
   8013  *      unit    - (IN) Unit number.
   8014  *      port    - (IN) Logical SOC port number.
   8015  * Returns:
   8016  *      SOC_E_XXX
   8017  */
   8018 STATIC int
   8019 _soc_trident3_mmu_ep_credit_reset(int unit, soc_port_t port)
   8020 {
   8021     soc_reg_t reg;
   8022     uint32 rval = 0;
   8023 
   8024     reg = MMU_PORT_CREDITr;
   8025 
   8026     soc_reg_field_set(unit, reg, &rval, INITIALIZEf, 1);
   8027     SOC_IF_ERROR_RETURN
   8028         (soc_reg32_set(unit, reg, port, 0, rval));
   8029     SOC_IF_ERROR_RETURN
   8030         (soc_reg32_set(unit, reg, port, 0, 0));
   8031 
   8032     return SOC_E_NONE;
   8033 }
   8034 
   8035 /*
   8036  * Function:
   8037  *      _soc_trident3_ing_fsaf_init
   8038  * Purpose:
   8039  *      Initalize ForceSAF global settings.
   8040  *      Currently, duration register is set. Should always be
   8041  *      targeted for a minimum duration of 2us.
   8042  * Parameters:
   8043  *      unit    - (IN) Unit number.
   8044  *      port    - (IN) Logical SOC port number.
   8045  * Returns:
   8046  *      SOC_E_XXX
   8047  * Note:
   8048  *      Per port settings leverage ASF init process.
   8049  */
   8050 STATIC int
   8051 _soc_trident3_ing_fsaf_init(int unit)
   8052 {
   8053     int pipe;
   8054     int duration;
   8055     uint64 rval64;
   8056     soc_info_t *si = &SOC_INFO(unit);
   8057     soc_reg_t reg;
   8058     static const soc_reg_t idb_fsaf_cfg = IDB_DBG_Br;
   8059 
   8060     duration = si->frequency * 2;
   8061     for (pipe = 0; pipe < si->num_pipe; pipe ++) {
   8062         reg = SOC_REG_UNIQUE_ACC(unit, idb_fsaf_cfg)[pipe];
   8063         SOC_IF_ERROR_RETURN
   8064             (soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval64));
   8065         soc_reg64_field32_set(unit, reg, &rval64, FIELD_Af, duration);
   8066         SOC_IF_ERROR_RETURN
   8067             (soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval64));
   8068     }
   8069 
   8070     return SOC_E_NONE;
   8071 }
   8072 
   8073 /*
   8074  * Function:
   8075  *      soc_trident3_edb_buf_reset
   8076  * Purpose:
   8077  *      Initialize EP credits in MMU, release EDB port buffer and
   8078  *      enable cell request in EP.
   8079  * Parameters:
   8080  *      unit    - (IN) Unit number.
   8081  *      port    - (IN) Logical SOC port number.
   8082  *      reset   - (IN) Reset.
   8083  * Returns:
   8084  *      SOC_E_XXX
   8085  */
   8086 int
   8087 soc_trident3_edb_buf_reset(int unit, soc_port_t port, int reset)
   8088 {
   8089     soc_info_t *si = &SOC_INFO(unit);
   8090     uint32 entry[SOC_MAX_MEM_WORDS];
   8091     int phy_port;
   8092     uint32 rval;
   8093     int level;
   8094     soc_timeout_t to;
   8095     int wait_time = 250000;
   8096 
   8097     if (SAL_BOOT_QUICKTURN) {
   8098         wait_time *= 20;
   8099     }
   8100 
   8101     /* Get physical port */
   8102     phy_port = si->port_l2p_mapping[port];
   8103     if (phy_port == -1) {
   8104         return SOC_E_INTERNAL;
   8105     }
   8106 
   8107     if (reset) {
   8108         /* Set register to get number of used entries in EDB buffer */
   8109         SOC_IF_ERROR_RETURN
   8110             (READ_EGR_EDB_MISC_CTRLr(unit, &rval));
   8111         soc_reg_field_set(unit, EGR_EDB_MISC_CTRLr, &rval,
   8112                           SELECT_CURRENT_USED_ENTRIESf, 1);
   8113         SOC_IF_ERROR_RETURN
   8114             (WRITE_EGR_EDB_MISC_CTRLr(unit, rval));
   8115 
   8116         soc_timeout_init(&to, wait_time, 0);
   8117 
   8118         /* Poll until EDB buffer is empty */
   8119         for (;;) {
   8120             SOC_IF_ERROR_RETURN
   8121                 (READ_EGR_MAX_USED_ENTRIESm(unit, MEM_BLOCK_ALL,
   8122                                             phy_port, entry));
   8123             level = soc_mem_field32_get(unit, EGR_MAX_USED_ENTRIESm,
   8124                                         entry, LEVELf);
   8125             if (level == 0) {
   8126                 break;
   8127             }
   8128             if (soc_timeout_check(&to)) {
   8129                 LOG_ERROR(BSL_LS_SOC_PORT,
   8130                           (BSL_META_U(unit,
   8131                                       "EDB buffer drain timeout: "
   8132                                       "port %d, %s, "
   8133                                       "timeout (pending: %d)\n"),
   8134                            unit, SOC_PORT_NAME(unit, port), level));
   8135                 return SOC_E_INTERNAL;
   8136             }
   8137         }
   8138 
   8139         /*
   8140          * Hold EDB port buffer in reset state and disable cell
   8141          * request generation in EP.
   8142          */
   8143         SOC_IF_ERROR_RETURN
   8144             (READ_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
   8145                                                  phy_port, entry));
   8146         soc_mem_field32_set(unit, EGR_PER_PORT_BUFFER_SFT_RESETm,
   8147                             entry, ENABLEf, 1);
   8148         SOC_IF_ERROR_RETURN
   8149             (WRITE_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
   8150                                                   phy_port, entry));
   8151         SOC_IF_ERROR_RETURN
   8152             (READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry));
   8153         soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 0);
   8154         SOC_IF_ERROR_RETURN
   8155             (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry));
   8156 
   8157     } else {
   8158 
   8159         /* Initialize EP credits in MMU */
   8160         SOC_IF_ERROR_RETURN(_soc_trident3_mmu_ep_credit_reset(unit, port));
   8161 
   8162         /*
   8163          * Release EDB port buffer reset and
   8164          * enable cell request generation in EP.
   8165          */
   8166         SOC_IF_ERROR_RETURN
   8167             (READ_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
   8168                                                  phy_port, entry));
   8169         soc_mem_field32_set(unit, EGR_PER_PORT_BUFFER_SFT_RESETm,
   8170                             entry, ENABLEf, 0);
   8171         SOC_IF_ERROR_RETURN
   8172             (WRITE_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
   8173                                                   phy_port, entry));
   8174 
   8175         SOC_IF_ERROR_RETURN
   8176             (READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry));
   8177         soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 1);
   8178         SOC_IF_ERROR_RETURN
   8179             (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry));
   8180     }
   8181 
   8182     return SOC_E_NONE;
   8183 }
   8184 
   8185 soc_error_t
   8186 soc_trident3_idb_buf_reset(int unit, soc_port_t port, int reset)
   8187 {
   8188     soc_reg_t reg, reg1;
   8189     int port_block_base, phy_port, lane;
   8190     int pipe, obm, clport, obm_usage_count = ~0, ca_empty = 0;
   8191     uint32 rval;
   8192     uint64 rval1, rval2;
   8193     soc_info_t *si = &SOC_INFO(unit);
   8194     static const soc_reg_t idb_obm_usage_regs[] = {
   8195         IDB_OBM0_USAGEr, IDB_OBM1_USAGEr,
   8196         IDB_OBM2_USAGEr, IDB_OBM3_USAGEr,
   8197         IDB_OBM4_USAGEr, IDB_OBM5_USAGEr,
   8198         IDB_OBM6_USAGEr, IDB_OBM7_USAGEr,
   8199         IDB_OBM8_USAGEr, IDB_OBM9_USAGEr,
   8200         IDB_OBM10_USAGEr, IDB_OBM11_USAGEr,
   8201         IDB_OBM12_USAGEr, IDB_OBM13_USAGEr,
   8202         IDB_OBM14_USAGEr, IDB_OBM15_USAGEr
   8203     };
   8204     static const soc_reg_t idb_obm_ca_status_regs[] = {
   8205         IDB_OBM0_CA_HW_STATUSr, IDB_OBM1_CA_HW_STATUSr,
   8206         IDB_OBM2_CA_HW_STATUSr, IDB_OBM3_CA_HW_STATUSr,
   8207         IDB_OBM4_CA_HW_STATUSr, IDB_OBM5_CA_HW_STATUSr,
   8208         IDB_OBM6_CA_HW_STATUSr, IDB_OBM7_CA_HW_STATUSr,
   8209         IDB_OBM8_CA_HW_STATUSr, IDB_OBM9_CA_HW_STATUSr,
   8210         IDB_OBM10_CA_HW_STATUSr, IDB_OBM11_CA_HW_STATUSr,
   8211         IDB_OBM12_CA_HW_STATUSr, IDB_OBM13_CA_HW_STATUSr,
   8212         IDB_OBM14_CA_HW_STATUSr, IDB_OBM15_CA_HW_STATUSr
   8213     };
   8214     static const soc_reg_t obm_ctrl_regs[] = {
   8215         IDB_OBM0_CONTROLr, IDB_OBM1_CONTROLr,
   8216         IDB_OBM2_CONTROLr, IDB_OBM3_CONTROLr,
   8217         IDB_OBM4_CONTROLr, IDB_OBM5_CONTROLr,
   8218         IDB_OBM6_CONTROLr, IDB_OBM7_CONTROLr,
   8219         IDB_OBM8_CONTROLr, IDB_OBM9_CONTROLr,
   8220         IDB_OBM10_CONTROLr, IDB_OBM11_CONTROLr,
   8221         IDB_OBM12_CONTROLr, IDB_OBM13_CONTROLr,
   8222         IDB_OBM14_CONTROLr, IDB_OBM15_CONTROLr
   8223     };
   8224     static const soc_reg_t obm_ca_ctrl_regs[] = {
   8225         IDB_OBM0_CA_CONTROLr, IDB_OBM1_CA_CONTROLr,
   8226         IDB_OBM2_CA_CONTROLr, IDB_OBM3_CA_CONTROLr,
   8227         IDB_OBM4_CA_CONTROLr, IDB_OBM5_CA_CONTROLr,
   8228         IDB_OBM6_CA_CONTROLr, IDB_OBM7_CA_CONTROLr,
   8229         IDB_OBM8_CA_CONTROLr, IDB_OBM9_CA_CONTROLr,
   8230         IDB_OBM10_CA_CONTROLr, IDB_OBM11_CA_CONTROLr,
   8231         IDB_OBM12_CA_CONTROLr, IDB_OBM13_CA_CONTROLr,
   8232         IDB_OBM14_CA_CONTROLr, IDB_OBM15_CA_CONTROLr,
   8233     };
   8234     static const soc_field_t fifo_empty_port_fields[] = {
   8235         FIFO_EMPTY_PORT0f, FIFO_EMPTY_PORT1f, FIFO_EMPTY_PORT2f,
   8236         FIFO_EMPTY_PORT3f
   8237     };
   8238     static const soc_field_t port_reset_fields[] = {
   8239         PORT0_RESETf, PORT1_RESETf, PORT2_RESETf, PORT3_RESETf
   8240     };
   8241 
   8242     phy_port = si->port_l2p_mapping[port];
   8243     port_block_base = PORT_BLOCK_BASE_PORT(port);
   8244     lane = phy_port - port_block_base;
   8245     pipe = si->port_pipe[port];
   8246     clport = si->port_serdes[port];
   8247     obm = clport & 0xF;
   8248 
   8249     if (reset && !SAL_BOOT_SIMULATION) {
   8250         soc_timeout_t to;
   8251 
   8252         reg = SOC_REG_UNIQUE_ACC(unit, idb_obm_usage_regs[obm])[pipe];
   8253         reg1 = SOC_REG_UNIQUE_ACC(unit, idb_obm_ca_status_regs[obm])[pipe];
   8254 
   8255         soc_timeout_init(&to, 250000, 0);
   8256         /* Poll until IDB buffer is empty */
   8257         for (;;) {
   8258             if (0 != obm_usage_count) {
   8259                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, lane,
   8260                                                 &rval1));
   8261                 obm_usage_count = soc_reg64_field32_get(unit, reg, rval1,
   8262                                                         TOTAL_COUNTf);
   8263             }
   8264             if (0 == ca_empty) {
   8265                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg1, REG_PORT_ANY, 0,
   8266                                                 &rval2));
   8267                 ca_empty = soc_reg64_field32_get(unit, reg1, rval2,
   8268                                                  fifo_empty_port_fields[lane]);
   8269             }
   8270             if ((0 == obm_usage_count) && (1 == ca_empty)) {
   8271                 break;
   8272             }
   8273             if (soc_timeout_check(&to)) {
   8274                 LOG_ERROR(BSL_LS_SOC_COMMON,
   8275                           (BSL_META_U(unit,
   8276                                     "IDBBufferDrainTimeOut:port %d,%s, timeout"
   8277                                     "(idb_obm_usage: %d) "
   8278                                     "(ca_fifo_empty: %d)\n"),
   8279                           unit, SOC_PORT_NAME(unit, port), obm_usage_count,
   8280                           ca_empty));
   8281                 return SOC_E_INTERNAL;
   8282             }
   8283         }
   8284     }
   8285 
   8286     reg = SOC_REG_UNIQUE_ACC(unit, obm_ctrl_regs[obm])[pipe];
   8287     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   8288     soc_reg_field_set(unit, reg, &rval, port_reset_fields[lane], reset);
   8289     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   8290 
   8291     reg = SOC_REG_UNIQUE_ACC(unit, obm_ca_ctrl_regs[obm])[pipe];
   8292     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   8293     soc_reg_field_set(unit, reg, &rval, port_reset_fields[lane], reset);
   8294     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   8295 
   8296     return SOC_E_NONE;
   8297 }
   8298 
   8299 /*
   8300  * Function:
   8301  *      soc_td3_speed_class_validate
   8302  * Purpose:
   8303  *      Check speed classes
   8304  * Parameters:
   8305  *      unit     - (IN) Unit number.
   8306  * Returns:
   8307  *      SOC_E_XXX
   8308  * Note:
   8309  *      This function is called at early stage of initialization for
   8310  *      port configuration check.
   8311  */
   8312 int
   8313 soc_td3_speed_class_validate(int unit)
   8314 {
   8315     soc_info_t *si = &SOC_INFO(unit);
   8316     int port, speed;
   8317     uint32 speed_mask, count;
   8318 
   8319     speed_mask = 0;
   8320     PBMP_PORT_ITER(unit, port) {
   8321         if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port) ||
   8322             IS_MANAGEMENT_PORT(unit, port) || IS_CPU_PORT(unit, port) ||
   8323             IS_LB_PORT(unit, port)) {
   8324             continue;
   8325         }
   8326         speed = soc_port_speed_higig2eth(si->port_speed_max[port]);
   8327         speed_mask |= SOC_PA_SPEED(speed);
   8328     }
   8329 
   8330     count = _shr_popcount(speed_mask);
   8331     if (count > ((si->oversub_mode) ? 5 : 4)) {
   8332         LOG_ERROR(BSL_LS_BCM_COMMON,
   8333                   (BSL_META_U(unit,
   8334                               "No port configurations with more than 4 port "
   8335                               "speed classes are supported.\n")));
   8336         return SOC_E_CONFIG;
   8337     }
   8338 
   8339     if(SOC_FAILURE(soc_td3_speed_mix_validate(unit, speed_mask))) {
   8340         return SOC_E_CONFIG;
   8341     }
   8342 
   8343     return SOC_E_NONE;
   8344 }
   8345 
   8346 
   8347 STATIC int
   8348 _soc_trident3_misc_init(int unit)
   8349 {
   8350 #if defined(BCM_56870_A0)
   8351     soc_control_t *soc;
   8352     soc_info_t *si;
   8353     int block_info_idx;
   8354     soc_mem_t mem;
   8355     soc_reg_t reg;
   8356     uint32 rval, fval;
   8357     uint64 rval64;
   8358     soc_field_t fields[2];
   8359     uint32 values[2];
   8360     uint32 entry[SOC_MAX_MEM_WORDS];
   8361     soc_pbmp_t pbmp;
   8362     int clport, lane, mode, index, factor;
   8363     uint32 correction_duration, detection_duration;
   8364     int port, phy_port, phy_port_base;
   8365     int parity_enable, pbm_count=0;
   8366     modport_map_subport_entry_t map_entry;
   8367     ing_dest_port_enable_entry_t ingr_entry;
   8368 
   8369     static soc_field_t port_fields[_TD3_PORTS_PER_PBLK] = {
   8370         PORT0f, PORT1f, PORT2f, PORT3f
   8371     };
   8372     static const int mode_encodings[SOC_TD3_PORT_RATIO_COUNT] = {
   8373         4, 3, 3, 3, 2, 2, 1, 1, 0
   8374     };
   8375     uint32 mc_ctrl = 0;
   8376     int fabric_port_enable = 1;
   8377     int int_divisor, ext_divisor, delay;
   8378 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT)
   8379     int num_overlay_ecmp_rh_flowset_entries;
   8380     int ecmp_levels = 1;
   8381 #endif
   8382     int num_lag_rh_flowset_entries;
   8383 
   8384     soc = SOC_CONTROL(unit);
   8385     si = &SOC_INFO(unit);
   8386 
   8387     SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_stop(unit));
   8388     SOC_IF_ERROR_RETURN(soc_generic_sram_mem_scan_stop(unit));
   8389 
   8390     parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE);
   8391     if (parity_enable) {
   8392         if (!SOC_WARM_BOOT(unit)) {
   8393             /* Initialize PORT MIB counter */
   8394             rval = 0;
   8395             SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   8396                 port = SOC_BLOCK_PORT(unit, block_info_idx);
   8397                 soc_reg_field_set(unit, CLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf);
   8398                 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MIB_RESETr(unit, port, rval));
   8399                 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MIB_RESETr(unit, port, 0));
   8400             }
   8401             rval = 0;
   8402             SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_XLPORT) {
   8403                 port = SOC_BLOCK_PORT(unit, block_info_idx);
   8404                 soc_reg_field_set(unit, XLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf);
   8405                 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, rval));
   8406                 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, 0));
   8407             }
   8408             /* Certain mems/regs need to be cleared before enabling SER */
   8409             SOC_IF_ERROR_RETURN(soc_trident3_clear_mmu_memory(unit));
   8410             /*SOC_IF_ERROR_RETURN(_soc_trident3_clear_all_port_data(unit));*/
   8411         }
   8412         soc_ser_alpm_cache_check(unit);
   8413         soc_ser_log_init(unit, NULL, 0);
   8414 
   8415         /* Enable l2_mgmt interrupt */
   8416         SOC_IF_ERROR_RETURN
   8417             (soc_reg_field32_modify(unit, L2_MGMT_INTR_MASKr, REG_PORT_ANY,
   8418                                     SER_FIFO_NOT_EMPTYf, 1));
   8419 
   8420 #ifdef BCM_CMICX_SUPPORT
   8421     if (soc_feature(unit, soc_feature_cmicx)) {
   8422         
   8423         /* (void)soc_cmicm_intr3_enable(unit, 0x2); L2_MGMT_TO_CMIC_INTR bit 1 */
   8424     }
   8425 #endif
   8426         soc_trident3_tcam_ser_init(unit);
   8427         SOC_IF_ERROR_RETURN(soc_trident3_ser_enable_all(unit, TRUE));
   8428         soc_trident3_ser_register(unit);
   8429 
   8430 #if defined(SER_TR_TEST_SUPPORT)
   8431         /*Initialize chip-specific functions for SER testing*/
   8432         soc_td3_ser_test_register(unit);
   8433 #endif /*defined(SER_TR_TEST_SUPPORT*/
   8434     }
   8435 
   8436 #ifdef BCM_CMICX_SUPPORT
   8437     if (soc_feature(unit, soc_feature_cmicx) && !(SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM)) {
   8438         SOC_IF_ERROR_RETURN(_soc_td3_ledup_init(unit));
   8439     }
   8440 #endif /* BCM_CMICX_SUPPORT */
   8441 
   8442     SOC_IF_ERROR_RETURN(_soc_trident3_init_mmu_memory(unit));
   8443 
   8444     if (parity_enable) {
   8445         SOC_IF_ERROR_RETURN(soc_trident3_ser_enable_parity_table_all(unit, TRUE));
   8446         SOC_IF_ERROR_RETURN(READ_MMU_GCFG_MISCCONFIGr(unit, &rval));
   8447         soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, PARITY_ENf, 1);
   8448         SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   8449     }
   8450 
   8451     if (!SOC_IS_RELOADING(unit) && !SOC_WARM_BOOT(unit)) {
   8452         SOC_IF_ERROR_RETURN(
   8453             _soc_cancun_load_status_clear(unit, CANCUN_SOC_FILE_TYPE_CIH));
   8454         /* Dummy call to clear garbage h/w values */
   8455         SOC_IF_ERROR_RETURN
   8456             (soc_trident3_temperature_monitor_get(unit,
   8457                                                   COUNTOF(pvtmon_result_reg),
   8458                                                   NULL,
   8459                                                   NULL));
   8460     }
   8461 
   8462     /* UFT/UAT config programming */
   8463     SOC_IF_ERROR_RETURN(soc_trident3_uft_uat_config(unit));
   8464     soc_cancun_init(unit);
   8465     soc_trident3_latency_config(unit);
   8466     _soc_trident3_port_mapping_init(unit);
   8467 
   8468     /*
   8469      * Parse config at init time and cache property value for use at
   8470      * run time
   8471      */
   8472     if (SOC_PBMP_NOT_NULL(PBMP_HG_ALL(unit))) {
   8473         fabric_port_enable = 1;
   8474     } else {
   8475         fabric_port_enable = soc_property_get(unit, spn_FABRIC_PORT_ENABLE, 1);
   8476     }
   8477     SOC_CONTROL_LOCK(unit);
   8478     si->fabric_port_enable = fabric_port_enable;
   8479     SOC_CONTROL_UNLOCK(unit);
   8480 
   8481 
   8482     if (!SAL_BOOT_XGSSIM) {
   8483         if (soc->tdm_info == NULL) {
   8484             soc->tdm_info = sal_alloc(sizeof(_soc_trident3_tdm_temp_t),
   8485                                       "Trident3 TDM info");
   8486             if (soc->tdm_info == NULL) {
   8487                 return SOC_E_MEMORY;
   8488             }
   8489             sal_memset(soc->tdm_info, 0, sizeof(_soc_trident3_tdm_temp_t));
   8490         }
   8491         _soc_trident3_tdm_init(unit);
   8492         _soc_trident3_idb_init(unit);
   8493     }
   8494 
   8495     /* Check the speed classes */
   8496     SOC_IF_ERROR_RETURN(soc_td3_speed_class_validate(unit));
   8497 
   8498     sal_memset(entry, 0, sizeof(cpu_pbm_entry_t));
   8499     soc_mem_pbmp_field_set(unit, CPU_PBMm, entry, BITMAPf, &PBMP_CMIC(unit));
   8500     SOC_IF_ERROR_RETURN
   8501         (soc_mem_write(unit, CPU_PBMm, MEM_BLOCK_ALL, 0, entry));
   8502 
   8503     sal_memset(entry, 0, sizeof(cpu_pbm_2_entry_t));
   8504     soc_mem_pbmp_field_set(unit, CPU_PBM_2m, entry, BITMAPf, &PBMP_CMIC(unit));
   8505     SOC_IF_ERROR_RETURN
   8506         (soc_mem_write(unit, CPU_PBM_2m, MEM_BLOCK_ALL, 0, entry));
   8507 
   8508 #if __GNUC__ > 6
   8509 #pragma GCC diagnostic push
   8510 #pragma GCC diagnostic ignored "-Wmemset-elt-size"
   8511 #endif
   8512     /*
   8513      * We are NOT doing a sal_memset(entry,0,sizeof(entry)) for
   8514      * performance reasons, because the actual soc_mem_field_set()
   8515      * will only write sizeof(device_loopback_ports_bitmap_entry_t)=17
   8516      * bytes while sizeof(entry)=SOC_MAX_MEM_BYTES can be up to 651
   8517      * depending on which devices are compiled in.
   8518      */
   8519     sal_memset(entry, 0, sizeof(device_loopback_ports_bitmap_entry_t));
   8520 #if __GNUC__ > 6
   8521 #pragma GCC diagnostic pop
   8522 #endif
   8523     soc_mem_pbmp_field_set(unit, DEVICE_LOOPBACK_PORTS_BITMAPm, entry, BITMAPf,
   8524                            &PBMP_LB(unit));
   8525     SOC_IF_ERROR_RETURN
   8526         (soc_mem_write(unit, DEVICE_LOOPBACK_PORTS_BITMAPm, MEM_BLOCK_ALL, 0,
   8527                        entry));
   8528 
   8529     PBMP_LB_ITER(unit, port) {
   8530         mem = SOC_MEM_UNIQUE_ACC(unit, MULTIPASS_LOOPBACK_BITMAPm)
   8531             [si->port_pipe[port]];
   8532         sal_memset(entry, 0, sizeof(multipass_loopback_bitmap_entry_t));
   8533         SOC_PBMP_PORT_SET(pbmp, port);
   8534         soc_mem_pbmp_field_set(unit, mem, &entry, BITMAPf, &pbmp);
   8535         SOC_IF_ERROR_RETURN
   8536             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, entry));
   8537     }
   8538 
   8539     sal_memset(entry, 0, sizeof(egr_ing_port_entry_t));
   8540     soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 1);
   8541     PBMP_HG_ITER(unit, port) {
   8542         SOC_IF_ERROR_RETURN
   8543             (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry));
   8544     }
   8545     SOC_IF_ERROR_RETURN
   8546         (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, si->cpu_hg_index,
   8547                        entry));
   8548     soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 2);
   8549     PBMP_LB_ITER(unit, port) {
   8550         SOC_IF_ERROR_RETURN
   8551             (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry));
   8552     }
   8553 
   8554     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   8555         port = SOC_BLOCK_PORT(unit, block_info_idx);
   8556         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   8557         phy_port_base = PORT_BLOCK_BASE_PORT(port);
   8558 
   8559         /* Assert CLPORT soft reset */
   8560         rval = 0;
   8561         for (lane = 0; lane < _TD3_PORTS_PER_PBLK; lane++) {
   8562             if (si->port_p2l_mapping[phy_port_base + lane] != -1) {
   8563                 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, &rval,
   8564                                   port_fields[lane], 1);
   8565             }
   8566         }
   8567         SOC_IF_ERROR_RETURN(WRITE_CLPORT_SOFT_RESETr(unit, port, rval));
   8568 
   8569         /* Set port mode */
   8570         soc_trident3_port_ratio_get(unit, clport, &mode);
   8571         rval = 0;
   8572         soc_reg_field_set(unit, CLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf,
   8573                           mode_encodings[mode]);
   8574         soc_reg_field_set(unit, CLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf,
   8575                           mode_encodings[mode]);
   8576         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MODE_REGr(unit, port, rval));
   8577 
   8578         /* De-assert XLPORT soft reset */
   8579         SOC_IF_ERROR_RETURN(WRITE_CLPORT_SOFT_RESETr(unit, port, 0));
   8580 
   8581         /* Enable CLPORT */
   8582         rval = 0;
   8583         for (lane = 0; lane < _TD3_PORTS_PER_PBLK; lane++) {
   8584             if (si->port_p2l_mapping[phy_port_base + lane] != -1) {
   8585                 soc_reg_field_set(unit, CLPORT_ENABLE_REGr, &rval,
   8586                                   port_fields[lane], 1);
   8587             }
   8588         }
   8589         SOC_IF_ERROR_RETURN(WRITE_CLPORT_ENABLE_REGr(unit, port, rval));
   8590     }
   8591 
   8592     SOC_PBMP_COUNT(si->management_pbm, pbm_count);
   8593     /* In case of dual management port - program top misc control */
   8594     SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROLr(unit,&rval));
   8595     soc_reg_field_set(unit, TOP_MISC_CONTROLr, &rval, ENABLE_2ND_MGMT_PORTf,
   8596                   (pbm_count > 1)? 1 : 0);
   8597     WRITE_TOP_MISC_CONTROLr(unit, rval);
   8598 
   8599     SOC_IF_ERROR_RETURN(READ_SECOND_MGMT_PORTr(unit,&rval));
   8600     soc_reg_field_set(unit, SECOND_MGMT_PORTr, &rval, ENABLEf,
   8601                   (pbm_count > 1)? 1 : 0);
   8602     WRITE_SECOND_MGMT_PORTr(unit, rval);
   8603 
   8604     SOC_PBMP_ITER(si->management_pbm, port) {
   8605         /* Assert XLPORT soft reset */
   8606         rval = 0;
   8607         if (si->port_p2l_mapping[129] != -1) { /* management port 0 */
   8608             soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, PORT0f, 1);
   8609         }
   8610         if (si->port_p2l_mapping[128] != -1) { /* management port 1 */
   8611             soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, PORT2f, 1);
   8612         }
   8613         SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, rval));
   8614 
   8615         /* Set port mode to DUAL */
   8616         rval = 0;
   8617         soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf,
   8618                           3);
   8619         soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf,
   8620                           3);
   8621         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, port, rval));
   8622 
   8623         /* De-assert XLPORT soft reset */
   8624         SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, 0));
   8625 
   8626         /* Enable XLPORT */
   8627         rval = 0;
   8628         if (si->port_p2l_mapping[129] != -1) { /* management port 0 */
   8629             soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, PORT0f, 1);
   8630         }
   8631         if (si->port_p2l_mapping[128] != -1) { /* management port 0 */
   8632             soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, PORT2f, 1);
   8633         }
   8634         SOC_IF_ERROR_RETURN(WRITE_XLPORT_ENABLE_REGr(unit, port, rval));
   8635     }
   8636 
   8637     SOC_IF_ERROR_RETURN(READ_MMU_GCFG_MISCCONFIGr(unit, &rval));
   8638     soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, REFRESH_ENf, 1);
   8639     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   8640 
   8641     /* Enable dual hash tables */
   8642     SOC_IF_ERROR_RETURN(soc_trident3_hash_init(unit));
   8643 
   8644     /* Configure EP credit */
   8645     sal_memset(entry, 0, sizeof(egr_mmu_cell_credit_entry_t));
   8646     PBMP_ALL_ITER(unit, port) {
   8647         SOC_IF_ERROR_RETURN(
   8648             soc_td3_port_asf_speed_to_mmu_cell_credit(unit, port,
   8649                 si->port_speed_max[port], &fval));
   8650         SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ANY,
   8651                             si->port_l2p_mapping[port], &entry));
   8652         soc_EGR_MMU_CELL_CREDITm_field32_set(unit, &entry, CREDITf, fval);
   8653         SOC_IF_ERROR_RETURN(WRITE_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ALL,
   8654                             si->port_l2p_mapping[port], &entry));
   8655     }
   8656 
   8657     /* Configure egress transmit start count */
   8658     PBMP_ALL_ITER(unit, port) {
   8659         SOC_IF_ERROR_RETURN(
   8660             soc_td3_port_asf_xmit_start_count_set(unit, port,
   8661                 si->port_speed_max[port], _SOC_TD3_ASF_MODE_SAF, 0));
   8662     }
   8663 
   8664     /* Ingress Force SAF */
   8665     SOC_IF_ERROR_RETURN(_soc_trident3_ing_fsaf_init(unit));
   8666 
   8667     /* Egress Force SAF */
   8668     if (SOC_PBMP_NOT_NULL(si->oversub_pbm)) {
   8669         factor = 178125;
   8670         mem = EDB_1DBG_Bm;
   8671         sal_memset(entry, 0, sizeof(edb_1dbg_b_entry_t));
   8672 
   8673         PBMP_ALL_ITER(unit, port) {
   8674             fval = ((si->port_speed_max[port] / 10) * factor) / 100000;
   8675             soc_mem_field32_set(unit, mem, &entry, FIELD_Bf, fval);
   8676             SOC_IF_ERROR_RETURN
   8677                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   8678                                si->port_l2p_mapping[port], entry));
   8679         }
   8680 
   8681         for (index = 0; index < NUM_PIPE(unit); index++) {
   8682             if (SOC_PBMP_IS_NULL(si->pipe_pbm[index])) {
   8683                 continue;
   8684             }
   8685             reg = SOC_REG_UNIQUE_ACC(unit, EDB_1DBG_Ar)[index];
   8686             SOC_IF_ERROR_RETURN
   8687                 (soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval64));
   8688             correction_duration = 135 * si->frequency / 10;
   8689             detection_duration = 15 * si->frequency / 10;
   8690             soc_reg64_field32_set(unit, EDB_1DBG_Ar, &rval64, FIELD_Af, detection_duration);
   8691             soc_reg64_field32_set(unit, EDB_1DBG_Ar, &rval64, FIELD_Bf, correction_duration);
   8692             soc_reg64_field32_set(unit, EDB_1DBG_Ar, &rval64, FIELD_Cf, 25);
   8693             SOC_IF_ERROR_RETURN
   8694                 (soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval64));
   8695         }
   8696     }
   8697 
   8698     /* Enable egress */
   8699     sal_memset(entry, 0, sizeof(egr_enable_entry_t));
   8700     soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 1);
   8701     PBMP_ALL_ITER(unit, port) {
   8702         phy_port = si->port_l2p_mapping[port];
   8703         SOC_IF_ERROR_RETURN
   8704             (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry));
   8705     }
   8706 
   8707     sal_memset(entry, 0, sizeof(epc_link_bmap_entry_t));
   8708     soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf,
   8709                            &PBMP_CMIC(unit));
   8710     SOC_IF_ERROR_RETURN(WRITE_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL, 0, entry));
   8711 
   8712     /* enable all ports */
   8713     sal_memset(&ingr_entry, 0, sizeof(ingr_entry));
   8714     soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, &ingr_entry,
   8715                            PORT_BITMAPf, &PBMP_ALL(unit));
   8716     SOC_IF_ERROR_RETURN(
   8717         WRITE_ING_DEST_PORT_ENABLEm(unit, MEM_BLOCK_ALL, 0, &ingr_entry));
   8718 
   8719     sal_memset(&map_entry, 0, sizeof(map_entry));
   8720     soc_mem_field32_set(unit, MODPORT_MAP_SUBPORTm, &map_entry, ENABLEf, 1);
   8721 
   8722     /* my_modid and other modid related initialization */
   8723     PBMP_ALL_ITER(unit, port) {
   8724         /* configure logical port numbers */
   8725         soc_mem_field32_set(unit, MODPORT_MAP_SUBPORTm, &map_entry,
   8726                             DESTf, port);
   8727         SOC_IF_ERROR_RETURN(WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ALL,
   8728                                                         port, &map_entry));
   8729     }
   8730 
   8731     /* setting up my_modid */
   8732     SOC_IF_ERROR_RETURN(READ_MY_MODID_SET_2_64r(unit, &rval64));
   8733 
   8734     soc_reg64_field32_set(unit, MY_MODID_SET_2_64r, &rval64,
   8735                           MODID_0_VALIDf, 1);
   8736     soc_reg64_field32_set(unit, MY_MODID_SET_2_64r, &rval64,
   8737                           MODID_0f, SOC_BASE_MODID(unit));
   8738 
   8739     SOC_IF_ERROR_RETURN(WRITE_MY_MODID_SET_2_64r(unit, rval64));
   8740 
   8741     SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, &rval64));
   8742     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   8743                           L3SRC_HIT_ENABLEf, 1);
   8744     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   8745                           L2DST_HIT_ENABLEf, 1);
   8746     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   8747                           APPLY_EGR_MASK_ON_L2f, 1);
   8748     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   8749                           APPLY_EGR_MASK_ON_L3f, 1);
   8750     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   8751                           ARP_RARP_TO_FPf, 0x3); /* enable both ARP & RARP */
   8752     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   8753                           ARP_VALIDATION_ENf, 1);
   8754     if (soc_feature(unit, soc_feature_port_lag_failover)) {
   8755         soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   8756                               IGNORE_HG_HDR_LAG_FAILOVERf, 0);
   8757     } else {
   8758         soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   8759                               IGNORE_HG_HDR_LAG_FAILOVERf, 1);
   8760     }
   8761     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   8762                           APPLY_HG_MGID_ADJUSTf, 0xFF);
   8763 
   8764     SOC_IF_ERROR_RETURN(WRITE_ING_CONFIG_64r(unit, rval64));
   8765 
   8766 
   8767 
   8768     /* The HW defaults for EGR_VLAN_CONTROL_1.VT_MISS_UNTAG == 1, which
   8769      * causes the outer tag to be removed from packets that don't have
   8770      * a hit in the egress vlan tranlation table. Set to 0 to disable this.
   8771      */
   8772     /* Programming EGR_VLAN_CONTROL_1m table */
   8773 #if 0
   8774     /* Can't call bcm function in soc layer. */
   8775     if (soc_feature(unit, soc_feature_egr_all_profile)) {
   8776         PBMP_ALL_ITER(unit, port) {
   8777             soc_field_t flds = {VT_MISS_UNTAGf, REMARK_OUTER_DOT1Pf};
   8778             uint32 vals = {0, 1};
   8779             BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_fields_set(unit,
   8780                 port, EGR_VLAN_CONTROL_1m, flds, vals);
   8781         }
   8782     }
   8783 #endif
   8784 
   8785     SOC_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   8786     SOC_PBMP_REMOVE(pbmp, PBMP_LB(unit));
   8787     SOC_IF_ERROR_RETURN(soc_mem_read(unit, ING_EN_EFILTER_BITMAPm,
   8788                                      MEM_BLOCK_ANY, 0, &entry));
   8789     soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm, &entry, BITMAPf,
   8790                            &pbmp);
   8791     SOC_IF_ERROR_RETURN(soc_mem_write(unit, ING_EN_EFILTER_BITMAPm,
   8792                                       MEM_BLOCK_ANY, 0, &entry));
   8793 
   8794     /* Multicast range initialization */
   8795     SOC_IF_ERROR_RETURN
   8796         (soc_hbx_higig2_mcast_sizes_set(unit,
   8797              soc_property_get(unit, spn_HIGIG2_MULTICAST_VLAN_RANGE,
   8798                               SOC_HBX_MULTICAST_RANGE_DEFAULT),
   8799              soc_property_get(unit, spn_HIGIG2_MULTICAST_L2_RANGE,
   8800                               soc_mem_index_count(unit, L2MCm)),
   8801              soc_property_get(unit, spn_HIGIG2_MULTICAST_L3_RANGE,
   8802                               soc_mem_index_count(unit, L3_IPMCm))));
   8803 
   8804     soc->mcast_size = soc_property_get(unit, spn_MULTICAST_L2_RANGE,
   8805                                         soc_mem_index_count(unit, L2MCm));
   8806     soc->ipmc_size =  soc_property_get(unit, spn_MULTICAST_L3_RANGE,
   8807                                         soc_mem_index_count(unit, L3_IPMCm));
   8808 
   8809     SOC_IF_ERROR_RETURN(READ_MC_CONTROL_4r(unit, &mc_ctrl));
   8810 
   8811     soc_reg_field_set(unit, MC_CONTROL_4r, &mc_ctrl,
   8812                       ALLOW_IPMC_INDEX_WRAP_AROUNDf, 1);
   8813     SOC_IF_ERROR_RETURN
   8814         (WRITE_MC_CONTROL_4r(unit, mc_ctrl));
   8815 
   8816     /* spn_RATE_EXT_MDIO_DIVIDEND and spn_RATE_INT_MDIO_DIVIDEND are
   8817      * NOT applicable to TRIDENT3.
   8818      */
   8819 
   8820     /* MDIO Clock Frquency for TD3 is 250 MHz
   8821      * Set external MDIO freq to around 5 MHz
   8822      * Hence divisor is set to 50
   8823      */
   8824 
   8825     ext_divisor = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVISOR, 50);
   8826 
   8827     /*
   8828      * Set internal MDIO freq to around 10 MHz
   8829      * Valid range is from 2.5MHz to 20MHz
   8830      * Hence divisor is set to 25
   8831      */
   8832     int_divisor = soc_property_get(unit, spn_RATE_INT_MDIO_DIVISOR, 25);
   8833 
   8834     delay = soc_property_get(unit, spn_MDIO_OUTPUT_DELAY, -1);
   8835     if (delay < 0  || delay > 255) {
   8836         /* valid range for delay is 0-255
   8837          * if outside this range, skip configuring delay
   8838          */
   8839         delay = -1;
   8840     }
   8841 
   8842     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   8843               (BSL_META_U(unit,
   8844               "Config MIIM rings with int divisor %d, ext divisor %d, delay %d\n"),
   8845               int_divisor, ext_divisor, delay));
   8846 
   8847     soc_cmicx_miim_divider_set_all(unit, int_divisor, ext_divisor, delay);
   8848 
   8849     
   8850     _phy_tsce_firmware_set_helper[unit] = soc_trident3_tscx_firmware_set;
   8851     _phy_tscf_firmware_set_helper[unit] = soc_trident3_tscx_firmware_set;
   8852 
   8853     /* Check if Hierarchical ECMP mode is set */
   8854     if (soc_property_get(unit, spn_L3_ECMP_LEVELS, 1) == 2) {
   8855         uint32 ecmp_mode = 1;
   8856         rval = 0;
   8857         soc_reg_field_set(unit, ECMP_CONFIGr, &rval, ECMP_MODEf, ecmp_mode);
   8858         SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIGr(unit, rval));
   8859 
   8860     } else {
   8861         uint32 rval = 0;
   8862         uint32 ecmp_mode = 0;
   8863         soc_reg_field_set(unit, ECMP_CONFIGr, &rval, ECMP_MODEf, ecmp_mode);
   8864         SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIGr(unit, rval));
   8865 
   8866     }
   8867 
   8868     SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ENHANCED_HASHING_CONTROLr,
   8869                         REG_PORT_ANY, ECMP_FLOWSET_TABLE_CONFIGf, 1));
   8870 #if defined(BCM_RIOT_SUPPORT) || defined(BCM_MULTI_LEVEL_ECMP_SUPPORT)
   8871         ecmp_levels = soc_property_get(unit, spn_L3_ECMP_LEVELS, 1);
   8872         if ((soc_feature(unit, soc_feature_riot) ||
   8873             soc_feature(unit, soc_feature_multi_level_ecmp)) &&
   8874             ecmp_levels > 1 && soc_mem_index_count(unit,RH_ECMP_FLOWSETm)) {
   8875 
   8876             num_overlay_ecmp_rh_flowset_entries = soc_property_get(unit,
   8877                    spn_RIOT_OVERLAY_ECMP_RESILIENT_HASH_SIZE, 0);
   8878 
   8879             if (SOC_FIELD_RANGE_CHECK(
   8880                  num_overlay_ecmp_rh_flowset_entries, 0, 32768)) {
   8881                  num_overlay_ecmp_rh_flowset_entries = 32768;
   8882             }
   8883 
   8884             switch (num_overlay_ecmp_rh_flowset_entries) {
   8885             case 0:
   8886                 break;
   8887             case 32768:
   8888                 if (soc_mem_index_count(unit,RH_ECMP_FLOWSETm) >= 32768) {
   8889                     SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   8890                                  ENHANCED_HASHING_CONTROLr,
   8891                                  REG_PORT_ANY, ECMP_FLOWSET_TABLE_CONFIGf, 2));
   8892                 } else {
   8893                     LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit,
   8894                     "%s:Total ECMP entries %d are less than RH entries :%d \n"),
   8895                     FUNCTION_NAME(),  soc_mem_index_count(unit,RH_ECMP_FLOWSETm),
   8896                     num_overlay_ecmp_rh_flowset_entries));
   8897                     return SOC_E_CONFIG;
   8898                }
   8899                 break;
   8900             default:
   8901                 LOG_ERROR(BSL_LS_BCM_COMMON, (BSL_META_U(unit,
   8902                     "%s: Value for overlay RH entries is not correct : %d \n"),
   8903                     FUNCTION_NAME(),  num_overlay_ecmp_rh_flowset_entries));
   8904                return SOC_E_CONFIG;
   8905             }
   8906         }
   8907 #endif
   8908 
   8909    /* Setup SW2_FP_DST_ACTION_CONTROL */
   8910    fields[0] = HGTRUNK_RES_ENf;
   8911    values[0] = 1;
   8912    fields[1] = LAG_RES_ENf;
   8913    values[1] = 1;
   8914    SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit,
   8915                                         SW2_IFP_DST_ACTION_CONTROLr,
   8916                                         REG_PORT_ANY, 2, fields, values));
   8917 
   8918    /* Enhanced hashing  LAG/TRUNK config
   8919     * LAG/TRUNK share the same flow set table used in RH
   8920     * 64k is shared between LAG and HGT for
   8921     * - 32k each - default
   8922     * - 64K dedicated to HGT RH
   8923     * - 64K dedicated to LAG RH
   8924     */
   8925     num_lag_rh_flowset_entries = soc_property_get(unit,
   8926                 spn_TRUNK_RESILIENT_HASH_TABLE_SIZE, 32768);
   8927 
   8928     switch (num_lag_rh_flowset_entries) {
   8929         case 0:
   8930             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ENHANCED_HASHING_CONTROL_2r,
   8931                         REG_PORT_ANY, HGT_LAG_FLOWSET_TABLE_CONFIGf, 1));
   8932             break;
   8933         case 65536:
   8934             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ENHANCED_HASHING_CONTROL_2r,
   8935                         REG_PORT_ANY, HGT_LAG_FLOWSET_TABLE_CONFIGf, 0));
   8936             break;
   8937         case 32768:
   8938             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ENHANCED_HASHING_CONTROL_2r,
   8939                         REG_PORT_ANY, HGT_LAG_FLOWSET_TABLE_CONFIGf, 2));
   8940             break;
   8941         default:
   8942             return SOC_E_CONFIG;
   8943     }
   8944     SOC_IF_ERROR_RETURN
   8945         (soc_counter_tomahawk_status_enable(unit, TRUE));
   8946 
   8947     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   8948                 (BSL_META_U(unit,
   8949                             "MISC Init completed (u=%d)\n"), unit));
   8950 
   8951     /* Mem Scan thread start should be the last step in Misc init */
   8952     if (parity_enable) {
   8953         SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_start(unit));
   8954         SOC_IF_ERROR_RETURN(soc_generic_sram_mem_scan_start(unit));
   8955     }
   8956 
   8957     return SOC_E_NONE;
   8958 #else
   8959     return SOC_E_UNAVAIL;
   8960 #endif
   8961 }
   8962 
   8963 
   8964 /*
   8965  * Function used for index calculation of certain memories,
   8966  * where index is derived from more than one key.
   8967  * Eg. (Port, SP) or (Port, PG)
   8968  * Defined as Macro: SOC_TD3_MMU_PIPED_MEM_INDEX
   8969  * Note: If no special indexig required, return the same index.
   8970  */
   8971 uint32 _soc_td3_piped_mem_index(int unit, soc_port_t port,
   8972                                soc_mem_t mem, int arr_off)
   8973 {
   8974     int     mmu_port, index;
   8975 
   8976     mmu_port = SOC_TD3_MMU_PORT(unit, port);
   8977 
   8978     switch (mem) {
   8979         case MMU_THDM_DB_PORTSP_CONFIGm:
   8980         case MMU_THDM_MCQE_PORTSP_CONFIGm:
   8981 #ifdef BCM_MAVERICK2_SUPPORT
   8982             if (SOC_IS_MAVERICK2(unit)) {
   8983                 index = ((mmu_port & SOC_TD3_MMU_PORT_STRIDE) * _TD3_MMU_NUM_POOL)
   8984                     + arr_off;
   8985             } else
   8986 #endif
   8987             {
   8988                 index = (_TD3_PORTS_PER_PIPE * arr_off) + (mmu_port &
   8989                         SOC_TD3_MMU_PORT_STRIDE);
   8990             }
   8991             break;
   8992         case THDI_PORT_SP_CONFIGm:
   8993         case MMU_THDU_CONFIG_PORTm:
   8994         case MMU_THDU_RESUME_PORTm:
   8995         case MMU_THDU_COUNTER_PORTm:
   8996             index = ((mmu_port & SOC_TD3_MMU_PORT_STRIDE) * _TD3_MMU_NUM_POOL)
   8997                      + arr_off;
   8998             break;
   8999         case THDI_PORT_PG_CONFIGm:
   9000             index = ((mmu_port & SOC_TD3_MMU_PORT_STRIDE) * _TD3_MMU_NUM_PG)
   9001                      + arr_off;
   9002             break;
   9003         default:
   9004             return arr_off;
   9005     }
   9006 
   9007     return index;
   9008 }
   9009 
   9010 /*
   9011  * Function:
   9012  *      soc_td3_mmu_bmp_reg_pos_get
   9013  * Purpose:
   9014  *      Helper function for register resolve.
   9015  *      Can be used for registers that include only bitmap field.
   9016  *      Each bit in the bitmap is MMU port.
   9017  *      2 splited registers are used to accomodate 66 ports for each pipe.
   9018  * Parameters:
   9019  *      unit    - (IN) Unit number.
   9020  *      port    - (IN) Logical SOC port number.
   9021  *      pipe    - (OUT) Pipe number.
   9022  *      split   - (OUT) Reg split number.
   9023  *      pos     - (OUT) Position in bitmap.
   9024  * Returns:
   9025  *      SOC_E_XXX
   9026  */
   9027 int
   9028 soc_td3_mmu_bmp_reg_pos_get(int unit, soc_port_t port,
   9029                             int *pipe, int *split, int *pos)
   9030 {
   9031     int pipe_tmp, mmu_port, phy_port;
   9032     int split_tmp, pos_tmp;
   9033     soc_info_t *si;
   9034 
   9035     si = &SOC_INFO(unit);
   9036     pipe_tmp = si->port_pipe[port];
   9037     phy_port = si->port_l2p_mapping[port];
   9038     mmu_port = si->port_p2m_mapping[phy_port];
   9039     /* Reg config is per pipe, get local MMU port. */
   9040     mmu_port = mmu_port & SOC_TD3_MMU_PORT_STRIDE;
   9041 
   9042     if (mmu_port < 64) {
   9043         split_tmp = 0;
   9044         pos_tmp = mmu_port;
   9045     } else {
   9046         split_tmp = 1;
   9047         pos_tmp = mmu_port - 64;
   9048     }
   9049 
   9050     if (pipe != NULL) {
   9051         *pipe = pipe_tmp;
   9052     }
   9053     if (split != NULL) {
   9054         *split = split_tmp;
   9055     }
   9056     if (pos != NULL) {
   9057         *pos = pos_tmp;
   9058     }
   9059 
   9060     return SOC_E_NONE;
   9061 }
   9062 
   9063 STATIC int
   9064 _soc_td3_thdo_hw_get(int unit, soc_port_t port, int *enable)
   9065 {
   9066     uint64 rval64;
   9067     int pipe, i;
   9068     int split, pos;
   9069     soc_reg_t reg[3][2] = {
   9070         {
   9071             THDU_OUTPUT_PORT_RX_ENABLE_SPLIT0r,
   9072             THDU_OUTPUT_PORT_RX_ENABLE_SPLIT1r
   9073         },
   9074         {
   9075             MMU_THDM_DB_PORT_RX_ENABLE_64_SPLIT0r,
   9076             MMU_THDM_DB_PORT_RX_ENABLE_64_SPLIT1r
   9077         },
   9078         {
   9079             MMU_THDM_MCQE_PORT_RX_ENABLE_64_SPLIT0r,
   9080             MMU_THDM_MCQE_PORT_RX_ENABLE_64_SPLIT1r
   9081         }
   9082     };
   9083 
   9084     SOC_IF_ERROR_RETURN(
   9085         soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos));
   9086 
   9087     COMPILER_64_ZERO(rval64);
   9088     *enable = TRUE;
   9089     for (i = 0; i < 3; i++) {
   9090         SOC_IF_ERROR_RETURN
   9091             (soc_trident3_xpe_reg_get(unit, reg[i][split],
   9092                                       -1, pipe, 0, &rval64));
   9093 
   9094         if (!COMPILER_64_BITTEST(rval64, pos)) {
   9095             *enable = FALSE;
   9096             break;
   9097         }
   9098     }
   9099 #ifdef INCLUDE_AVS
   9100     /* Register trident3 related functions */
   9101     SOC_IF_ERROR_RETURN(soc_td3_avs_init(unit));
   9102 #endif /* INCLUDE_AVS  */
   9103     return SOC_E_NONE;
   9104 }
   9105 
   9106 STATIC int
   9107 _soc_td3_thdo_hw_set(int unit, soc_port_t port, int enable)
   9108 {
   9109     uint64 rval64, rval64_tmp;
   9110     int pipe, i;
   9111     int split, pos;
   9112     soc_reg_t reg[3][2] = {
   9113         {
   9114             THDU_OUTPUT_PORT_RX_ENABLE_SPLIT0r,
   9115             THDU_OUTPUT_PORT_RX_ENABLE_SPLIT1r
   9116         },
   9117         {
   9118             MMU_THDM_DB_PORT_RX_ENABLE_64_SPLIT0r,
   9119             MMU_THDM_DB_PORT_RX_ENABLE_64_SPLIT1r
   9120         },
   9121         {
   9122             MMU_THDM_MCQE_PORT_RX_ENABLE_64_SPLIT0r,
   9123             MMU_THDM_MCQE_PORT_RX_ENABLE_64_SPLIT1r
   9124         }
   9125     };
   9126 
   9127     SOC_IF_ERROR_RETURN(
   9128         soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos));
   9129 
   9130     for (i = 0; i < 3; i++) {
   9131         COMPILER_64_ZERO(rval64);
   9132         COMPILER_64_ZERO(rval64_tmp);
   9133 
   9134         if (pos < 32) {
   9135             COMPILER_64_SET(rval64_tmp, 0, (1 << pos));
   9136         } else {
   9137             COMPILER_64_SET(rval64_tmp, (1 << (pos - 32)), 0);
   9138         }
   9139 
   9140         SOC_IF_ERROR_RETURN
   9141             (soc_trident3_xpe_reg_get(unit, reg[i][split],
   9142                                       -1, pipe, 0, &rval64));
   9143 
   9144         if (enable) {
   9145             COMPILER_64_OR(rval64, rval64_tmp);
   9146         } else {
   9147             COMPILER_64_NOT(rval64_tmp);
   9148             COMPILER_64_AND(rval64, rval64_tmp);
   9149         }
   9150 
   9151         SOC_IF_ERROR_RETURN
   9152             (soc_trident3_xpe_reg_set(unit, reg[i][split],
   9153                                       -1, pipe, 0, rval64));
   9154     }
   9155 
   9156     return SOC_E_NONE;
   9157 }
   9158 
   9159 /*
   9160  * Funtion to caltulate global buffer reserve for ASF.
   9161  */
   9162 STATIC int
   9163 _soc_td3_mmu_config_buf_asf(int unit, int lossless, int *cnt)
   9164 {
   9165     soc_info_t *si;
   9166     int pm, oversub, num_ports, ports[3], asf = 0;
   9167     static int asf_profile[SOC_MAX_NUM_DEVICES] = {-2};
   9168     int asf_reserved_cells[3][3][2] =     /* 1/2/4 port, asf profile, line/oversub*/
   9169         {
   9170             {{ 0,  0}, {16,  31}, { 39, 50}},     /* 1-port PM */
   9171             {{ 0,  0}, {32,  62}, { 78, 100}},     /* 2-ports PM */
   9172             {{ 0,  0}, {64, 124}, {156, 200}},    /* 3/4-ports PM */
   9173         };
   9174 
   9175     /* To init static array to -1 */
   9176     if (asf_profile[0] == -2) {
   9177         sal_memset(asf_profile, -1, sizeof(asf_profile));
   9178     }
   9179 
   9180     if (asf_profile[unit] == -1) {
   9181         asf_profile[unit] = soc_property_get(unit, spn_ASF_MEM_PROFILE,
   9182             _SOC_TD3_ASF_MEM_PROFILE_SIMILAR);
   9183         if ((asf_profile[unit] > _SOC_TD3_ASF_MEM_PROFILE_EXTREME)
   9184             || (asf_profile[unit] < _SOC_TD3_ASF_MEM_PROFILE_NONE)) {
   9185             asf_profile[unit] = _SOC_TD3_ASF_MEM_PROFILE_NONE;
   9186         }
   9187     }
   9188 
   9189     si = &SOC_INFO(unit);
   9190     oversub = SOC_PBMP_IS_NULL(si->oversub_pbm)? 0 : 1;
   9191 
   9192     ports[0] = ports[1] = ports[2] = 0;
   9193     for (pm = 0; pm < _TD3_PBLKS_PER_DEV(unit); pm++) {
   9194         num_ports = soc_td3_ports_per_pm_get(unit, pm);
   9195         if (num_ports == 1) {
   9196             ports[0]++;
   9197         } else if (num_ports == 2) {
   9198             ports[1]++;
   9199         } else if ((num_ports == 4) || (num_ports == 3)) {
   9200             ports[2]++;
   9201         }
   9202     }
   9203 
   9204     asf = asf_reserved_cells[0][asf_profile[unit]][oversub] * ports[0]
   9205         + asf_reserved_cells[1][asf_profile[unit]][oversub] * ports[1]
   9206         + asf_reserved_cells[2][asf_profile[unit]][oversub] * ports[2];
   9207 
   9208     if (cnt != NULL) {
   9209         *cnt = asf;
   9210     }
   9211 
   9212     return SOC_E_NONE;
   9213 }
   9214 
   9215 /*
   9216  * Function used for global resource reservation (MCQE / RQE / Buf cell).
   9217  * Input state: Total hardware resource.
   9218  * Output state: Resource available for admission control.
   9219  */
   9220 STATIC void
   9221 _soc_td3_mmu_config_dev_reserve(int unit, _soc_mmu_device_info_t *devcfg,
   9222                                 int lossless)
   9223 {
   9224     int port, pm, asf_rsvd = 0;
   9225     uint32 total_mcq = 0, num_ports = 0;
   9226     uint32 cpu_cnt = 1, lb_cnt = 2, mgmt_cnt = 1;
   9227     soc_info_t *si = &SOC_INFO(unit);
   9228 
   9229     /* Device reservation for RQE Entry */
   9230     devcfg->total_rqe_queue_entry -= _TD3_MMU_RQE_ENTRY_RSVD_PER_XPE;
   9231 
   9232     /* Device reservation for MCQ Entry - 6 entries for each MC queue */
   9233     if (si->flex_eligible) {
   9234         for (pm = 0; pm < _TD3_PBLKS_PER_DEV(unit); pm++) {
   9235             num_ports += soc_td3_ports_per_pm_get(unit, pm);
   9236         }
   9237         total_mcq += (num_ports * SOC_TD3_NUM_MCAST_QUEUE_PER_PORT);
   9238     } else {
   9239         PBMP_ALL_ITER(unit, port) {
   9240             if (IS_CPU_PORT(unit, port) ||
   9241                 IS_LB_PORT(unit,port) ||
   9242                 IS_MGMT_PORT(unit,port)) {
   9243                 continue;
   9244             }
   9245             total_mcq += si->port_num_cosq[port];
   9246         }
   9247     }
   9248     total_mcq += ((cpu_cnt * SOC_TD3_NUM_CPU_QUEUES) +
   9249                   (lb_cnt + mgmt_cnt) * SOC_TD3_NUM_MCAST_QUEUE_PER_PORT);
   9250 
   9251     devcfg->total_mcq_entry -= ((total_mcq * _TD3_MCQE_RSVD_PER_MCQ) +
   9252                                 _TD3_TDM_MCQE_RSVD_OVERSHOOT);
   9253 
   9254     /* Device reservation for buffer cell */
   9255     (void)_soc_td3_mmu_config_buf_asf(unit, lossless, &asf_rsvd);
   9256     devcfg->mmu_total_cell -= asf_rsvd;
   9257 }
   9258 
   9259 STATIC void
   9260 _soc_td3_mmu_init_dev_config(int unit, _soc_mmu_device_info_t *devcfg,
   9261                              int lossless)
   9262 {
   9263     if (devcfg == NULL) {
   9264         LOG_FATAL(BSL_LS_SOC_COMMON,
   9265                  (BSL_META_U(unit,
   9266                             "MMU config data error\
   9267                             (u=%d)\n"), unit));
   9268         return;
   9269     }
   9270     sal_memset(devcfg, 0, sizeof(_soc_mmu_device_info_t));
   9271 
   9272     devcfg->max_pkt_byte = _TD3_MMU_MAX_PACKET_BYTES;
   9273     devcfg->mmu_hdr_byte = _TD3_MMU_PACKET_HEADER_BYTES;
   9274     devcfg->jumbo_pkt_size = _TD3_MMU_JUMBO_FRAME_BYTES;
   9275     devcfg->default_mtu_size = _TD3_MMU_DEFAULT_MTU_BYTES;
   9276     devcfg->mmu_cell_size = _TD3_MMU_BYTES_PER_CELL;
   9277     devcfg->mmu_total_cell = _TD3_MMU_TOTAL_CELLS_PER_XPE;
   9278     devcfg->num_pg = _TD3_MMU_NUM_PG;
   9279     devcfg->num_service_pool = _TD3_MMU_NUM_POOL;
   9280     devcfg->flags = SOC_MMU_CFG_F_PORT_MIN | SOC_MMU_CFG_F_PORT_POOL_MIN |
   9281                     SOC_MMU_CFG_F_RQE | SOC_MMU_CFG_F_EGR_MCQ_ENTRY;
   9282     devcfg->total_mcq_entry = _TD3_MMU_TOTAL_MCQ_ENTRY(unit);
   9283     devcfg->rqe_queue_num = 11;
   9284     devcfg->total_rqe_queue_entry = _TD3_MMU_TOTAL_RQE_ENTRY(unit);
   9285 
   9286     _soc_td3_mmu_config_dev_reserve(unit, devcfg, lossless);
   9287 }
   9288 
   9289 STATIC void
   9290 _soc_td3_mmu_sw_info_config (int unit, _soc_td3_mmu_sw_config_info_t * swcfg,
   9291                              int lossless)
   9292 {
   9293     /* Default settings is lossless */
   9294     swcfg->mmu_egr_queue_min = 0;
   9295     swcfg->mmu_egr_qgrp_min = 0;
   9296     swcfg->mmu_total_pri_groups = 8;
   9297     swcfg->mmu_active_pri_groups = 1;
   9298     swcfg->mmu_pg_min = 8;
   9299     swcfg->mmu_port_min = 0;
   9300     swcfg->mmu_mc_egr_qentry_min = 0;
   9301     swcfg->mmu_rqe_qentry_min = 8;
   9302     swcfg->mmu_rqe_queue_min = 8;
   9303     if (lossless == 0)
   9304     {
   9305         swcfg->mmu_egr_queue_min = 8;
   9306         swcfg->mmu_egr_qgrp_min = 16;
   9307         swcfg->mmu_pg_min = 0;
   9308     }
   9309 }
   9310 
   9311 STATIC int
   9312 _soc_td3_default_pg_headroom(int unit, soc_port_t port,
   9313                             int lossless)
   9314 {
   9315     int speed = 1000, hdrm = 0;
   9316     uint8 port_oversub = 0;
   9317 
   9318     if (IS_CPU_PORT(unit, port)) {
   9319         return 77;
   9320     } else if (!lossless) {
   9321         return 0;
   9322     } else if (IS_LB_PORT(unit, port)) {
   9323         return 150;
   9324     }
   9325 
   9326     speed = SOC_INFO(unit).port_speed_max[port];
   9327 
   9328     if (SOC_PBMP_MEMBER(SOC_INFO(unit).oversub_pbm, port)) {
   9329         port_oversub = 1;
   9330     }
   9331     if ((speed >= 1000) && (speed <= 10000)) {
   9332         hdrm = port_oversub ? 194 : 160;
   9333     } else if ((speed > 10000) && (speed <= 20000)) {
   9334         hdrm = port_oversub ? 231 : 197;
   9335     } else if ((speed > 20000) && (speed <= 25000)) {
   9336         hdrm = port_oversub ? 288 : 254;
   9337     } else if ((speed > 25000) && (speed <= 42000)) {
   9338         hdrm = port_oversub ? 355 : 274;
   9339     } else if ((speed > 42000) && (speed <= 50000)) {
   9340         hdrm = port_oversub ? 432 : 351;
   9341     } else if (speed >= 100000) {
   9342         hdrm = port_oversub ? 768 : 574;
   9343     } else {
   9344         hdrm = port_oversub ? 194 : 160;
   9345     }
   9346     return hdrm;
   9347 }
   9348 
   9349 /*
   9350  * Default phase_1 MMU settings about headroom, guarantee, dynamic, color, ...
   9351  * which depend on single port/queue/qgroup/pg...
   9352  * Input state: Available for admission in devcfg, configured swcfg.
   9353  * Output state: Independent data filled in buf.
   9354  * Version 1.1
   9355  */
   9356 STATIC void
   9357 _soc_td3_mmu_config_buf_phase1(int unit, _soc_mmu_cfg_buf_t *buf,
   9358                                _soc_mmu_device_info_t *devcfg,
   9359                                _soc_td3_mmu_sw_config_info_t *swcfg,
   9360                                int lossless)
   9361 {
   9362     soc_info_t *si;
   9363     _soc_mmu_cfg_buf_pool_t *buf_pool;
   9364     _soc_mmu_cfg_buf_port_t *buf_port;
   9365     _soc_mmu_cfg_buf_port_pool_t *buf_port_pool;
   9366     _soc_mmu_cfg_buf_prigroup_t *buf_prigroup;
   9367     _soc_mmu_cfg_buf_queue_t *buf_queue;
   9368     _soc_mmu_cfg_buf_qgroup_t *queue_grp;
   9369     _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue;
   9370     int max_packet_cells, default_mtu_cells;
   9371     int port, idx;
   9372     int total_pool_size = 0, asf_rsvd = 0;
   9373     int rqe_entry_shared_total, qmin;
   9374 
   9375     si = &SOC_INFO(unit);
   9376 
   9377     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   9378                 (BSL_META_U(unit,
   9379                             "Initializing default MMU config phase 1(u=%d)\n"), unit));
   9380     max_packet_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->max_pkt_byte +
   9381                                                    devcfg->mmu_hdr_byte,
   9382                                                    devcfg->mmu_cell_size);
   9383     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size +
   9384                                                    devcfg->mmu_hdr_byte,
   9385                                                    devcfg->mmu_cell_size);
   9386 
   9387     (void)_soc_td3_mmu_config_buf_asf(unit, lossless, &asf_rsvd);
   9388     total_pool_size = devcfg->mmu_total_cell + asf_rsvd; /* Add back ASF reserved. */
   9389 
   9390     buf->headroom = 2 * max_packet_cells;   /* 1 packet per pipe. */
   9391 
   9392     rqe_entry_shared_total = devcfg->total_rqe_queue_entry -
   9393         (_TD3_MMU_NUM_RQE_QUEUES * swcfg->mmu_rqe_qentry_min);
   9394 
   9395     for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
   9396         buf_pool = &buf->pools[idx];
   9397         if (idx == 0) {  /* 100% scale up by 100 */
   9398             buf_pool->size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   9399             buf_pool->yellow_size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   9400             buf_pool->red_size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   9401             buf_pool->total_mcq_entry = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   9402             buf_pool->total_rqe_entry = rqe_entry_shared_total;
   9403         } else {
   9404             buf_pool->size = 0;
   9405             buf_pool->yellow_size = 0;
   9406             buf_pool->red_size = 0;
   9407             buf_pool->total_mcq_entry = 0;
   9408             buf_pool->total_rqe_entry = 0;
   9409         }
   9410     }
   9411 
   9412     for (idx = 0; idx < SOC_TD3_MMU_CFG_QGROUP_MAX; idx++) {
   9413         queue_grp = &buf->qgroups[idx];
   9414         /* resume limits - accounted for 8 cell granularity */
   9415         queue_grp->pool_resume = 16;
   9416         queue_grp->yellow_resume = 16;
   9417         queue_grp->red_resume = 16;
   9418         queue_grp->guarantee = swcfg->mmu_egr_qgrp_min;
   9419         if (lossless) {
   9420             queue_grp->discard_enable = 0;
   9421         } else {
   9422             queue_grp->discard_enable = 1;
   9423         }
   9424     }
   9425 
   9426     PBMP_ALL_ITER(unit, port) {
   9427         if (port >= SOC_MMU_CFG_PORT_MAX) {
   9428             break;
   9429         }
   9430         buf_port = &buf->ports[port];
   9431 
   9432         /* internal priority to priority group mapping */
   9433         for (idx = 0; idx < _TD3_MMU_NUM_INT_PRI; idx++) {
   9434             buf_port->pri_to_prigroup[idx] = 7;
   9435         }
   9436 
   9437         /* priority group to pool mapping */
   9438         for (idx = 0; idx < _TD3_MMU_NUM_PG; idx++) {
   9439             buf_port->prigroups[idx].pool_idx = 0;
   9440         }
   9441 
   9442         for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
   9443             buf_port_pool = &buf_port->pools[idx];
   9444             buf_port_pool->guarantee = 0;
   9445             buf_port_pool->pool_limit = 0;
   9446             buf_port_pool->pool_resume = 0;
   9447             if (idx == 0) {
   9448                 buf_port_pool->pool_limit = total_pool_size;
   9449                 buf_port_pool->pool_resume = total_pool_size -
   9450                                              (default_mtu_cells * 2);
   9451             }
   9452         }
   9453 
   9454         buf_port->pkt_size = max_packet_cells;
   9455 
   9456         /* priority group */
   9457         for (idx = 0; idx < _TD3_MMU_NUM_PG; idx++) {
   9458             buf_prigroup = &buf_port->prigroups[idx];
   9459             buf_prigroup->guarantee = 0;
   9460             buf_prigroup->user_delay = -1;
   9461             buf_prigroup->switch_delay = -1;
   9462             buf_prigroup->pkt_size = max_packet_cells;
   9463             buf_prigroup->device_headroom_enable = 0;
   9464             buf_prigroup->pool_floor = 0;
   9465             buf_prigroup->headroom = 0;
   9466             buf_prigroup->pool_resume = 0;
   9467             buf_prigroup->flow_control_enable = 0;
   9468             if (idx == 7) {
   9469                 buf_prigroup->device_headroom_enable = 1;
   9470                 buf_prigroup->flow_control_enable = lossless;
   9471                 buf_prigroup->headroom =
   9472                     _soc_td3_default_pg_headroom(unit, port, lossless);
   9473                 if (lossless) {
   9474                     buf_prigroup->guarantee = swcfg->mmu_pg_min;
   9475                 }
   9476             }
   9477         }
   9478 
   9479         /* multicast queue */
   9480         if (IS_CPU_PORT(unit, port) ||
   9481             IS_LB_PORT(unit,port)) {
   9482             qmin = swcfg->mmu_egr_queue_min;
   9483         } else {
   9484             qmin = 0;
   9485         }
   9486         for (idx = 0; idx < si->port_num_cosq[port]; idx++) {
   9487             buf_queue = &buf_port->queues[idx];
   9488             buf_queue->qgroup_id = -1;
   9489             buf_queue->guarantee = qmin;
   9490             buf_queue->mcq_entry_guarantee = swcfg->mmu_mc_egr_qentry_min;
   9491             buf_queue->color_discard_enable = 0;
   9492             if (lossless) {
   9493                 buf_queue->discard_enable = 0;
   9494                 /* resume limits - accounted for 8 cell granularity */
   9495                 buf_queue->pool_resume = 16;
   9496             } else {
   9497                 buf_queue->discard_enable = 1;
   9498                 /* resume limits - accounted for 8 cell granularity */
   9499                 buf_queue->pool_resume = 16;
   9500             }
   9501         }
   9502 
   9503         /* unicast queue */
   9504         for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) {
   9505             buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx];
   9506             buf_queue->qgroup_id = -1;
   9507             buf_queue->guarantee = 0;
   9508             buf_queue->color_discard_enable = 0;
   9509             if (lossless) {
   9510                 buf_queue->discard_enable = 0;
   9511                 /* resume limits - accounted for 8 cell granularity */
   9512                 buf_queue->pool_resume = 16;
   9513                 buf_queue->yellow_resume = 16;
   9514                 buf_queue->red_resume = 16;
   9515             } else {
   9516                 buf_queue->discard_enable = 1;
   9517                 /* resume limits - accounted for 8 cell granularity */
   9518                 buf_queue->pool_resume = 16;
   9519                 buf_queue->yellow_resume = 16;
   9520                 buf_queue->red_resume = 16;
   9521                 buf_queue->qgroup_id = 0;
   9522                 buf_queue->qgroup_min_enable = 1;
   9523             }
   9524         }
   9525 
   9526         /* queue to pool mapping */
   9527         for (idx = 0;
   9528              idx < si->port_num_cosq[port] + si->port_num_uc_cosq[port]; idx++) {
   9529             buf_port->queues[idx].pool_idx = 0;
   9530         }
   9531     }
   9532 
   9533     /* RQE */
   9534     for (idx = 0; idx < _TD3_MMU_NUM_RQE_QUEUES; idx++) {
   9535         buf_rqe_queue = &buf->rqe_queues[idx];
   9536         buf_rqe_queue->pool_idx = 0;
   9537         buf_rqe_queue->guarantee = swcfg->mmu_rqe_queue_min;
   9538         if (lossless) {
   9539             buf_rqe_queue->discard_enable = 0;
   9540         } else {
   9541             buf_rqe_queue->discard_enable = 1;
   9542         }
   9543     }
   9544 }
   9545 
   9546 /*
   9547  * Default phase_2 MMU settings about shared buffer limit, which depends on
   9548  * guaranteed/headroom buffers on all port/queue/qgroup/pg/...
   9549  * Input state: _soc_mmu_cfg_buf_calculate processed buf.
   9550  * Output state: All necessary data filled in buf.
   9551  * Version 1.1
   9552  */
   9553 STATIC void
   9554 _soc_td3_mmu_config_buf_phase2(int unit, _soc_mmu_cfg_buf_t *buf,
   9555                                _soc_mmu_device_info_t *devcfg,
   9556                                _soc_td3_mmu_sw_config_info_t *swcfg,
   9557                                int lossless)
   9558 {
   9559     soc_info_t *si;
   9560     _soc_mmu_cfg_buf_pool_t *buf_pool;
   9561     _soc_mmu_cfg_buf_port_t *buf_port;
   9562     _soc_mmu_cfg_buf_prigroup_t *buf_prigroup;
   9563     _soc_mmu_cfg_buf_queue_t *buf_queue;
   9564     _soc_mmu_cfg_buf_qgroup_t *queue_grp;
   9565     _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue;
   9566     int port, idx, pm, ports[3] = {0};
   9567     int pg_hdrm_ob[] = {699, 379, 224}; /* PG headroom of 1/2/4-port PortMacro */
   9568     int total_pool_size = 0;
   9569     int ing_rsvd_total = 0, egr_rsvd_total = 0;
   9570     int ing_shared_total, egr_shared_total;
   9571     int total_rsvd_qmin = 0;
   9572     uint32 color_limit = 0;
   9573     uint32 num_ports = 0, mgmt_cnt = 0, cpu_cnt = 0, lb_cnt = 0;
   9574     uint32 cpu_hdrm = 0, lb_hdrm = 0, mgmt_hdrm = 0;
   9575 
   9576     si = &SOC_INFO(unit);
   9577 
   9578     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   9579                 (BSL_META_U(unit,
   9580                             "Initializing default MMU config phase 2(u=%d)\n"), unit));
   9581 
   9582     buf_pool = &buf->pools[0];
   9583     total_pool_size = devcfg->mmu_total_cell; /* per XPE limit */
   9584     total_rsvd_qmin = swcfg->mmu_egr_queue_min * (SOC_TD3_NUM_CPU_QUEUES +
   9585                         (SOC_TD3_NUM_MCAST_QUEUE_PER_PORT * 2));
   9586 
   9587     PBMP_ALL_ITER(unit, port) {
   9588         if (IS_CPU_PORT(unit, port)) {
   9589             cpu_cnt++;
   9590             cpu_hdrm = _soc_td3_default_pg_headroom(unit, port, lossless);
   9591         } else if (IS_LB_PORT(unit,port)) {
   9592             lb_cnt++;
   9593             lb_hdrm = _soc_td3_default_pg_headroom(unit, port, lossless);
   9594         } else if (IS_MGMT_PORT(unit,port)) {
   9595             mgmt_cnt++;
   9596             mgmt_hdrm = _soc_td3_default_pg_headroom(unit, port, lossless);
   9597         } else {
   9598             num_ports++;
   9599         }
   9600     }
   9601     if (si->flex_eligible) {
   9602         num_ports = 0;
   9603         for (pm = 0; pm < _TD3_PBLKS_PER_DEV(unit); pm++) {
   9604             port = soc_td3_ports_per_pm_get(unit, pm);
   9605             if (port == 1) {
   9606                 ports[0]++;
   9607             } else if (port == 2) {
   9608                 ports[1]++;
   9609             } else if ((port == 4) || (port == 3)) {
   9610                 ports[2]++;
   9611                 port = 4;
   9612             }
   9613             num_ports += port;
   9614         }
   9615 
   9616         if (lossless) {
   9617             ing_rsvd_total += (buf->headroom +
   9618                 swcfg->mmu_active_pri_groups*(
   9619                 ports[0]*pg_hdrm_ob[0] + 2*ports[1]*pg_hdrm_ob[1] +
   9620                 4*ports[2]*pg_hdrm_ob[2] + cpu_cnt*cpu_hdrm + lb_cnt*lb_hdrm) +
   9621                 swcfg->mmu_pg_min*swcfg->mmu_active_pri_groups*(
   9622                 num_ports + cpu_cnt + lb_cnt + mgmt_cnt) +
   9623                 swcfg->mmu_port_min*swcfg->mmu_active_pri_groups*(
   9624                 num_ports + cpu_cnt + lb_cnt + mgmt_cnt));
   9625             /* Management port is not included during Total PG
   9626              * headroom calculation */
   9627             buf_pool->prigroup_headroom -= mgmt_hdrm;
   9628         } else {
   9629             ing_rsvd_total += buf->headroom + cpu_hdrm;
   9630         }
   9631     } else {
   9632         if (lossless) {
   9633             /* Management port is not included during Total PG
   9634              * headroom calculation */
   9635             buf_pool->prigroup_headroom -= mgmt_hdrm;
   9636         }
   9637         ing_rsvd_total += (buf->headroom + buf_pool->prigroup_headroom +
   9638                            buf_pool->prigroup_guarantee);
   9639     }
   9640 
   9641     egr_rsvd_total += total_rsvd_qmin +
   9642                        ((num_ports + mgmt_cnt) * swcfg->mmu_egr_qgrp_min) +
   9643                        (swcfg->mmu_rqe_queue_min * _TD3_MMU_NUM_RQE_QUEUES);
   9644 
   9645     if (lossless) {
   9646         ing_rsvd_total += egr_rsvd_total;
   9647     }
   9648 
   9649     ing_shared_total = total_pool_size - ing_rsvd_total;
   9650     egr_shared_total = total_pool_size - egr_rsvd_total;
   9651 
   9652     swcfg->ing_shared_total = ing_shared_total;
   9653     swcfg->egr_shared_total = egr_shared_total;
   9654 
   9655     LOG_VERBOSE(BSL_LS_SOC_MMU,
   9656                 (BSL_META_U(unit,
   9657                             "MMU config: Total Shared size: ingress %d egress %d\n"),
   9658                             ing_shared_total, egr_shared_total));
   9659 
   9660     color_limit = 0 | _MMU_CFG_BUF_DYNAMIC_FLAG;
   9661 
   9662     for (idx = 0; idx < SOC_TD3_MMU_CFG_QGROUP_MAX; idx++) {
   9663         queue_grp = &buf->qgroups[idx];
   9664         if (lossless) {
   9665             queue_grp->pool_scale = -1;
   9666             queue_grp->pool_limit = egr_shared_total;
   9667             queue_grp->red_limit = egr_shared_total;
   9668             queue_grp->yellow_limit = egr_shared_total;
   9669         } else {
   9670             queue_grp->pool_scale = 8;
   9671             queue_grp->pool_limit = 0;
   9672             queue_grp->red_limit = color_limit;
   9673             queue_grp->yellow_limit = color_limit;
   9674         }
   9675     }
   9676 
   9677     PBMP_ALL_ITER(unit, port) {
   9678         if (port >= SOC_MMU_CFG_PORT_MAX) {
   9679             break;
   9680         }
   9681         buf_port = &buf->ports[port];
   9682 
   9683         /* priority group */
   9684         for (idx = 0; idx < _TD3_MMU_NUM_PG; idx++) {
   9685             buf_prigroup = &buf_port->prigroups[idx];
   9686             buf_prigroup->pool_limit = 0;
   9687             buf_prigroup->pool_scale = -1;
   9688             if (idx == 7) {
   9689                 if (lossless) {
   9690                     buf_prigroup->pool_scale = 8;
   9691                 } else {
   9692                     buf_prigroup->pool_limit = ing_shared_total;
   9693                 }
   9694             }
   9695         }
   9696 
   9697         /* multicast queue */
   9698         for (idx = 0; idx < si->port_num_cosq[port]; idx++) {
   9699             buf_queue = &buf_port->queues[idx];
   9700             if (lossless) {
   9701                 buf_queue->pool_scale = -1;
   9702                 buf_queue->pool_limit = egr_shared_total;
   9703                 buf_queue->yellow_limit = egr_shared_total;
   9704                 buf_queue->red_limit = egr_shared_total;
   9705             } else {
   9706                 buf_queue->pool_scale = 8;
   9707                 buf_queue->pool_limit = 0;
   9708                 buf_queue->yellow_limit = color_limit
   9709                                           | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;
   9710                 buf_queue->red_limit = color_limit
   9711                                        | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;
   9712             }
   9713         }
   9714 
   9715         /* unicast queue */
   9716         for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) {
   9717             buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx];
   9718             if (lossless) {
   9719                 buf_queue->pool_scale = -1;
   9720                 buf_queue->pool_limit = egr_shared_total;
   9721                 buf_queue->red_limit = egr_shared_total;
   9722                 buf_queue->yellow_limit = egr_shared_total;
   9723             } else {
   9724                 buf_queue->pool_scale = 8;
   9725                 buf_queue->pool_limit = 0;
   9726                 buf_queue->red_limit = color_limit
   9727                                        | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;
   9728                 buf_queue->yellow_limit = color_limit
   9729                                           | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;
   9730             }
   9731         }
   9732     }
   9733 
   9734     /* RQE */
   9735     for (idx = 0; idx < _TD3_MMU_NUM_RQE_QUEUES; idx++) {
   9736         buf_rqe_queue = &buf->rqe_queues[idx];
   9737         if (lossless) {
   9738             buf_rqe_queue->pool_scale = -1;
   9739             buf_rqe_queue->pool_limit = egr_shared_total;
   9740             buf_rqe_queue->red_limit = egr_shared_total;
   9741             buf_rqe_queue->yellow_limit = egr_shared_total;
   9742         } else {
   9743             buf_rqe_queue->pool_scale = 8;
   9744             buf_rqe_queue->pool_limit = 0;
   9745             buf_rqe_queue->red_limit = color_limit;
   9746             buf_rqe_queue->yellow_limit = color_limit;
   9747         }
   9748     }
   9749 }
   9750 
   9751 STATIC int
   9752 _soc_td3_pool_scale_to_limit(int size, int scale)
   9753 {
   9754     int factor = 1000;
   9755 
   9756     switch (scale) {
   9757         case 7: factor = 875; break;
   9758         case 6: factor = 750; break;
   9759         case 5: factor = 625; break;
   9760         case 4: factor = 500; break;
   9761         case 3: factor = 375; break;
   9762         case 2: factor = 250; break;
   9763         case 1: factor = 125; break;
   9764         case 0:
   9765         default:
   9766             factor = 1000; break;
   9767     }
   9768     return (size * factor)/1000;
   9769 }
   9770 
   9771 STATIC int
   9772 _soc_td3_mmu_config_buf_set_hw_port(int unit, int port, _soc_mmu_cfg_buf_t *buf,
   9773                                _soc_mmu_device_info_t *devcfg, int lossless,
   9774                                _soc_td3_mmu_sw_config_info_t *swcfg)
   9775 {
   9776     soc_info_t *si;
   9777     _soc_mmu_cfg_buf_pool_t *buf_pool;
   9778     _soc_mmu_cfg_buf_port_t *buf_port;
   9779     _soc_mmu_cfg_buf_port_pool_t *buf_port_pool;
   9780     thdi_port_sp_config_entry_t thdi_sp_config;
   9781     thdi_port_pg_config_entry_t pg_config_mem;
   9782     _soc_mmu_cfg_buf_prigroup_t *buf_prigroup;
   9783     _soc_mmu_cfg_buf_queue_t *buf_queue;
   9784     uint32 entry0[SOC_MAX_MEM_WORDS], entry1[SOC_MAX_MEM_WORDS];
   9785     soc_reg_t reg = INVALIDr;
   9786     soc_mem_t mem0, mem1, mem2, mem3;
   9787     uint32 fval, rval;
   9788     int base, numq;
   9789     int idx, midx, pri, index1;
   9790     int default_mtu_cells, limit, rlimit;
   9791     int pipe;
   9792 
   9793     static const soc_mem_t mmu_thdi_port_mem[] = {
   9794         THDI_PORT_SP_CONFIGm,
   9795         THDI_PORT_PG_CONFIGm
   9796     };
   9797     static const soc_mem_t mmu_thdo_q_uc_mem[] = {
   9798         MMU_THDU_CONFIG_QUEUEm,
   9799         MMU_THDU_OFFSET_QUEUEm,
   9800         MMU_THDU_Q_TO_QGRP_MAPm
   9801     };
   9802     static const soc_mem_t mmu_thdo_port_uc_mem[] = {
   9803         MMU_THDU_CONFIG_PORTm,
   9804         MMU_THDU_RESUME_PORTm
   9805     };
   9806     static const soc_mem_t mmu_thdo_q_mc_mem[] = {
   9807         MMU_THDM_DB_QUEUE_CONFIGm,
   9808         MMU_THDM_DB_QUEUE_OFFSETm,
   9809         MMU_THDM_MCQE_QUEUE_CONFIGm,
   9810         MMU_THDM_MCQE_QUEUE_OFFSETm
   9811     };
   9812 
   9813     static const soc_mem_t mmu_thdo_port_mc_mem[] = {
   9814         MMU_THDM_DB_PORTSP_CONFIGm,
   9815         MMU_THDM_MCQE_PORTSP_CONFIGm
   9816     };
   9817 
   9818     static const soc_field_t prigroup_reg[] = {
   9819         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   9820     };
   9821     static const soc_field_t prigroup_field[] = {
   9822         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   9823         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   9824         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   9825         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   9826     };
   9827     static const soc_field_t prigroup_spid_field[] = {
   9828         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   9829         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   9830     };
   9831 
   9832     si = &SOC_INFO(unit);
   9833     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size +
   9834                                                    devcfg->mmu_hdr_byte,
   9835                                                    devcfg->mmu_cell_size);
   9836 
   9837     /* internal priority to priority group mapping */
   9838     buf_port = &buf->ports[port];
   9839 
   9840     for (idx = 0; idx < COUNTOF(prigroup_field); idx++) {
   9841         if (idx % 8 == 0) { /* 8 fields per register */
   9842             reg = prigroup_reg[idx / 8];
   9843             rval = 0;
   9844         }
   9845         soc_reg_field_set(unit, reg, &rval, prigroup_field[idx],
   9846                 buf_port->pri_to_prigroup[idx]);
   9847         if (idx % 8 == 7) { /* 8 fields per register */
   9848             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   9849         }
   9850     }
   9851 
   9852     /* Input port per port settings */
   9853     pipe = si->port_pipe[port];
   9854     buf_port = &buf->ports[port];
   9855 
   9856     rval = 0;
   9857     for (idx = 0; idx < _TD3_MMU_NUM_PG; idx++) {
   9858         soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval,
   9859                           prigroup_spid_field[idx],
   9860                           buf_port->prigroups[idx].pool_idx);
   9861     }
   9862     SOC_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, port, rval));
   9863 
   9864     /* Per port per pool settings */
   9865     mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdi_port_mem[0])[pipe];
   9866     if (mem0 != INVALIDm) {
   9867         for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
   9868             buf_port_pool = &buf_port->pools[idx];
   9869             midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, port, mmu_thdi_port_mem[0],
   9870                                                idx);
   9871             sal_memset(&thdi_sp_config, 0, sizeof(thdi_sp_config));
   9872             soc_mem_field32_set(unit, mem0, &thdi_sp_config,
   9873                                 PORT_SP_MIN_LIMITf, buf_port_pool->guarantee);
   9874             soc_mem_field32_set(unit, mem0, &thdi_sp_config,
   9875                             PORT_SP_RESUME_LIMITf, buf_port_pool->pool_resume);
   9876             soc_mem_field32_set(unit, mem0, &thdi_sp_config,
   9877                                 PORT_SP_MAX_LIMITf, buf_port_pool->pool_limit);
   9878             SOC_IF_ERROR_RETURN
   9879                 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL,
   9880                                midx, &thdi_sp_config));
   9881         }
   9882     }
   9883 
   9884     fval = 0;
   9885     for (idx = 0; idx < _TD3_MMU_NUM_PG; idx++) {
   9886         if (buf_port->prigroups[idx].flow_control_enable != 0) {
   9887             for (pri=0; pri < 16; pri++) {
   9888                 if (buf_port->pri_to_prigroup[pri] == idx) {
   9889                     fval |= 1 << pri;
   9890                 }
   9891             }
   9892         }
   9893     }
   9894 
   9895     rval = 0;
   9896     soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   9897                       INPUT_PORT_RX_ENABLEf, 1);
   9898     if (port == CMIC_PORT (unit)) {
   9899         fval = 0;
   9900     }
   9901     soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   9902                       PORT_PRI_XON_ENABLEf, fval);
   9903     soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   9904                       PORT_PAUSE_ENABLEf, fval ? 1 : 0);
   9905     SOC_IF_ERROR_RETURN(WRITE_THDI_INPUT_PORT_XON_ENABLESr(unit,
   9906                         port, rval));
   9907 
   9908     rval = 0;
   9909     soc_reg_field_set(unit, THDI_PORT_MAX_PKT_SIZEr, &rval,
   9910                       PORT_MAX_PKT_SIZEf, buf_port->pkt_size);
   9911     SOC_IF_ERROR_RETURN(WRITE_THDI_PORT_MAX_PKT_SIZEr(unit, rval));
   9912 
   9913     /* Input port per port per priority group settings */
   9914     mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdi_port_mem[1])[pipe];
   9915     if (mem1 != INVALIDm) {
   9916         for (idx = 0; idx < _TD3_MMU_NUM_PG; idx++) {
   9917             buf_prigroup = &buf->ports[port].prigroups[idx];
   9918 
   9919             midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, port, mmu_thdi_port_mem[1],
   9920                                                idx);
   9921             sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem));
   9922             soc_mem_field32_set(unit, mem1, &pg_config_mem,
   9923                                 PG_MIN_LIMITf, buf_prigroup->guarantee);
   9924 
   9925             if (buf_prigroup->pool_scale != -1) {
   9926                 soc_mem_field32_set(unit, mem1, &pg_config_mem,
   9927                                     PG_SHARED_DYNAMICf, 1);
   9928                 soc_mem_field32_set(unit, mem1, &pg_config_mem,
   9929                                     PG_SHARED_LIMITf,
   9930                                     buf_prigroup->pool_scale);
   9931             } else {
   9932                 soc_mem_field32_set(unit, mem1, &pg_config_mem,
   9933                                     PG_SHARED_LIMITf,
   9934                                     buf_prigroup->pool_limit);
   9935             }
   9936 
   9937             soc_mem_field32_set(unit, mem1, &pg_config_mem,
   9938                                 PG_GBL_HDRM_ENf,
   9939                                 buf_prigroup->device_headroom_enable);
   9940             soc_mem_field32_set(unit, mem1, &pg_config_mem,
   9941                                 PG_HDRM_LIMITf, buf_prigroup->headroom);
   9942 
   9943             soc_mem_field32_set(unit, mem1, &pg_config_mem, PG_RESET_OFFSETf,
   9944                                 0);
   9945 
   9946             soc_mem_field32_set(unit, mem1, &pg_config_mem,
   9947                                 PG_RESET_FLOORf, buf_prigroup->pool_floor);
   9948 
   9949             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1, MEM_BLOCK_ALL, midx,
   9950                                 &pg_config_mem));
   9951         }
   9952     }
   9953 
   9954     /***********************************
   9955      * THDO
   9956  */
   9957     /* Output port per port per queue setting for regular multicast queue */
   9958     pipe = si->port_pipe[port];
   9959     numq = si->port_num_cosq[port];
   9960     base = si->port_cosq_base[port];
   9961 
   9962     mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[0])[pipe];
   9963     mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[1])[pipe];
   9964     if ((numq != 0) && (mem0 != INVALIDm) && (mem1 != INVALIDm)) {
   9965         for (idx = 0; idx < numq; idx++) {
   9966             buf_queue = &buf->ports[port].queues[idx];
   9967 
   9968             sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_config_0_entry_t));
   9969 
   9970             soc_mem_field32_set(unit, mem0, entry0, Q_MIN_LIMITf,
   9971                                 buf_queue->guarantee);
   9972             if (buf_queue->discard_enable) {
   9973                 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_ENABLEf, 1);
   9974             }
   9975             if (buf_queue->color_discard_enable) {
   9976                 soc_mem_field32_set(unit, mem0, entry0, Q_COLOR_LIMIT_ENABLEf, 1);
   9977             }
   9978             if (buf_queue->pool_scale != -1) {
   9979                 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_DYNAMICf, 1);
   9980                 soc_mem_field32_set(unit, mem0, entry0, Q_SHARED_ALPHAf,
   9981                                     buf_queue->pool_scale);
   9982             } else {
   9983                 /* Q_LIMIT_DYNAMIC_CELLf is 0 */
   9984                 soc_mem_field32_set(unit, mem0, entry0, Q_SHARED_LIMITf,
   9985                                     buf_queue->pool_limit);
   9986             }
   9987             if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   9988                     (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   9989                 soc_mem_field32_set(unit, mem0, entry0, Q_COLOR_LIMIT_DYNAMICf, 1);
   9990                 soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf,
   9991                         buf_queue->yellow_limit
   9992                                  & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   9993                                  & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   9994                 soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf,
   9995                         buf_queue->red_limit
   9996                                  & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   9997                                  & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   9998             } else {
   9999                 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
  10000                 soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf,
  10001                                     sal_ceil_func(buf_queue->yellow_limit, 8));
  10002                 soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf,
  10003                                     sal_ceil_func(buf_queue->red_limit, 8));
  10004             }
  10005 
  10006             soc_mem_field32_set(unit, mem0, entry0, Q_SPIDf, buf_queue->pool_idx);
  10007 
  10008             SOC_IF_ERROR_RETURN
  10009                 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, base + idx, entry0));
  10010 
  10011             sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_offset_entry_t));
  10012 
  10013             soc_mem_field32_set(unit, mem1, entry0, RESUME_OFFSETf,
  10014                                 (default_mtu_cells * 2)/8);
  10015             soc_mem_field32_set(unit, mem1, entry0,
  10016                                 YELLOW_RESUME_OFFSET_PROFILE_SELf, 0);
  10017             soc_mem_field32_set(unit, mem1, entry0,
  10018                                 RED_RESUME_OFFSET_PROFILE_SELf, 0);
  10019             SOC_IF_ERROR_RETURN
  10020                 (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, base + idx, entry0));
  10021 
  10022             rval = 0;
  10023             SOC_IF_ERROR_RETURN(
  10024                     WRITE_MMU_THDM_DB_QUEUE_RESUME_OFFSET_PROFILE_YELLOWr(unit, 0,
  10025                         2));
  10026 
  10027             rval = 0;
  10028             SOC_IF_ERROR_RETURN(
  10029                     WRITE_MMU_THDM_DB_QUEUE_RESUME_OFFSET_PROFILE_REDr(unit, 0,
  10030                         2));
  10031         }
  10032     }
  10033 
  10034     mem2 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[2])[pipe];
  10035     mem3 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[3])[pipe];
  10036     if ((numq != 0) && (mem2 != INVALIDm) && (mem3 != INVALIDm)) {
  10037         for (idx = 0; idx < numq; idx++) {
  10038             buf_queue = &buf->ports[port].queues[idx];
  10039             buf_pool = &buf->pools[buf_queue->pool_idx];
  10040             if (buf_pool->total == 0) {
  10041                 continue;
  10042             }
  10043             sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_config_entry_t));
  10044 
  10045             soc_mem_field32_set(unit, mem2, entry0, Q_MIN_LIMITf,
  10046                                 sal_ceil_func(buf_queue->mcq_entry_guarantee, 4));
  10047             limit = buf_pool->total_mcq_entry - buf_pool->mcq_entry_reserved;
  10048 
  10049             if (buf_queue->discard_enable) {
  10050                 soc_mem_field32_set(unit, mem2, entry0, Q_LIMIT_ENABLEf, 1);
  10051             }
  10052             if (buf_queue->color_discard_enable) {
  10053                 soc_mem_field32_set(unit, mem2, entry0, Q_COLOR_LIMIT_ENABLEf, 1);
  10054             }
  10055             if (buf_queue->pool_scale != -1) {
  10056                 soc_mem_field32_set(unit, mem2, entry0, Q_LIMIT_DYNAMICf, 1);
  10057                 soc_mem_field32_set(unit, mem2, entry0, Q_SHARED_ALPHAf,
  10058                                     buf_queue->pool_scale);
  10059             } else {
  10060                 /* Q_LIMIT_DYNAMIC_CELLf is 0 */
  10061                 soc_mem_field32_set(unit, mem2, entry0, Q_SHARED_LIMITf,
  10062                                     sal_ceil_func(limit, 4));
  10063             }
  10064             if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
  10065                     (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
  10066                 soc_mem_field32_set(unit, mem2, entry0, Q_COLOR_LIMIT_DYNAMICf, 1);
  10067                 soc_mem_field32_set(unit, mem2, entry0, YELLOW_SHARED_LIMITf,
  10068                         buf_queue->yellow_limit
  10069                                  & ~_MMU_CFG_BUF_DYNAMIC_FLAG
  10070                                  & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
  10071                 soc_mem_field32_set(unit, mem2, entry0, RED_SHARED_LIMITf,
  10072                         buf_queue->red_limit
  10073                                  & ~_MMU_CFG_BUF_DYNAMIC_FLAG
  10074                                  & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
  10075             } else {
  10076                 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
  10077                 soc_mem_field32_set(unit, mem2, entry0, YELLOW_SHARED_LIMITf,
  10078                                     sal_ceil_func(limit, 8));
  10079                 soc_mem_field32_set(unit, mem2, entry0, RED_SHARED_LIMITf,
  10080                                     sal_ceil_func(limit, 8));
  10081             }
  10082 
  10083             soc_mem_field32_set(unit, mem2, entry0, Q_SPIDf, buf_queue->pool_idx);
  10084 
  10085             SOC_IF_ERROR_RETURN
  10086                 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, base + idx, entry0));
  10087 
  10088             sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_offset_entry_t));
  10089 
  10090             soc_mem_field32_set(unit, mem3, entry0, RESUME_OFFSETf, 1);
  10091             soc_mem_field32_set(unit, mem3, entry0,
  10092                                 YELLOW_RESUME_OFFSET_PROFILE_SELf, 0);
  10093             soc_mem_field32_set(unit, mem3, entry0,
  10094                                 RED_RESUME_OFFSET_PROFILE_SELf, 0);
  10095             SOC_IF_ERROR_RETURN
  10096                 (soc_mem_write(unit, mem3, MEM_BLOCK_ALL, base + idx, entry0));
  10097 
  10098             rval = 0;
  10099             SOC_IF_ERROR_RETURN(
  10100                     WRITE_MMU_THDM_MCQE_QUEUE_RESUME_OFFSET_PROFILE_YELLOWr(unit, 0,
  10101                         1));
  10102 
  10103             rval = 0;
  10104             SOC_IF_ERROR_RETURN(
  10105                     WRITE_MMU_THDM_MCQE_QUEUE_RESUME_OFFSET_PROFILE_REDr(unit, 0,
  10106                         1));
  10107         }
  10108     }
  10109 
  10110     /* Per  port per pool */
  10111     for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
  10112         buf_port_pool = &buf->ports[port].pools[idx];
  10113         if (buf_port_pool->pool_limit == 0) {
  10114             continue;
  10115         }
  10116 
  10117         limit = buf_port_pool->pool_limit;
  10118         rlimit = limit - (default_mtu_cells * 2);
  10119 
  10120         mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_mc_mem[0])[pipe];
  10121         if (mem0 == INVALIDm) {
  10122             continue;
  10123         }
  10124 
  10125         index1 = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, port,
  10126                                              mmu_thdo_port_mc_mem[0], idx);
  10127         sal_memset(entry0, 0, sizeof(mmu_thdm_db_portsp_config_entry_t));
  10128 
  10129         soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMITf, limit);
  10130         soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf,
  10131                             sal_ceil_func(limit, 8));
  10132         soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf,
  10133                             sal_ceil_func(limit, 8));
  10134 
  10135         soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMIT_ENABLEf,
  10136                             !lossless);
  10137 
  10138         soc_mem_field32_set(unit, mem0, entry0, SHARED_RESUME_LIMITf,
  10139                             sal_ceil_func(rlimit, 8));
  10140         soc_mem_field32_set(unit, mem0, entry0, YELLOW_RESUME_LIMITf,
  10141                             sal_ceil_func(rlimit, 8));
  10142         soc_mem_field32_set(unit, mem0, entry0, RED_RESUME_LIMITf,
  10143                             sal_ceil_func(rlimit, 8));
  10144 
  10145         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem0, MEM_BLOCK_ALL,
  10146                             index1, entry0));
  10147 
  10148         mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_mc_mem[1])[pipe];
  10149         if (mem1 == INVALIDm) {
  10150             continue;
  10151         }
  10152         buf_pool = &buf->pools[idx];
  10153         sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_portsp_config_entry_t));
  10154 
  10155         limit = _TD3_MMU_TOTAL_MCQ_ENTRY(unit);
  10156 
  10157         soc_mem_field32_set(unit, mem1, entry0, SHARED_LIMITf,
  10158                             (sal_ceil_func(limit, 4)) - 1);
  10159         soc_mem_field32_set(unit, mem1, entry0, YELLOW_SHARED_LIMITf,
  10160                             (sal_ceil_func(limit, 8)) - 1);
  10161         soc_mem_field32_set(unit, mem1, entry0, RED_SHARED_LIMITf,
  10162                             (sal_ceil_func(limit, 8)) - 1);
  10163 
  10164         soc_mem_field32_set(unit, mem1, entry0, SHARED_LIMIT_ENABLEf,
  10165                             !lossless);
  10166 
  10167         soc_mem_field32_set(unit, mem1, entry0, SHARED_RESUME_LIMITf,
  10168                             (sal_ceil_func(limit, 8)) - 2);
  10169         soc_mem_field32_set(unit, mem1, entry0, YELLOW_RESUME_LIMITf,
  10170                             (sal_ceil_func(limit, 8)) - 2);
  10171         soc_mem_field32_set(unit, mem1, entry0, RED_RESUME_LIMITf,
  10172                             (sal_ceil_func(limit, 8)) - 2);
  10173 
  10174         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1, MEM_BLOCK_ALL,
  10175                             index1, entry0));
  10176     }
  10177 
  10178     /* Output port per port per queue setting for regular unicast queue */
  10179     pipe = si->port_pipe[port];
  10180     /* per port regular unicast queue */
  10181     numq = si->port_num_uc_cosq[port];
  10182     base = si->port_uc_cosq_base[port];
  10183 
  10184     mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[0])[pipe];
  10185     mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[1])[pipe];
  10186     mem2 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[2])[pipe];
  10187     if ((numq != 0) &&
  10188         (mem0 != INVALIDm) && (mem1 != INVALIDm) && (mem2 != INVALIDm)) {
  10189         for (idx = 0; idx < numq; idx++) {
  10190             buf_queue = &buf->ports[port].queues[si->port_num_cosq[port] + idx];
  10191 
  10192             sal_memset(entry0, 0, sizeof(mmu_thdu_config_queue_entry_t));
  10193             sal_memset(entry1, 0, sizeof(mmu_thdu_offset_queue_entry_t));
  10194 
  10195             soc_mem_field32_set(unit, mem0, entry0,
  10196                                 Q_MIN_LIMIT_CELLf, buf_queue->guarantee);
  10197             if (buf_queue->pool_scale != -1) {
  10198                 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_DYNAMIC_CELLf, 1);
  10199                 soc_mem_field32_set(unit, mem0, entry0, Q_SHARED_ALPHA_CELLf,
  10200                                     buf_queue->pool_scale);
  10201             } else {
  10202                 /* Q_LIMIT_DYNAMIC_CELLf is 0 */
  10203                 soc_mem_field32_set(unit, mem0, entry0, Q_SHARED_LIMIT_CELLf,
  10204                                     buf_queue->pool_limit);
  10205             }
  10206             soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_CELLf,
  10207                                 sal_ceil_func(buf_queue->pool_resume, 8));
  10208 
  10209             if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
  10210                     (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
  10211                 soc_mem_field32_set(unit, mem0, entry0,
  10212                                     Q_COLOR_LIMIT_DYNAMIC_CELLf, 1);
  10213                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_YELLOW_CELLf,
  10214                         buf_queue->yellow_limit
  10215                                  & ~_MMU_CFG_BUF_DYNAMIC_FLAG
  10216                                  & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
  10217                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_RED_CELLf,
  10218                         buf_queue->red_limit
  10219                                  & ~_MMU_CFG_BUF_DYNAMIC_FLAG
  10220                                  & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
  10221             } else {
  10222                 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
  10223                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_YELLOW_CELLf,
  10224                                     sal_ceil_func(buf_queue->yellow_limit, 8));
  10225                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_RED_CELLf,
  10226                                     sal_ceil_func(buf_queue->red_limit, 8));
  10227             }
  10228             soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_YELLOW_CELLf,
  10229                                 sal_ceil_func(buf_queue->yellow_resume, 8));
  10230             soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_RED_CELLf,
  10231                                 sal_ceil_func(buf_queue->red_resume, 8));
  10232             SOC_IF_ERROR_RETURN
  10233                 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, base + idx, entry0));
  10234 
  10235             SOC_IF_ERROR_RETURN
  10236                 (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, base + idx, entry1));
  10237 
  10238             sal_memset(entry0, 0, sizeof(mmu_thdo_q_to_qgrp_map_entry_t));
  10239 
  10240             if (buf_queue->qgroup_id >= 0) {
  10241                 soc_mem_field32_set(unit, mem2, entry0, QGROUP_VALIDf, 1);
  10242                 if (buf_queue->qgroup_min_enable) {
  10243                     soc_mem_field32_set(unit, mem2, entry0, USE_QGROUP_MINf, 1);
  10244                 }
  10245             }
  10246             if (buf_queue->discard_enable) {
  10247                 soc_mem_field32_set(unit, mem2, entry0, Q_LIMIT_ENABLEf, 1);
  10248             }
  10249 
  10250             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, base + idx,
  10251                                 entry0));
  10252         }
  10253     }
  10254 
  10255     /* Per  port per pool unicast */
  10256     for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
  10257         buf_pool = &buf->pools[idx];
  10258 
  10259         if (buf_pool->total == 0) {
  10260             continue;
  10261         }
  10262 
  10263         limit = buf->ports[port].pools[idx].pool_limit;
  10264 
  10265         mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_uc_mem[0])[pipe];
  10266         mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_uc_mem[1])[pipe];
  10267         if ((mem0 == INVALIDm) || (mem1 == INVALIDm)) {
  10268             continue;
  10269         }
  10270         index1 = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, port,
  10271                                              mmu_thdo_port_uc_mem[0], idx);
  10272         sal_memset(entry0, 0, sizeof(mmu_thdu_config_port_entry_t));
  10273         sal_memset(entry1, 0, sizeof(mmu_thdu_resume_port_entry_t));
  10274 
  10275         soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMITf, limit);
  10276         soc_mem_field32_set(unit, mem1, entry1, SHARED_RESUMEf,
  10277                             sal_ceil_func((limit - (default_mtu_cells * 2)),
  10278                             8));
  10279 
  10280         soc_mem_field32_set(unit, mem0, entry0, YELLOW_LIMITf,
  10281                             sal_ceil_func(limit, 8));
  10282         soc_mem_field32_set(unit, mem1, entry1, YELLOW_RESUMEf,
  10283                             sal_ceil_func((limit - (default_mtu_cells*2)),
  10284                             8));
  10285 
  10286         soc_mem_field32_set(unit, mem0, entry0, RED_LIMITf,
  10287                             sal_ceil_func(limit, 8));
  10288         soc_mem_field32_set(unit, mem1, entry1, RED_RESUMEf,
  10289                             sal_ceil_func((limit - (default_mtu_cells * 2)),
  10290                             8));
  10291 
  10292         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem0, MEM_BLOCK_ALL,
  10293                             index1, entry0));
  10294         SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1, MEM_BLOCK_ALL,
  10295                             index1, entry1));
  10296     }
  10297 
  10298     return SOC_E_NONE;
  10299 }
  10300 
  10301 STATIC int
  10302 _soc_td3_mmu_config_buf_set_hw_global(int unit, _soc_mmu_cfg_buf_t *buf,
  10303                                _soc_mmu_device_info_t *devcfg, int lossless,
  10304                                _soc_td3_mmu_sw_config_info_t *swcfg)
  10305 {
  10306     _soc_mmu_cfg_buf_pool_t *buf_pool;
  10307     _soc_mmu_cfg_buf_qgroup_t *queue_grp;
  10308     mmu_thdo_config_qgroup_entry_t cfg_qgrp;
  10309     mmu_thdo_offset_qgroup_entry_t offset_qgrp;
  10310     _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue;
  10311     soc_mem_t mem0, mem1;
  10312     uint32 fval, rval, rval2, rval3;
  10313     int rqlen, idx, pval;
  10314     int jumbo_frame_cells, default_mtu_cells, limit;
  10315     int pipe;
  10316     uint64 rval64;
  10317     uint64 rval2_64;
  10318     int pool_resume = 0;
  10319 
  10320      static const soc_mem_t mmu_thdo_qgrp_uc_mem[] = {
  10321          MMU_THDU_CONFIG_QGROUPm,
  10322          MMU_THDU_OFFSET_QGROUPm
  10323     };
  10324 
  10325     jumbo_frame_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->jumbo_pkt_size +
  10326                                                     devcfg->mmu_hdr_byte,
  10327                                                     devcfg->mmu_cell_size);
  10328     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size +
  10329                                                    devcfg->mmu_hdr_byte,
  10330                                                    devcfg->mmu_cell_size);
  10331     pool_resume = 2 * jumbo_frame_cells;
  10332 
  10333     rval = 0;
  10334     fval = _TD3_MMU_PHYSICAL_CELLS_PER_XPE - _TD3_MMU_RSVD_CELLS_CFAP_PER_XPE;
  10335     soc_reg_field_set(unit, CFAPFULLTHRESHOLDSETr, &rval, CFAPFULLSETPOINTf,
  10336                       fval);
  10337     SOC_IF_ERROR_RETURN(
  10338         soc_trident3_xpe_reg32_set(unit, CFAPFULLTHRESHOLDSETr, -1, -1,
  10339                                    -1, rval));
  10340 
  10341     rval = 0;
  10342     soc_reg_field_set(unit, CFAPFULLTHRESHOLDRESETr, &rval,
  10343                       CFAPFULLRESETPOINTf, fval - (2 * jumbo_frame_cells));
  10344     SOC_IF_ERROR_RETURN(
  10345         soc_trident3_xpe_reg32_set(unit, CFAPFULLTHRESHOLDRESETr, -1, -1,
  10346                                    -1, rval));
  10347 
  10348     rval = 0;
  10349     soc_reg_field_set(unit, CFAPBANKFULLr, &rval, LIMITf,
  10350                       _TD3_MMU_CFAP_BANK_FULL_LIMIT);
  10351     for (idx = 0; idx < SOC_REG_NUMELS(unit, CFAPBANKFULLr); idx++) {
  10352         SOC_IF_ERROR_RETURN(
  10353             soc_trident3_xpe_reg32_set(unit, CFAPBANKFULLr, -1, -1,
  10354                                        idx, rval));
  10355     }
  10356 
  10357     rval = 0;
  10358     SOC_IF_ERROR_RETURN(READ_MMU_SCFG_TOQ_MC_CFG0r(unit, &rval));
  10359     soc_reg_field_set(unit, MMU_SCFG_TOQ_MC_CFG0r, &rval,
  10360                       MCQE_FULL_THRESHOLDf, 0);
  10361     SOC_IF_ERROR_RETURN(WRITE_MMU_SCFG_TOQ_MC_CFG0r(unit, rval));
  10362 
  10363     rval = 0;
  10364     for (idx = 0; idx < 2; idx++) {
  10365         SOC_IF_ERROR_RETURN
  10366             (soc_reg32_get(unit, THDI_HDRM_POOL_CFGr, idx, 0, &rval));
  10367         soc_reg_field_set(unit, THDI_HDRM_POOL_CFGr, &rval,
  10368                           PEAK_COUNT_UPDATE_EN_HPf, 0);
  10369         SOC_IF_ERROR_RETURN
  10370             (soc_reg32_set(unit, THDI_HDRM_POOL_CFGr, idx, 0, rval));
  10371     }
  10372 
  10373     /* Input thresholds */
  10374     rval = 0;
  10375     soc_reg_field_set(unit, THDI_GLOBAL_HDRM_LIMITr,
  10376                       &rval, GLOBAL_HDRM_LIMITf, buf->headroom / 2);
  10377     SOC_IF_ERROR_RETURN(
  10378         soc_trident3_xpe_reg32_set(unit, THDI_GLOBAL_HDRM_LIMITr, -1, -1, 0,
  10379                                    rval));
  10380 
  10381     for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
  10382         buf_pool = &buf->pools[idx];
  10383         if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) {
  10384             continue;
  10385         }
  10386 
  10387         limit = swcfg->ing_shared_total;
  10388 
  10389         rval = 0;
  10390         soc_reg_field_set(unit, THDI_BUFFER_CELL_LIMIT_SPr, &rval, LIMITf,
  10391                           limit);
  10392         SOC_IF_ERROR_RETURN(
  10393             soc_trident3_xpe_reg32_set(unit, THDI_BUFFER_CELL_LIMIT_SPr,
  10394                                        -1, -1, idx, rval));
  10395 
  10396         rval = 0;
  10397         soc_reg_field_set(unit, THDI_CELL_RESET_LIMIT_OFFSET_SPr, &rval,
  10398                           OFFSETf, pool_resume);
  10399         SOC_IF_ERROR_RETURN(
  10400             soc_trident3_xpe_reg32_set(unit, THDI_CELL_RESET_LIMIT_OFFSET_SPr,
  10401                                        -1, -1, idx, rval));
  10402 
  10403         rval = 0;
  10404         soc_reg_field_set(unit, THDI_HDRM_BUFFER_CELL_LIMIT_HPr, &rval,
  10405                           LIMITf, buf_pool->prigroup_headroom);
  10406         SOC_IF_ERROR_RETURN(
  10407             soc_trident3_xpe_reg32_set(unit, THDI_HDRM_BUFFER_CELL_LIMIT_HPr,
  10408                                        -1, -1, idx, rval));
  10409     }
  10410 
  10411     rval = 0;
  10412     SOC_IF_ERROR_RETURN(
  10413         soc_trident3_xpe_reg32_set(unit, THDI_BUFFER_CELL_LIMIT_PUBLIC_POOLr,
  10414                                    -1, -1, 0, rval));
  10415 
  10416     /* output thresholds */
  10417     SOC_IF_ERROR_RETURN(READ_OP_THDU_CONFIGr(unit, &rval));
  10418     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval,
  10419                       ENABLE_QUEUE_AND_GROUP_TICKETf, 1);
  10420     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval,
  10421                       ENABLE_UPDATE_COLOR_RESUMEf, 0);
  10422     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, MOP_POLICY_1Bf, 1);
  10423     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, MOP_POLICY_1Af, 0);
  10424     SOC_IF_ERROR_RETURN(WRITE_OP_THDU_CONFIGr(unit, rval));
  10425 
  10426     rval = 0;
  10427     SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval));
  10428     soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval,
  10429                       MOP_POLICYf, 1);
  10430     SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval));
  10431 
  10432     rval = 0;
  10433     SOC_IF_ERROR_RETURN(READ_MMU_THDR_DB_CONFIGr(unit, &rval));
  10434     soc_reg_field_set(unit, MMU_THDR_DB_CONFIGr, &rval,
  10435                       MOP_POLICY_1Bf, 1);
  10436     SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIGr(unit, rval));
  10437 
  10438     /* per service pool settings */
  10439     for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
  10440         buf_pool = &buf->pools[idx];
  10441         if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) {
  10442             continue;
  10443         }
  10444 
  10445         limit = swcfg->egr_shared_total;
  10446 
  10447         rval = 0;
  10448         soc_reg_field_set(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, &rval,
  10449                           SHARED_LIMITf, limit);
  10450         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_POOL_SHARED_LIMITr(unit,
  10451                                                                  idx,
  10452                                                                  rval));
  10453 
  10454         rval = 0;
  10455         soc_reg_field_set(unit, MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr,
  10456                           &rval, YELLOW_SHARED_LIMITf, sal_ceil_func(limit, 8));
  10457         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr(unit,
  10458                                                                         idx,
  10459                                                                         rval));
  10460 
  10461         rval = 0;
  10462         soc_reg_field_set(unit, MMU_THDM_DB_POOL_RED_SHARED_LIMITr,
  10463                           &rval, RED_SHARED_LIMITf, sal_ceil_func(limit, 8));
  10464         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_POOL_RED_SHARED_LIMITr(unit,
  10465                                                                      idx,
  10466                                                                      rval));
  10467 
  10468         rval = 0;
  10469         soc_reg_field_set(unit, MMU_THDM_DB_POOL_RESUME_LIMITr,
  10470                           &rval, RESUME_LIMITf, sal_ceil_func(limit, 8));
  10471         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_POOL_RESUME_LIMITr(unit,
  10472                                                                  idx,
  10473                                                                  rval));
  10474 
  10475         rval = 0;
  10476         soc_reg_field_set(unit, MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr,
  10477                           &rval, YELLOW_RESUME_LIMITf, sal_ceil_func(limit, 8));
  10478         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr(unit,
  10479                                                                         idx,
  10480                                                                         rval));
  10481 
  10482         rval = 0;
  10483         soc_reg_field_set(unit, MMU_THDM_DB_POOL_RED_RESUME_LIMITr,
  10484                           &rval, RED_RESUME_LIMITf, sal_ceil_func(limit, 8));
  10485         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_POOL_RED_RESUME_LIMITr(unit,
  10486                                                                      idx,
  10487                                                                      rval));
  10488 
  10489         /* mcq entries */
  10490         limit = buf_pool->total_mcq_entry - buf_pool->mcq_entry_reserved;
  10491 
  10492         rval = 0;
  10493         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_SHARED_LIMITr,
  10494                           &rval, SHARED_LIMITf, sal_ceil_func(limit, 4));
  10495         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_MCQE_POOL_SHARED_LIMITr(unit,
  10496                                                                    idx, rval));
  10497 
  10498         rval = 0;
  10499         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr,
  10500                           &rval, YELLOW_SHARED_LIMITf, sal_ceil_func(limit, 8));
  10501         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr(unit,
  10502                                                                    idx, rval));
  10503 
  10504         rval = 0;
  10505         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr,
  10506                           &rval, RED_SHARED_LIMITf, sal_ceil_func(limit, 8));
  10507         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr(unit,
  10508                                                                    idx, rval));
  10509 
  10510         rval = 0;
  10511         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RESUME_LIMITr,
  10512                           &rval, RESUME_LIMITf, sal_ceil_func(limit, 8));
  10513         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_MCQE_POOL_RESUME_LIMITr(unit,
  10514                                                                    idx, rval));
  10515 
  10516         rval = 0;
  10517         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_YELLOW_RESUME_LIMITr,
  10518                           &rval, YELLOW_RESUME_LIMITf, sal_ceil_func(limit, 8));
  10519         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_MCQE_POOL_YELLOW_RESUME_LIMITr(unit,
  10520                                                                    idx, rval));
  10521 
  10522         rval = 0;
  10523         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RED_RESUME_LIMITr,
  10524                           &rval, RED_RESUME_LIMITf, sal_ceil_func(limit, 8));
  10525         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_MCQE_POOL_RED_RESUME_LIMITr(unit,
  10526                                                                    idx, rval));
  10527     }
  10528 
  10529     /* configure Q-groups */
  10530     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  10531         for (idx = 0; idx < SOC_TD3_MMU_CFG_QGROUP_MAX; idx++) {
  10532             mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_qgrp_uc_mem[0])[pipe];
  10533             mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_qgrp_uc_mem[1])[pipe];
  10534             if ((mem0 == INVALIDm) || (mem1 == INVALIDm)) {
  10535                 continue;
  10536             }
  10537             queue_grp = &buf->qgroups[idx];
  10538 
  10539 
  10540             sal_memset(&cfg_qgrp, 0, sizeof(cfg_qgrp));
  10541             sal_memset(&offset_qgrp, 0, sizeof(offset_qgrp));
  10542 
  10543             soc_mem_field32_set(unit, mem0, &cfg_qgrp,
  10544                                 Q_MIN_LIMIT_CELLf, queue_grp->guarantee);
  10545 
  10546             if (queue_grp->pool_scale != -1) {
  10547                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
  10548                                     Q_SHARED_ALPHA_CELLf,
  10549                                     queue_grp->pool_scale);
  10550                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
  10551                                     Q_LIMIT_DYNAMIC_CELLf, 1);
  10552             } else {
  10553                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
  10554                                     Q_SHARED_LIMIT_CELLf,
  10555                                     queue_grp->pool_limit);
  10556             }
  10557 
  10558             if ((queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
  10559                 (queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
  10560                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
  10561                                     Q_COLOR_LIMIT_DYNAMIC_CELLf, 1);
  10562             }
  10563 
  10564             if (queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) {
  10565                 pval = _soc_td3_pool_scale_to_limit(queue_grp->pool_limit,
  10566                           queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG);
  10567                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
  10568                                     LIMIT_RED_CELLf, sal_ceil_func(pval, 8));
  10569 
  10570             } else {
  10571                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
  10572                                     LIMIT_RED_CELLf,
  10573                                     sal_ceil_func(queue_grp->red_limit, 8));
  10574             }
  10575 
  10576             if (queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) {
  10577                 pval = _soc_td3_pool_scale_to_limit(queue_grp->pool_limit,
  10578                           queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG);
  10579                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
  10580                                     LIMIT_YELLOW_CELLf, sal_ceil_func(pval, 8));
  10581 
  10582             } else {
  10583                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
  10584                                     LIMIT_YELLOW_CELLf,
  10585                                     sal_ceil_func(queue_grp->yellow_limit, 8));
  10586             }
  10587 
  10588             soc_mem_field32_set(unit, mem1, &offset_qgrp,
  10589                                 RESET_OFFSET_CELLf,
  10590                                 sal_ceil_func(queue_grp->pool_resume, 8));
  10591             soc_mem_field32_set(unit, mem1, &offset_qgrp,
  10592                                 RESET_OFFSET_YELLOW_CELLf,
  10593                                 sal_ceil_func(queue_grp->pool_resume, 8));
  10594             soc_mem_field32_set(unit, mem1, &offset_qgrp,
  10595                                 RESET_OFFSET_RED_CELLf,
  10596                                 sal_ceil_func(queue_grp->pool_resume, 8));
  10597             SOC_IF_ERROR_RETURN
  10598                     (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, idx, &cfg_qgrp));
  10599             SOC_IF_ERROR_RETURN
  10600                     (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, idx, &offset_qgrp));
  10601         }
  10602     }
  10603 
  10604     /* RQE */
  10605     for (idx = 0; idx < _TD3_MMU_NUM_RQE_QUEUES; idx++) {
  10606         buf_rqe_queue = &buf->rqe_queues[idx];
  10607 
  10608         rval = 0;
  10609         soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_MIN_PRIQr,
  10610                           &rval, MIN_LIMITf, buf_rqe_queue->guarantee);
  10611         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_LIMIT_MIN_PRIQr(unit, idx, rval));
  10612 
  10613         rval = 0;
  10614         rval2 = 0;
  10615         rval3 = 0;
  10616         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr,
  10617                             &rval, SPIDf, buf_rqe_queue->pool_idx);
  10618 
  10619         if ((buf_rqe_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
  10620             (buf_rqe_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
  10621             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr,
  10622                               &rval, COLOR_LIMIT_DYNAMICf, 1);
  10623             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
  10624                 SHARED_RED_LIMITf,
  10625                 buf_rqe_queue->red_limit & ~_MMU_CFG_BUF_DYNAMIC_FLAG);
  10626             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
  10627                 SHARED_YELLOW_LIMITf,
  10628                 buf_rqe_queue->yellow_limit & ~_MMU_CFG_BUF_DYNAMIC_FLAG);
  10629         } else {
  10630             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
  10631                               SHARED_RED_LIMITf,
  10632                               sal_ceil_func(buf_rqe_queue->red_limit, 8));
  10633 
  10634             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
  10635                               SHARED_YELLOW_LIMITf,
  10636                               sal_ceil_func(buf_rqe_queue->yellow_limit, 8));
  10637         }
  10638 
  10639         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr, &rval, LIMIT_ENABLEf,
  10640                           (buf_rqe_queue->discard_enable ? 1 : 0));
  10641 
  10642         if (buf_rqe_queue->pool_scale != -1) {
  10643             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr,
  10644                               &rval, DYNAMIC_ENABLEf, 1);
  10645             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
  10646                               SHARED_ALPHAf, buf_rqe_queue->pool_scale);
  10647         } else {
  10648             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
  10649                               SHARED_LIMITf, buf_rqe_queue->pool_limit);
  10650         }
  10651         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
  10652                           RESET_OFFSETf, 2);
  10653 
  10654         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIG1_PRIQr(unit, idx, rval));
  10655 
  10656         COMPILER_64_SET(rval2_64, 0, rval2);
  10657         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIG_PRIQr(unit, idx, rval2_64));
  10658         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_LIMIT_COLOR_PRIQr(unit,
  10659                                                                 idx, rval3));
  10660 
  10661         rval = 0;
  10662         soc_reg_field_set(unit, MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr,
  10663                           &rval, RESET_OFFSET_REDf, 2);
  10664         soc_reg_field_set(unit, MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr,
  10665                           &rval, RESET_OFFSET_YELLOWf, 2);
  10666         SOC_IF_ERROR_RETURN(
  10667                   WRITE_MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr(unit, idx, rval));
  10668 
  10669         /* queue entry */
  10670         buf_pool = &buf->pools[buf_rqe_queue->pool_idx];
  10671         rval = 0;
  10672         soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_MIN_PRIQr,
  10673                           &rval, MIN_LIMITf,
  10674                           sal_ceil_func(buf_rqe_queue->guarantee, 8));
  10675         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_LIMIT_MIN_PRIQr(unit, idx, rval));
  10676 
  10677         rval = 0;
  10678         rval2 = 0;
  10679         rval3 = 0;
  10680         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr,
  10681                           &rval, SPIDf, buf_rqe_queue->pool_idx);
  10682 
  10683         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr,
  10684                           &rval, COLOR_LIMIT_DYNAMICf, (!lossless));
  10685         soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr,
  10686                           &rval3, SHARED_RED_LIMITf,
  10687                           lossless? (sal_ceil_func(buf_pool->total_rqe_entry,
  10688                           8)): 0);
  10689         soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr,
  10690                           &rval3, SHARED_YELLOW_LIMITf,
  10691                           lossless? (sal_ceil_func(buf_pool->total_rqe_entry,
  10692                           8)): 0);
  10693 
  10694         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr, &rval,
  10695                           LIMIT_ENABLEf, !lossless);
  10696         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr,
  10697                           &rval, DYNAMIC_ENABLEf, (!lossless));
  10698 
  10699         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_PRIQr, &rval2,
  10700                           SHARED_LIMITf,
  10701                           lossless? (sal_ceil_func(buf_pool->total_rqe_entry,
  10702                           8)): 8);
  10703         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_PRIQr, &rval2,
  10704                           RESET_OFFSETf, 1);
  10705 
  10706         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG1_PRIQr(unit, idx, rval));
  10707         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG_PRIQr(unit, idx, rval2));
  10708         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_LIMIT_COLOR_PRIQr(unit, idx, rval3));
  10709 
  10710         rval = 0;
  10711         soc_reg_field_set(unit, MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr,
  10712                           &rval, RESET_OFFSET_REDf,
  10713                           sal_ceil_func(default_mtu_cells, 8));
  10714         soc_reg_field_set(unit, MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr,
  10715                           &rval, RESET_OFFSET_YELLOWf,
  10716                           sal_ceil_func(default_mtu_cells, 8));
  10717         SOC_IF_ERROR_RETURN(
  10718                   WRITE_MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr(unit, idx, rval));
  10719 
  10720     }
  10721 
  10722     /* per pool RQE settings */
  10723     for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
  10724         buf_pool = &buf->pools[idx];
  10725         if (((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) ||
  10726             (buf_pool->total == 0)) {
  10727             continue;
  10728         }
  10729 
  10730         limit = swcfg->egr_shared_total;
  10731 
  10732         COMPILER_64_ZERO(rval64);
  10733         soc_reg64_field32_set(unit, MMU_THDR_DB_CONFIG_SPr,
  10734                               &rval64, SHARED_LIMITf, limit);
  10735         soc_reg64_field32_set(unit, MMU_THDR_DB_CONFIG_SPr, &rval64,
  10736             RESUME_LIMITf, sal_ceil_func((limit - (default_mtu_cells * 2)), 8));
  10737         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIG_SPr(unit, idx, rval64));
  10738 
  10739         rval = 0;
  10740         soc_reg_field_set(unit, MMU_THDR_DB_SP_SHARED_LIMITr, &rval,
  10741                           SHARED_RED_LIMITf,
  10742                           sal_ceil_func(limit, 8));
  10743         soc_reg_field_set(unit, MMU_THDR_DB_SP_SHARED_LIMITr, &rval,
  10744                           SHARED_YELLOW_LIMITf,
  10745                           sal_ceil_func(limit, 8));
  10746         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_SP_SHARED_LIMITr(unit, idx, rval));
  10747 
  10748         rval = 0;
  10749         soc_reg_field_set(unit, MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, &rval,
  10750                           RESUME_RED_LIMITf,
  10751                           sal_ceil_func((limit - (default_mtu_cells * 2)), 8));
  10752         soc_reg_field_set(unit, MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, &rval,
  10753                           RESUME_YELLOW_LIMITf,
  10754                           sal_ceil_func((limit - (default_mtu_cells * 2)), 8));
  10755         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr(unit,
  10756                                                                      idx, rval));
  10757 
  10758         rqlen = sal_ceil_func(buf_pool->total_rqe_entry, 8);
  10759         if (rqlen == 0) {
  10760             continue;
  10761         }
  10762 
  10763         rval = 0;
  10764         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_SPr, &rval,
  10765                           SHARED_LIMITf, rqlen);
  10766         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_SPr, &rval,
  10767                           RESUME_LIMITf, rqlen - 1);
  10768         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG_SPr(unit, idx, rval));
  10769 
  10770         rval = 0;
  10771         soc_reg_field_set(unit, MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr, &rval,
  10772                           SHARED_RED_LIMITf, rqlen);
  10773         soc_reg_field_set(unit, MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr, &rval,
  10774                           SHARED_YELLOW_LIMITf, rqlen);
  10775         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr(unit,
  10776                                                                      idx,
  10777                                                                      rval));
  10778 
  10779         rval = 0;
  10780         soc_reg_field_set(unit, MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr, &rval,
  10781                           RESUME_RED_LIMITf, rqlen - 1);
  10782         soc_reg_field_set(unit, MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr, &rval,
  10783                           RESUME_YELLOW_LIMITf, rqlen - 1);
  10784         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr(unit,
  10785                                                                      idx, rval));
  10786     }
  10787 
  10788 
  10789     /* Device level config setting */
  10790 #if 0
  10791     if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0)) {
  10792         SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval));
  10793         soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval,
  10794                           UC_MC_PORTSP_COMB_ACCT_ENABLEf, 1);
  10795         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval));
  10796     }
  10797 #endif
  10798     return SOC_E_NONE;
  10799 }
  10800 
  10801 STATIC int
  10802 _soc_td3_mmu_config_buf_set_hw(int unit, _soc_mmu_cfg_buf_t *buf,
  10803                                _soc_mmu_device_info_t *devcfg, int lossless,
  10804                                _soc_td3_mmu_sw_config_info_t *swcfg)
  10805 {
  10806     int port;
  10807 
  10808     SOC_IF_ERROR_RETURN
  10809         (_soc_td3_mmu_config_buf_set_hw_global(unit, buf, devcfg, lossless,
  10810                                                swcfg));
  10811 
  10812     PBMP_ALL_ITER(unit, port) {
  10813         SOC_IF_ERROR_RETURN
  10814             (_soc_td3_mmu_config_buf_set_hw_port(unit, port, buf, devcfg,
  10815                                                  lossless, swcfg));
  10816     }
  10817 
  10818     return SOC_E_NONE;
  10819 }
  10820 
  10821 int
  10822 soc_td3_mmu_config_init_port(int unit, int port)
  10823 {
  10824     int rv;
  10825     int lossless = 1;
  10826     _soc_mmu_cfg_buf_t *buf;
  10827     _soc_mmu_device_info_t devcfg;
  10828     _soc_td3_mmu_sw_config_info_t swcfg;
  10829 
  10830     buf = soc_mmu_cfg_alloc(unit);
  10831     if (!buf) {
  10832         return SOC_E_MEMORY;
  10833     }
  10834 
  10835     lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 0);
  10836 
  10837     _soc_td3_mmu_init_dev_config(unit, &devcfg, lossless);
  10838     _soc_td3_mmu_sw_info_config (unit, &swcfg, lossless);
  10839 
  10840 
  10841     /* Calculate the buf - global as well as per port
  10842      * but _soc_td3_mmu_config_buf_set_hw_port is only called
  10843      * for that port - since it is flex operation - we don't
  10844      * touch any other port */
  10845     _soc_td3_mmu_config_buf_phase1(unit, buf, &devcfg, &swcfg, lossless);
  10846 
  10847     if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) {
  10848         /* Override default config */
  10849         _soc_mmu_cfg_buf_read(unit, buf, &devcfg);
  10850     }
  10851     rv = _soc_mmu_cfg_buf_check(unit, buf, &devcfg);
  10852     if (SOC_FAILURE(rv)) {
  10853         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10854                 (BSL_META_U(unit,
  10855                             "MMU config: Use default setting\n")));
  10856         _soc_td3_mmu_config_buf_phase1(unit, buf, &devcfg, &swcfg, lossless);
  10857         SOC_IF_ERROR_RETURN
  10858             (_soc_mmu_cfg_buf_calculate(unit, buf, &devcfg));
  10859     }
  10860 
  10861     _soc_td3_mmu_config_buf_phase2(unit, buf, &devcfg, &swcfg, lossless);
  10862     /* Override default phase 2 config */
  10863     if (SOC_SUCCESS(rv)) {
  10864         if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) {
  10865             _soc_mmu_cfg_buf_read(unit, buf, &devcfg);
  10866         }
  10867     }
  10868     rv = _soc_td3_mmu_config_buf_set_hw_port(unit, port, buf, &devcfg,
  10869                                              lossless, &swcfg);
  10870 
  10871     soc_mmu_cfg_free(unit, buf);
  10872 
  10873     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10874                 (BSL_META_U(unit,
  10875                             "MMU THDI/THDO init done\n")));
  10876     return rv;
  10877 }
  10878 
  10879 /* Default MMU settings - Version 3.0 */
  10880 STATIC int
  10881 soc_td3_mmu_config_init(int unit, int test_only)
  10882 {
  10883     int rv;
  10884     int lossless = 1;
  10885     _soc_mmu_cfg_buf_t *buf;
  10886     _soc_mmu_device_info_t devcfg;
  10887     _soc_td3_mmu_sw_config_info_t swcfg;
  10888 
  10889     buf = soc_mmu_cfg_alloc(unit);
  10890     if (!buf) {
  10891         return SOC_E_MEMORY;
  10892     }
  10893 
  10894     lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 0);
  10895     SOC_INFO(unit).mmu_lossless = lossless;
  10896 
  10897     _soc_td3_mmu_init_dev_config(unit, &devcfg, lossless);
  10898     _soc_td3_mmu_sw_info_config (unit, &swcfg, lossless);
  10899 
  10900     _soc_td3_mmu_config_buf_phase1(unit, buf, &devcfg, &swcfg, lossless);
  10901     if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) {
  10902         /* Override default config */
  10903         _soc_mmu_cfg_buf_read(unit, buf, &devcfg);
  10904     }
  10905     rv = _soc_mmu_cfg_buf_check(unit, buf, &devcfg);
  10906     if (!test_only) {
  10907         if (SOC_FAILURE(rv)) {
  10908             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10909                         (BSL_META_U(unit,
  10910                                     "MMU config: Use default setting\n")));
  10911             _soc_td3_mmu_config_buf_phase1(unit, buf, &devcfg, &swcfg, lossless);
  10912             SOC_IF_ERROR_RETURN
  10913                 (_soc_mmu_cfg_buf_calculate(unit, buf, &devcfg));
  10914         }
  10915 
  10916         _soc_td3_mmu_config_buf_phase2(unit, buf, &devcfg, &swcfg, lossless);
  10917         /* Override default phase 2 config */
  10918         if (SOC_SUCCESS(rv)) {
  10919             if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) {
  10920                 _soc_mmu_cfg_buf_read(unit, buf, &devcfg);
  10921             }
  10922         }
  10923         rv = _soc_td3_mmu_config_buf_set_hw(unit, buf, &devcfg, lossless, &swcfg);
  10924     }
  10925 
  10926     soc_mmu_cfg_free(unit, buf);
  10927 
  10928     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10929                 (BSL_META_U(unit,
  10930                             "MMU THDI/THDO init done\n")));
  10931     return rv;
  10932 }
  10933 
  10934 STATIC int
  10935 _soc_trident3_mmu_init(int unit)
  10936 {
  10937     int port;
  10938     int enable = 1;
  10939     int test_only;
  10940     uint32 rval = 0;
  10941 
  10942 #ifdef BCM_WARM_BOOT_SUPPORT
  10943     if (SOC_WARM_BOOT(unit)) {
  10944     } else
  10945 #endif
  10946     {
  10947         test_only = (SAL_BOOT_XGSSIM) ? TRUE : FALSE;
  10948         SOC_IF_ERROR_RETURN(soc_td3_mmu_config_init(unit, test_only));
  10949 
  10950         PBMP_ALL_ITER(unit, port) {
  10951             _soc_td3_thdo_hw_set(unit, port, enable);
  10952         }
  10953     }
  10954 
  10955     /* enable WRED refresh */
  10956     SOC_IF_ERROR_RETURN(READ_WRED_REFRESH_CONTROLr(unit, &rval));
  10957     soc_reg_field_set(unit, WRED_REFRESH_CONTROLr, &rval,
  10958                       REFRESH_DISABLEf, 0);
  10959     SOC_IF_ERROR_RETURN(WRITE_WRED_REFRESH_CONTROLr(unit, rval));
  10960 
  10961     SOC_IF_ERROR_RETURN(soc_td3_post_mmu_init_update(unit));
  10962     return SOC_E_NONE;
  10963 }
  10964 
  10965 int
  10966 soc_trident3_age_timer_get(int unit, int *age_seconds, int *enabled)
  10967 {
  10968     soc_control_t *soc = SOC_CONTROL(unit);
  10969     *enabled = soc->l2x_age_pid != SAL_THREAD_ERROR &&
  10970                soc->l2x_age_enable ?
  10971                1 : 0;
  10972     *age_seconds = soc->l2x_age_pid != SAL_THREAD_ERROR &&
  10973                    soc->l2x_age_enable ?
  10974                    soc->l2x_age_interval : 0;
  10975     return SOC_E_NONE;
  10976 }
  10977 
  10978 int
  10979 soc_trident3_age_timer_max_get(int unit, int *max_seconds)
  10980 {
  10981     *max_seconds = 0x7fffffff;
  10982     return SOC_E_NONE;
  10983 }
  10984 
  10985 int
  10986 soc_trident3_age_timer_set(int unit, int age_seconds, int enable)
  10987 {
  10988     soc_control_t *soc = SOC_CONTROL(unit);
  10989     sal_usecs_t interval = soc->l2x_age_interval;
  10990 
  10991     if (soc->l2x_age_interval) {
  10992         if (!enable) {
  10993             soc->l2x_age_enable = 0;
  10994         } else {
  10995             if (age_seconds) {
  10996                 SOC_CONTROL_LOCK(unit);
  10997                 soc->l2x_age_interval = age_seconds;
  10998                 SOC_CONTROL_UNLOCK(unit);
  10999             }
  11000             soc->l2x_age_enable = 1;
  11001             if (interval != age_seconds) {
  11002                 sal_sem_give(soc->l2x_age_notify);
  11003             }
  11004         }
  11005     } else {
  11006         if (enable) {
  11007             soc->l2x_age_enable = 1;
  11008             SOC_IF_ERROR_RETURN
  11009                 (soc_th_l2_bulk_age_start(unit, age_seconds));
  11010         }
  11011     }
  11012 
  11013     return SOC_E_NONE;
  11014 }
  11015 
  11016 STATIC int
  11017 soc_trident3_oversub_group_find(int unit, soc_td3_port_lanes_t *lanes_ctrl)
  11018 {
  11019     soc_info_t *si = &SOC_INFO(unit);
  11020     soc_reg_t reg;
  11021     int port_base, phy_port_base, idb_port_base, mmu_port_base;
  11022     int port, mmu_port, id, inst;
  11023     uint32 rval, fval;
  11024     int pipe, group, slot, count, i;
  11025     int cur_ids[4], cur_ids_len;
  11026     int ids_len;
  11027     int slots[4], slots_len;
  11028     int speed_max, cur_speed_max;
  11029     static const soc_reg_t idb_grp_tbl_regs[] = {
  11030         IS_OVR_SUB_GRP0_TBLr, IS_OVR_SUB_GRP1_TBLr,
  11031         IS_OVR_SUB_GRP2_TBLr, IS_OVR_SUB_GRP3_TBLr,
  11032         IS_OVR_SUB_GRP4_TBLr, IS_OVR_SUB_GRP5_TBLr
  11033     };
  11034     static const soc_reg_t mmu_grp_tbl_regs[] = {
  11035         OVR_SUB_GRP0_TBLr, OVR_SUB_GRP1_TBLr,
  11036         OVR_SUB_GRP2_TBLr, OVR_SUB_GRP3_TBLr,
  11037         OVR_SUB_GRP4_TBLr, OVR_SUB_GRP5_TBLr
  11038     };
  11039 
  11040     port_base = lanes_ctrl->port_base;
  11041     phy_port_base = si->port_l2p_mapping[port_base];
  11042     idb_port_base = si->port_l2i_mapping[port_base];
  11043     mmu_port_base = si->port_p2m_mapping[phy_port_base];
  11044     pipe = si->port_pipe[port_base];
  11045 
  11046     /* Figure out the new speed group */
  11047     speed_max = 25000 * lanes_ctrl->lanes;
  11048     if (speed_max > si->port_speed_max[port_base]) {
  11049         speed_max = si->port_speed_max[port_base];
  11050     }
  11051     _soc_trident3_speed_to_ovs_class_mapping(unit, speed_max,
  11052                                              &lanes_ctrl->class);
  11053 
  11054     /* Figure out the current speed group */
  11055     cur_speed_max = 25000 * lanes_ctrl->cur_lanes;
  11056     if (cur_speed_max > si->port_speed_max[port_base]) {
  11057         cur_speed_max = si->port_speed_max[port_base];
  11058     }
  11059     _soc_trident3_speed_to_ovs_class_mapping(unit, cur_speed_max,
  11060                                              &lanes_ctrl->cur_class);
  11061 
  11062     /* Construct new and old idb port list for oversub group replacement */
  11063     cur_ids[0] = idb_port_base;
  11064     ids_len = cur_ids_len = 1;
  11065     if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  11066         /* idb port(s) to be removed */
  11067         for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11068             port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]];
  11069             cur_ids[1 + i] = si->port_l2i_mapping[port];
  11070         }
  11071         cur_ids_len += lanes_ctrl->phy_ports_len;
  11072     } else { /* idb port(s) to be added */
  11073         for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11074             port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]];
  11075         }
  11076         ids_len += lanes_ctrl->phy_ports_len;
  11077     }
  11078 
  11079     lanes_ctrl->idb_group = -1;
  11080     lanes_ctrl->idb_slots[0] = -1;
  11081     lanes_ctrl->cur_idb_slots[0] = -1;
  11082     for (group = 0; group < _OVS_GROUP_COUNT; group++) {
  11083         reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe];
  11084         SOC_IF_ERROR_RETURN
  11085             (soc_reg32_get(unit, reg, REG_PORT_ANY, group, &rval));
  11086         fval = soc_reg_field_get(unit, reg, rval, SPEEDf);
  11087         if (fval == 0) { /* unused idb port oversub group */
  11088             if (lanes_ctrl->idb_group == -1) {
  11089                 lanes_ctrl->idb_group = group;
  11090             }
  11091             continue;
  11092         } else if (fval == lanes_ctrl->class) {
  11093             if (lanes_ctrl->idb_slots[0] == -1) { /* hasn't found the group */
  11094                 /* Find slot(s) for new idb port oversub group */
  11095                 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe];
  11096                 count = _OVS_GROUP_TDM_LENGTH /
  11097                     (_TD3_PORTS_PER_PBLK / lanes_ctrl->lanes);
  11098                 slots_len = 0;
  11099                 for (slot = 0; slot < count; slot++) {
  11100                     SOC_IF_ERROR_RETURN
  11101                         (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval));
  11102                     if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) {
  11103                         continue;
  11104                     }
  11105                     slots[slots_len] = slot;
  11106                     slots_len++;
  11107                     if (slots_len == ids_len) {
  11108                         /* Enough free slots in an existing group */
  11109                         lanes_ctrl->idb_group = group;
  11110                         for (i = 0; i < slots_len; i++) {
  11111                             lanes_ctrl->idb_slots[i] = slots[i];
  11112                         }
  11113                         break;
  11114                     }
  11115                 }
  11116             }
  11117         } else if (fval == lanes_ctrl->cur_class) {
  11118             if (lanes_ctrl->cur_idb_slots[0] == -1) {
  11119                 /* Find slot(s) used by the currnet idb port oversub group */
  11120                 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe];
  11121                 count = _OVS_GROUP_TDM_LENGTH /
  11122                     (_TD3_PORTS_PER_PBLK / lanes_ctrl->cur_lanes);
  11123                 slots_len = 0;
  11124                 lanes_ctrl->cur_idb_empty = TRUE;
  11125                 for (slot = 0; slot < count; slot++) {
  11126                     SOC_IF_ERROR_RETURN
  11127                         (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval));
  11128                     id = soc_reg_field_get(unit, reg, rval, PORT_NUMf);
  11129                     if (id == 0x3f) {
  11130                         continue;
  11131                     }
  11132                     for (i = 0; i < cur_ids_len; i++) {
  11133                         if (id == cur_ids[i]) {
  11134                             slots[slots_len] = slot;
  11135                             slots_len++;
  11136                             break;
  11137                         }
  11138                     }
  11139                     if (i == cur_ids_len) {
  11140                         lanes_ctrl->cur_idb_empty = FALSE;
  11141                     } else if (slots_len == cur_ids_len) {
  11142                         lanes_ctrl->cur_idb_group = group;
  11143                         for (i = 0; i < slots_len; i++) {
  11144                             lanes_ctrl->cur_idb_slots[i] = slots[i];
  11145                         }
  11146                     }
  11147                     if (lanes_ctrl->cur_idb_slots[0] != -1 &&
  11148                         !lanes_ctrl->cur_idb_empty) {
  11149                         break;
  11150                     }
  11151                 }
  11152             }
  11153         }
  11154         if (lanes_ctrl->idb_slots[0] != -1 &&
  11155             lanes_ctrl->cur_idb_slots[0] != -1) {
  11156             break;
  11157         }
  11158     }
  11159 
  11160     if (lanes_ctrl->idb_group == -1) {
  11161         return SOC_E_FULL;
  11162     }
  11163 
  11164     /* Construct new and old mmu port list for oversub group replacement */
  11165     cur_ids[0] = mmu_port_base & 0x3f;
  11166     ids_len = cur_ids_len = 1;
  11167     if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  11168         /* mmu port(s) to be removed */
  11169         for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11170             mmu_port = si->port_p2m_mapping[lanes_ctrl->phy_ports[i]];
  11171             cur_ids[1 + i] = mmu_port & 0x3f;
  11172         }
  11173         cur_ids_len += lanes_ctrl->phy_ports_len;
  11174     } else { /* mmu port(s) to be added */
  11175         for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11176             mmu_port = si->port_p2m_mapping[lanes_ctrl->phy_ports[i]];
  11177         }
  11178         ids_len += lanes_ctrl->phy_ports_len;
  11179     }
  11180 
  11181     lanes_ctrl->mmu_group = -1;
  11182     lanes_ctrl->mmu_slots[0] = -1;
  11183     lanes_ctrl->cur_mmu_slots[0] = -1;
  11184     for (group = 0; group < _OVS_GROUP_COUNT; group++) {
  11185         reg = OVR_SUB_GRP_CFGr;
  11186         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  11187         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, group, &rval));
  11188         fval = soc_reg_field_get(unit, reg, rval, SPEEDf);
  11189         if (fval == 0) { /* unused mmu port oversub group */
  11190             if (lanes_ctrl->mmu_group == -1) {
  11191                 lanes_ctrl->mmu_group = group;
  11192             }
  11193             continue;
  11194         } else if (fval == lanes_ctrl->class) {
  11195             if (lanes_ctrl->mmu_slots[0] == -1) { /* hasn't found the group */
  11196                 /* Find slot(s) for new mmu port oversub group */
  11197                 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  11198                 reg = mmu_grp_tbl_regs[group];
  11199                 count = _OVS_GROUP_TDM_LENGTH /
  11200                     (_TD3_PORTS_PER_PBLK / lanes_ctrl->lanes);
  11201                 slots_len = 0;
  11202                 for (slot = 0; slot < count; slot++) {
  11203                     SOC_IF_ERROR_RETURN
  11204                         (soc_reg32_get(unit, reg, inst, slot, &rval));
  11205                     if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) {
  11206                         continue;
  11207                     }
  11208                     slots[slots_len] = slot;
  11209                     slots_len++;
  11210                     if (slots_len == ids_len) {
  11211                         /* Enough free slots in an existing group */
  11212                         lanes_ctrl->mmu_group = group;
  11213                         for (i = 0; i < slots_len; i++) {
  11214                             lanes_ctrl->mmu_slots[i] = slots[i];
  11215                         }
  11216                         break;
  11217                     }
  11218                 }
  11219             }
  11220         } else if (fval == lanes_ctrl->cur_class) {
  11221             if (lanes_ctrl->cur_mmu_slots[0] == -1) {
  11222                 /* Find slot(s) used by the currnet mmu port oversub group */
  11223                 reg = mmu_grp_tbl_regs[group];
  11224                 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  11225                 count = _OVS_GROUP_TDM_LENGTH /
  11226                     (_TD3_PORTS_PER_PBLK / lanes_ctrl->cur_lanes);
  11227                 slots_len = 0;
  11228                 lanes_ctrl->cur_mmu_empty = TRUE;
  11229                 for (slot = 0; slot < count; slot++) {
  11230                     SOC_IF_ERROR_RETURN
  11231                         (soc_reg32_get(unit, reg, inst, slot, &rval));
  11232                     id = soc_reg_field_get(unit, reg, rval, PORT_NUMf);
  11233                     if (id == 0x3f) {
  11234                         continue;
  11235                     }
  11236                     for (i = 0; i < cur_ids_len; i++) {
  11237                         if (id == cur_ids[i]) {
  11238                             slots[slots_len] = slot;
  11239                             slots_len++;
  11240                             break;
  11241                         }
  11242                     }
  11243                     if (i == cur_ids_len) {
  11244                         lanes_ctrl->cur_mmu_empty = FALSE;
  11245                     } else if (slots_len == cur_ids_len) {
  11246                         lanes_ctrl->cur_mmu_group = group;
  11247                         for (i = 0; i < slots_len; i++) {
  11248                             lanes_ctrl->cur_mmu_slots[i] = slots[i];
  11249                         }
  11250                     }
  11251                     if (lanes_ctrl->cur_mmu_slots[0] != -1 &&
  11252                         !lanes_ctrl->cur_mmu_empty) {
  11253                         break;
  11254                     }
  11255                 }
  11256             }
  11257         }
  11258         if (lanes_ctrl->mmu_slots[0] != -1 &&
  11259             lanes_ctrl->cur_mmu_slots[0] != -1) {
  11260             break;
  11261         }
  11262     }
  11263 
  11264     if (lanes_ctrl->mmu_group == -1) {
  11265         return SOC_E_FULL;
  11266     }
  11267 
  11268     return SOC_E_NONE;
  11269 }
  11270 
  11271 /*
  11272  * Function:
  11273  *      soc_trident3_port_lanes_validate
  11274  * Description:
  11275  *      Validate if the specified number of lanes can be configured on a port,
  11276  *      If the request can be done, fill in the control structure which will
  11277  *      be used by the routines programming the hardware.
  11278  * Parameters:
  11279  *      unit          - Device number
  11280  *      lanes_ctrl    - Control structure
  11281  *
  11282  * Each TSC can be configured into following 5 mode:
  11283  *   Lane number    0              1         2              3
  11284  *   ------------   -----------    --------  ------------   --------
  11285  *    single port   100G/40G       x         x              x
  11286  *      dual port   50G/d40G/20G   x         50G/d40G/20G   x
  11287  *   tri_023 port   50G/d40g/20G   x         25G/10G        25G/10G
  11288  *   tri_012 port   25G/10G        25G/10G   50G/d40G/20G   x
  11289  *      quad port   25G/10G        25G/10G   25G/10G        25G/10G
  11290  *
  11291  * (Note: All of the above apply to equivalent HG line rate speeds as well)
  11292  *
  11293  *          lanes                mode         valid lane index
  11294  *       ------------      ----------------   ----------------
  11295  *       new  current        new    current
  11296  *       ---  -------      -------  -------
  11297  * #1     4      1         single    quad            0
  11298  * #2     4      1         single   tri_012          0
  11299  * #3     4      2         single   tri_023          0
  11300  * #4     4      2         single    dual            0
  11301  * #5     2      1         tri_023   quad            0
  11302  * #6     2      1         tri_012   quad            2
  11303  * #7     2      1          dual    tri_023          2
  11304  * #8     2      1          dual    tri_012          0
  11305  * #9     2      4          dual    single           0
  11306  * #10    1      2         tri_023   dual            2
  11307  * #11    1      2         tri_012   dual            0
  11308  * #12    1      2          quad    tri_023          0
  11309  * #13    1      2          quad    tri_012          2
  11310  * #14    1      4          quad    single           0
  11311  * Following mode change requires 2 transition
  11312  *   - from single to tri_023: #9 + #10
  11313  *   - from single to tri_012: #9 + #11
  11314  * Following mode change are the result of lane change on multiple ports
  11315  *   - from quad to dual: #12 + #7 or #13 + #8
  11316  *   - from dual to quad: #10 + #12 or #11 + # 13
  11317  *   - from tri_023 to tri_012: #7 + #11 or #12 + #6
  11318  *   - from tri_012 to tri_023: #8 + #10 or #13 + #5
  11319  *
  11320  * Logical port number will stay the same after conversion, for example
  11321  *     converting single port to dual port, the logical port number of lane 0
  11322  *     will be changed.
  11323  */
  11324 int
  11325 soc_trident3_port_lanes_validate(int unit, soc_td3_port_lanes_t *lanes_ctrl)
  11326 {
  11327     soc_info_t *si = &SOC_INFO(unit);
  11328     int port_base, phy_port_base;
  11329     uint32 rval;
  11330     int i;
  11331 
  11332     /* Find physical and mmu port number for the specified port */
  11333     port_base = lanes_ctrl->port_base;
  11334     phy_port_base = si->port_l2p_mapping[port_base];
  11335     if (phy_port_base == -1) {
  11336         return SOC_E_PORT;
  11337     }
  11338     lanes_ctrl->oversub = SOC_PBMP_MEMBER(si->oversub_pbm, port_base);
  11339 
  11340     /* Find lane index for the specified port (base port) */
  11341     lanes_ctrl->bindex = SOC_PORT_BINDEX(unit, phy_port_base);
  11342 
  11343     /* Get the current mode */
  11344     SOC_IF_ERROR_RETURN(READ_CLPORT_MODE_REGr(unit, port_base, &rval));
  11345     lanes_ctrl->cur_mode = soc_reg_field_get(unit, CLPORT_MODE_REGr, rval,
  11346                                              XPORT0_CORE_PORT_MODEf);
  11347 
  11348     /* Figure out the current number of lanes */
  11349     switch (lanes_ctrl->cur_mode) {
  11350     case SOC_TD3_PORT_MODE_QUAD:
  11351         lanes_ctrl->cur_lanes = 1;
  11352         break;
  11353     case SOC_TD3_PORT_MODE_TRI_012:
  11354         lanes_ctrl->cur_lanes = lanes_ctrl->bindex == 0 ? 1 : 2;
  11355         break;
  11356     case SOC_TD3_PORT_MODE_TRI_023:
  11357         lanes_ctrl->cur_lanes = lanes_ctrl->bindex == 0 ? 2 : 1;
  11358         break;
  11359     case SOC_TD3_PORT_MODE_DUAL:
  11360         lanes_ctrl->cur_lanes = 2;
  11361         break;
  11362     case SOC_TD3_PORT_MODE_SINGLE:
  11363         lanes_ctrl->cur_lanes = 4;
  11364         break;
  11365     default:
  11366         return SOC_E_FAIL;
  11367     }
  11368     /* Validate new number of lanes */
  11369     if (lanes_ctrl->lanes == 4 || lanes_ctrl->cur_lanes == 4) {
  11370         if (lanes_ctrl->bindex & 0x3) {
  11371             return SOC_E_PARAM;
  11372         }
  11373     } else if (lanes_ctrl->lanes == 2 || lanes_ctrl->cur_lanes == 2) {
  11374         if (lanes_ctrl->bindex & 0x1) {
  11375             return SOC_E_PARAM;
  11376         }
  11377     } else if (lanes_ctrl->lanes != 1) {
  11378         return SOC_E_PARAM;
  11379     }
  11380 
  11381     /* No change to number of lanes */
  11382     if (lanes_ctrl->lanes == lanes_ctrl->cur_lanes) {
  11383         return SOC_E_NONE;
  11384     }
  11385 
  11386     if (lanes_ctrl->oversub) {
  11387         SOC_IF_ERROR_RETURN(soc_trident3_oversub_group_find(unit, lanes_ctrl));
  11388     }
  11389 
  11390     /* Figure out new mode */
  11391     if (lanes_ctrl->lanes == 4) {
  11392         lanes_ctrl->mode = 4;
  11393     } else if (lanes_ctrl->lanes == 2) {
  11394         if (lanes_ctrl->cur_mode == SOC_TD3_PORT_MODE_QUAD) {
  11395             lanes_ctrl->mode = lanes_ctrl->bindex == 0 ?
  11396                 SOC_TD3_PORT_MODE_TRI_023 : SOC_TD3_PORT_MODE_TRI_012;
  11397         } else {
  11398             lanes_ctrl->mode = SOC_TD3_PORT_MODE_DUAL;
  11399         }
  11400     } else{
  11401         if (lanes_ctrl->cur_mode == SOC_TD3_PORT_MODE_DUAL) {
  11402             lanes_ctrl->mode = lanes_ctrl->bindex == 0 ?
  11403                 SOC_TD3_PORT_MODE_TRI_012 : SOC_TD3_PORT_MODE_TRI_023;
  11404         } else {
  11405             lanes_ctrl->mode = SOC_TD3_PORT_MODE_QUAD;
  11406         }
  11407     }
  11408 
  11409     lanes_ctrl->phy_ports_len = 0;
  11410     if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  11411         /* Figure out which port(s) to be removed */
  11412         if (lanes_ctrl->lanes == 4) {
  11413             if (lanes_ctrl->cur_mode == SOC_TD3_PORT_MODE_TRI_012 ||
  11414                 lanes_ctrl->cur_mode == SOC_TD3_PORT_MODE_QUAD) {
  11415                 if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
  11416                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  11417                         phy_port_base + 1;
  11418                 }
  11419             }
  11420             if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
  11421                 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  11422                                       phy_port_base + 2;
  11423             }
  11424             if (lanes_ctrl->cur_mode == SOC_TD3_PORT_MODE_TRI_023 ||
  11425                 lanes_ctrl->cur_mode == SOC_TD3_PORT_MODE_QUAD) {
  11426                 if (si->port_p2l_mapping[phy_port_base + 3] != -1) {
  11427                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  11428                         phy_port_base + 3;
  11429                 }
  11430             }
  11431         } else {
  11432             if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
  11433                 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  11434                                       phy_port_base + 1;
  11435             }
  11436         }
  11437     } else { /* Figure out which port(s) to be added */
  11438         if (lanes_ctrl->lanes == 2) {
  11439             if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
  11440                 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  11441                                       phy_port_base + 2;
  11442             }
  11443         } else {
  11444             if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
  11445                 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  11446                     phy_port_base + 1;
  11447             }
  11448             if (lanes_ctrl->cur_mode == SOC_TD3_PORT_MODE_SINGLE) {
  11449                 if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
  11450                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  11451                         phy_port_base + 2;
  11452                 }
  11453                 if (si->port_p2l_mapping[phy_port_base + 3] != -1) {
  11454                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  11455                         phy_port_base + 3;
  11456                 }
  11457             }
  11458         }
  11459     }
  11460 
  11461     if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  11462         static char *mode_name[] = {
  11463             "QUAD", "TRI_012", "TRI_023", "DUAL", "SINGLE"
  11464         };
  11465         LOG_CLI((BSL_META_U(unit,
  11466                             "port %d physical port %d bindex %d\n"),
  11467                  port_base, phy_port_base, lanes_ctrl->bindex));
  11468         LOG_CLI((BSL_META_U(unit,
  11469                             "  mode (new:%s cur:%s) lanes (new:%d cur:%d)\n"),
  11470                  mode_name[lanes_ctrl->mode],
  11471                  mode_name[lanes_ctrl->cur_mode],
  11472                  lanes_ctrl->lanes, lanes_ctrl->cur_lanes));
  11473         for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11474             LOG_CLI((BSL_META_U(unit,
  11475                                 "  %s physical port %d (port %d)\n"),
  11476                      lanes_ctrl->lanes > lanes_ctrl->cur_lanes ?
  11477                      "del" : "add",
  11478                      lanes_ctrl->phy_ports[i],
  11479                      si->port_p2l_mapping[lanes_ctrl->phy_ports[i]]));
  11480         }
  11481         if (lanes_ctrl->idb_group != -1) {
  11482             LOG_CLI((BSL_META_U(unit,
  11483                                 "new idb group %d slot %d"),
  11484                      lanes_ctrl->idb_group, lanes_ctrl->idb_slots[0]));
  11485             if (lanes_ctrl->lanes < lanes_ctrl->cur_lanes &&
  11486                 lanes_ctrl->idb_slots[0] != -1) {
  11487                 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11488                     LOG_CLI((BSL_META_U(unit,
  11489                                         " slot %d"), lanes_ctrl->idb_slots[i]));
  11490                 }
  11491             }
  11492             LOG_CLI((BSL_META_U(unit,
  11493                                 "\n")));
  11494         }
  11495         LOG_CLI((BSL_META_U(unit,
  11496                             "cur idb group %d slot %d"),
  11497                  lanes_ctrl->cur_idb_group, lanes_ctrl->cur_idb_slots[0]));
  11498         if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  11499             /* port(s) to be removed */
  11500             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11501                 LOG_CLI((BSL_META_U(unit,
  11502                                     " slot %d"), lanes_ctrl->idb_slots[i]));
  11503             }
  11504         }
  11505         LOG_CLI((BSL_META_U(unit,
  11506                             "\n")));
  11507 
  11508         if (lanes_ctrl->mmu_group != -1) {
  11509             LOG_CLI((BSL_META_U(unit,
  11510                                 "new mmu group %d slot %d"),
  11511                      lanes_ctrl->mmu_group, lanes_ctrl->mmu_slots[0]));
  11512             if (lanes_ctrl->lanes < lanes_ctrl->cur_lanes &&
  11513                 lanes_ctrl->mmu_slots[0] != -1) {
  11514                 /* port(s) to be added */
  11515                 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11516                     LOG_CLI((BSL_META_U(unit,
  11517                                         " slot %d"), lanes_ctrl->mmu_slots[i]));
  11518                 }
  11519             }
  11520             LOG_CLI((BSL_META_U(unit,
  11521                                 "\n")));
  11522         }
  11523         LOG_CLI((BSL_META_U(unit,
  11524                             "cur mmu group %d slot %d"),
  11525                  lanes_ctrl->cur_mmu_group, lanes_ctrl->cur_mmu_slots[0]));
  11526         if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  11527             /* port(s) to be removed */
  11528             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11529                 LOG_CLI((BSL_META_U(unit,
  11530                                     " slot %d"), lanes_ctrl->mmu_slots[i]));
  11531             }
  11532         }
  11533         LOG_CLI((BSL_META_U(unit,
  11534                             "\n")));
  11535     }
  11536 
  11537     return SOC_E_NONE;
  11538 }
  11539 
  11540 soc_error_t
  11541 soc_td3_granular_speed_get(int unit, soc_port_t port, int *speed)
  11542 {
  11543     uint32 fval;
  11544     egr_mmu_cell_credit_entry_t credit_entry;
  11545 
  11546     SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ANY,
  11547                         SOC_INFO(unit).port_l2p_mapping[port], &credit_entry));
  11548     fval = soc_EGR_MMU_CELL_CREDITm_field32_get(unit, &credit_entry, CREDITf);
  11549 
  11550     SOC_IF_ERROR_RETURN(soc_td3_port_asf_mmu_cell_credit_to_speed(unit,
  11551                             port, (uint8) fval, speed));
  11552     return SOC_E_NONE;
  11553 }
  11554 
  11555 int soc_td3_mmu_traffic_ctrl_size(int unit, int *req_scache_size)
  11556 {
  11557     *req_scache_size += sizeof(_soc_td3_mmu_traffic_ctrl_t);
  11558 
  11559     return SOC_E_NONE;
  11560 }
  11561 
  11562 int soc_td3_mmu_traffic_ctrl_wb_sync(int unit, uint8 **scache_ptr)
  11563 {
  11564     _soc_td3_mmu_traffic_ctrl_t *mmu_traffic_ctrl_scache_p;
  11565     _soc_td3_mmu_traffic_ctrl_t *mmu_traffic_ctrl;
  11566 
  11567     mmu_traffic_ctrl_scache_p =
  11568         (_soc_td3_mmu_traffic_ctrl_t *)(*scache_ptr);
  11569 
  11570     mmu_traffic_ctrl = _soc_td3_mmu_traffic_ctrl[unit];
  11571     if (mmu_traffic_ctrl == NULL || mmu_traffic_ctrl_scache_p == NULL) {
  11572         return SOC_E_NONE;
  11573     }
  11574     sal_memcpy(mmu_traffic_ctrl_scache_p, mmu_traffic_ctrl,
  11575                sizeof(_soc_td3_mmu_traffic_ctrl_t));
  11576     mmu_traffic_ctrl_scache_p++;
  11577 
  11578     *scache_ptr = (uint8 *)mmu_traffic_ctrl_scache_p;
  11579 
  11580     return SOC_E_NONE;
  11581 }
  11582 
  11583 int soc_td3_mmu_traffic_ctrl_wb_restore(int unit, uint8 **scache_ptr)
  11584 {
  11585     _soc_td3_mmu_traffic_ctrl_t *mmu_traffic_ctrl_scache_p;
  11586     _soc_td3_mmu_traffic_ctrl_t *mmu_traffic_ctrl;
  11587 
  11588     mmu_traffic_ctrl_scache_p =
  11589         (_soc_td3_mmu_traffic_ctrl_t *)(*scache_ptr);
  11590 
  11591     mmu_traffic_ctrl = _soc_td3_mmu_traffic_ctrl[unit];
  11592     if (mmu_traffic_ctrl == NULL || mmu_traffic_ctrl_scache_p == NULL) {
  11593         return SOC_E_NONE;
  11594     }
  11595     sal_memcpy(mmu_traffic_ctrl, mmu_traffic_ctrl_scache_p,
  11596                sizeof(_soc_td3_mmu_traffic_ctrl_t));
  11597     mmu_traffic_ctrl_scache_p++;
  11598 
  11599     *scache_ptr = (uint8 *)mmu_traffic_ctrl_scache_p;
  11600 
  11601     return SOC_E_NONE;
  11602 }
  11603 
  11604 /*
  11605  * Function:
  11606  *      _soc_td3_port_thdo_rx_enable_set
  11607  * Purpose:
  11608  *     enable/disable the traffic to the port according to
  11609  *     different callers.
  11610  *  the traffic to the port can be enabled only if all of the callers
  11611  *  are to enable it.
  11612  * Parameters:
  11613  *     unit                - (IN) unit number
  11614  *     port                - (IN) local port
  11615  *     enable              - (IN) enable/disable the traffic to the port.
  11616  *     flag                - (IN) different callers.
  11617  * Returns:
  11618  *     BCM_E_XXX
  11619  */
  11620 STATIC int
  11621 _soc_td3_port_thdo_rx_enable_set(int unit, soc_port_t port,
  11622                                  int enable, uint8 flag)
  11623 {
  11624     int   rv = SOC_E_NONE;
  11625     uint8 *thdo_drop_bmp;
  11626     _soc_td3_mmu_traffic_ctrl_t *mmu_traffic_ctrl;
  11627 
  11628     FWD_CTRL_LOCK(unit);
  11629 
  11630     mmu_traffic_ctrl = _soc_td3_mmu_traffic_ctrl[unit];
  11631     if (mmu_traffic_ctrl ==  NULL) {
  11632         FWD_CTRL_UNLOCK(unit);
  11633         return SOC_E_INIT;
  11634     }
  11635     LOG_INFO(BSL_LS_SOC_MMU,
  11636              (BSL_META_UP(unit, port,
  11637                           "[SET]MMU Tx enable set: %d, flag: 0x%02x.\n"),
  11638                           enable, flag));
  11639 
  11640     thdo_drop_bmp = &(mmu_traffic_ctrl->thdo_drop_bmp[port]);
  11641 
  11642     if (!enable) {
  11643         if (*thdo_drop_bmp & flag) {
  11644             /*self if already in thdo drop. No HW Op.*/
  11645         } else {
  11646             if (*thdo_drop_bmp == 0) {
  11647                 rv = _soc_td3_thdo_hw_set(unit, port, enable);
  11648                 if (SOC_FAILURE(rv)) {
  11649                     LOG_ERROR(BSL_LS_SOC_COMMON,
  11650                               (BSL_META_U(unit,
  11651                                           "Clear the registers fail.\n")));
  11652                     FWD_CTRL_UNLOCK(unit);
  11653                     return rv;
  11654                 }
  11655             }
  11656         }
  11657 
  11658         *thdo_drop_bmp |= flag;
  11659     } else {
  11660         if ((*thdo_drop_bmp != 0) && (*thdo_drop_bmp != flag)) {
  11661             /*other callers are in thdo drop. No HW Op.*/
  11662         } else {
  11663             /*Ok, only self is in thdo drop, enbable it*/
  11664             rv = _soc_td3_thdo_hw_set(unit, port, enable);
  11665             if (SOC_FAILURE(rv)) {
  11666                 LOG_ERROR(BSL_LS_SOC_COMMON,
  11667                           (BSL_META_U(unit,
  11668                                       "Set the registers fail.\n")));
  11669                 FWD_CTRL_UNLOCK(unit);
  11670                 return rv;
  11671             }
  11672         }
  11673 
  11674         *thdo_drop_bmp &= ~flag;
  11675     }
  11676 
  11677     FWD_CTRL_UNLOCK(unit);
  11678 
  11679     LOG_INFO(BSL_LS_SOC_MMU,
  11680              (BSL_META_UP(unit, port,
  11681                           "[SET]MMU Tx drop bmp: 0x%02x.\n"),
  11682                           *thdo_drop_bmp));
  11683     return rv;
  11684 }
  11685 
  11686 /*
  11687  * Function:
  11688  *     _soc_td3_port_thdo_rx_enable_get
  11689  * Purpose:
  11690  *     Get port traffic enqueue status.
  11691  * Parameters:
  11692  *     unit                - (IN) unit number
  11693  *     port                - (IN) local port
  11694  *     enable              - (OUT) traffic to the port status.
  11695  *                                 False if UC/MC is disabled.
  11696  * Returns:
  11697  *     BCM_E_XXX
  11698  */
  11699 STATIC int
  11700 _soc_td3_port_thdo_rx_enable_get(int unit, soc_port_t port,
  11701                                  int *enable)
  11702 {
  11703     int rv = SOC_E_NONE;
  11704 
  11705     rv = _soc_td3_thdo_hw_get(unit, port, enable);
  11706     LOG_INFO(BSL_LS_SOC_MMU,
  11707              (BSL_META_UP(unit, port,
  11708                           "[GET]MMU Tx drop bmp: 0x%02x, enable status: %d.\n"),
  11709                           _soc_td3_mmu_traffic_ctrl[unit]->thdo_drop_bmp[port],
  11710                           *enable));
  11711 
  11712     return rv;
  11713 }
  11714 
  11715 /*
  11716  * Function:
  11717  *     soc_td3_port_mmu_rx_enable_set
  11718  * Purpose:
  11719  *     enable/disable mmu rx traffic from the gport.
  11720  * Parameters:
  11721  *     unit       - (IN) unit number
  11722  *     port       - (IN) PORT identifier
  11723  *     enable     - (IN) enable/disable
  11724  * Returns:
  11725  *     BCM_E_XXX
  11726  */
  11727 int
  11728 soc_td3_port_mmu_rx_enable_set(int unit, soc_port_t port,
  11729                                int enable)
  11730 {
  11731     uint32 rval;
  11732 
  11733     /* Disable/Enable INPUT_PORT_RX to the port */
  11734     SOC_IF_ERROR_RETURN
  11735         (soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr,
  11736                        port, 0, &rval));
  11737 
  11738     if (!enable) {
  11739         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
  11740                           INPUT_PORT_RX_ENABLEf, 0);
  11741     } else {
  11742         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
  11743                           INPUT_PORT_RX_ENABLEf, 1);
  11744     }
  11745 
  11746     SOC_IF_ERROR_RETURN
  11747         (soc_reg32_set(unit, THDI_INPUT_PORT_XON_ENABLESr,
  11748                        port, 0, rval));
  11749     LOG_INFO(BSL_LS_SOC_MMU,
  11750              (BSL_META_UP(unit, port,
  11751                           "[SET]MMU Rx enable: %d.\n"),
  11752                           enable));
  11753 
  11754     return SOC_E_NONE;
  11755 }
  11756 
  11757 /*
  11758  * Function:
  11759  *     soc_td3_port_mmu_rx_enable_get
  11760  * Purpose:
  11761  *     Get status of mmu rx traffic from the gport.
  11762  * Parameters:
  11763  *     unit       - (IN) unit number
  11764  *     port       - (IN) PORT identifier
  11765  *     enable     - (OUT) enable/disable
  11766  * Returns:
  11767  *     BCM_E_XXX
  11768  */
  11769 int
  11770 soc_td3_port_mmu_rx_enable_get(int unit, soc_port_t port,
  11771                                int *enable)
  11772 {
  11773     uint32 rval;
  11774 
  11775     /* Disable/Enable INPUT_PORT_RX to the port */
  11776     SOC_IF_ERROR_RETURN
  11777         (soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr,
  11778                        port, 0, &rval));
  11779 
  11780     if (enable != NULL) {
  11781         *enable = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval,
  11782                                     INPUT_PORT_RX_ENABLEf);
  11783         LOG_INFO(BSL_LS_SOC_MMU,
  11784              (BSL_META_UP(unit, port,
  11785                           "[GET]MMU Rx enable status: %d.\n"),
  11786                           *enable));
  11787     }
  11788 
  11789     return SOC_E_NONE;
  11790 }
  11791 
  11792 int
  11793 soc_td3_port_traffic_egr_enable_set(int unit, soc_port_t port,
  11794                                int enable)
  11795 {
  11796     return _soc_td3_port_thdo_rx_enable_set(unit, port, enable,
  11797                                             PORT_TX_EN_CTRL);
  11798 }
  11799 
  11800 int
  11801 soc_td3_port_mmu_tx_enable_set(int unit, soc_port_t port,
  11802                                int enable)
  11803 {
  11804     return _soc_td3_port_thdo_rx_enable_set(unit, port, enable,
  11805                                             MMU_TRAFFIC_EN_CTRL);
  11806 }
  11807 
  11808 int
  11809 soc_td3_port_mmu_tx_enable_get(int unit, soc_port_t port,
  11810                                int *enable)
  11811 {
  11812     return _soc_td3_port_thdo_rx_enable_get(unit, port, enable);
  11813 }
  11814 
  11815 void
  11816 soc_trident3_temperature_intr(void *unit_vp, void *d1, void *d2,
  11817                               void *d3, void *d4)
  11818 {
  11819     uint32 rval, trval;
  11820     int i, rv, unit = PTR_TO_INT(unit_vp);
  11821     const soc_reg_t *pvtmon_result_register=NULL;
  11822     int num_entries_out;
  11823 #ifdef BCM_MAVERICK2_SUPPORT
  11824     if (SOC_IS_MAVERICK2(unit)) {
  11825         pvtmon_result_register = &pvtmon_result_reg_mv2[0];
  11826         num_entries_out = COUNTOF(pvtmon_result_reg_mv2);
  11827     } else
  11828 #endif
  11829     {
  11830         pvtmon_result_register = &pvtmon_result_reg[0];
  11831         num_entries_out = COUNTOF(pvtmon_result_reg);
  11832     }
  11833 
  11834 
  11835     if ((rv = READ_TOP_PVTMON_INTR_STATUSr(unit, &rval)) != SOC_E_NONE) {
  11836         LOG_ERROR(BSL_LS_SOC_COMMON,
  11837                   (BSL_META_U(unit,
  11838                               "TD3 Temp Intr, Reg access error.\n")));
  11839     }
  11840     LOG_ERROR(BSL_LS_SOC_COMMON,
  11841               (BSL_META_U(unit,
  11842                           "High temp interrupt: 0x%08x\n"), rval));
  11843     /* Raise event to app for it to take further graceful actions */
  11844     for (i = 0; i < num_entries_out; i++) {
  11845         if (i & soc_td3_temp_mon_mask[unit]) {
  11846             if ((rv = soc_reg32_get(unit, pvtmon_result_register[i], REG_PORT_ANY, 0,
  11847                                     &trval)) != SOC_E_NONE) {
  11848                 LOG_ERROR(BSL_LS_SOC_COMMON,
  11849                           (BSL_META_U(unit,
  11850                                       "TD3 Temp Intr, Reg access error.\n")));
  11851             }
  11852             trval = soc_reg_field_get(unit, pvtmon_result_register[i], trval,
  11853                                       PVT_DATAf);
  11854             /* Convert data to temperature.
  11855              * temp = 434.1-(data*0.5350) = (4341000-(trval*5350))/1000;
  11856              * Note: Since this is a high temp interrupt we can safely assume
  11857              * that this will end up being a +ive value.
  11858              */
  11859             trval = (4341000-(trval*5350))/1000;
  11860 
  11861             LOG_ERROR(BSL_LS_SOC_COMMON,
  11862                       (BSL_META_U(unit,
  11863                                   "TempMon %d: %d deg C.\n"), i, trval));
  11864             (void)soc_event_generate(unit, SOC_SWITCH_EVENT_ALARM,
  11865                                      SOC_SWITCH_EVENT_ALARM_HIGH_TEMP, i, trval);
  11866         }
  11867     }
  11868     /* Optionally hold system in reset.
  11869      * Note: The main intention is to stop the chip from getting fried and halt
  11870      *       all schan accesses as the h/w will not respond anymore.
  11871      *       We are not implementing a gracefull recovery, the unit needs to be
  11872      *       rebooted after this.
  11873      */
  11874     if (soc_property_get(unit, "temp_monitor_shutdown", 1)) {
  11875         if ((rv = WRITE_TOP_PVTMON_INTR_MASKr(unit, 0)) != SOC_E_NONE) {
  11876             LOG_ERROR(BSL_LS_SOC_COMMON,
  11877                       (BSL_META_U(unit,
  11878                                   "TH Temp Intr, Reg access error.\n")));
  11879         }
  11880         if ((rv = WRITE_TOP_SOFT_RESET_REGr(unit, 0)) != SOC_E_NONE) {
  11881             LOG_ERROR(BSL_LS_SOC_COMMON,
  11882                       (BSL_META_U(unit,
  11883                                   "TH Temp Intr, Reg access error.\n")));
  11884         }
  11885         if ((rv = READ_TOP_SOFT_RESET_REG_2r(unit, &rval)) != SOC_E_NONE) {
  11886             LOG_ERROR(BSL_LS_SOC_COMMON,
  11887                       (BSL_META_U(unit,
  11888                                   "TH Temp Intr, Reg access error.\n")));
  11889         }
  11890         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL0_RST_Lf,
  11891                           0);
  11892         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL1_RST_Lf,
  11893                           0);
  11894         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL2_RST_Lf,
  11895                           0);
  11896         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL3_RST_Lf,
  11897                           0);
  11898         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_TS_PLL_RST_Lf,
  11899                           1);
  11900         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL0_RST_Lf,
  11901                           0);
  11902         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL1_RST_Lf,
  11903                           0);
  11904         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf, 1);
  11905         if ((rv = WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)) != SOC_E_NONE) {
  11906             LOG_ERROR(BSL_LS_SOC_COMMON,
  11907                       (BSL_META_U(unit,
  11908                                   "TH Temp Intr, Reg access error.\n")));
  11909         }
  11910         if ((rv = WRITE_TOP_SOFT_RESET_REG_3r(unit, 0)) != SOC_E_NONE) {
  11911             LOG_ERROR(BSL_LS_SOC_COMMON,
  11912                       (BSL_META_U(unit,
  11913                                   "TH Temp Intr, Reg access error.\n")));
  11914         }
  11915 
  11916         /* Stop all schan transactions on this unit */
  11917 #ifdef  INCLUDE_I2C
  11918         if ((rv = soc_i2c_detach(unit)) != SOC_E_NONE) {
  11919             LOG_ERROR(BSL_LS_SOC_COMMON,
  11920                       (BSL_META_U(unit,
  11921                                   "TH Temp Intr, i2c detach error.\n")));
  11922         }
  11923 #endif
  11924         if (!SOC_IS_RCPU_ONLY(unit)) {
  11925             /* Free up DMA memory */
  11926             if ((rv = soc_dma_detach(unit)) != SOC_E_NONE) {
  11927                 LOG_ERROR(BSL_LS_SOC_COMMON,
  11928                           (BSL_META_U(unit,
  11929                                       "TH Temp Intr, dma detach error.\n")));
  11930             }
  11931         }
  11932         if ((rv = soc_mem_scan_stop(unit)) != SOC_E_NONE) {
  11933             LOG_ERROR(BSL_LS_SOC_COMMON,
  11934                       (BSL_META_U(unit,
  11935                                   "TH Temp Intr, mem scan stop error.\n")));
  11936         }
  11937         /* Terminate counter module */
  11938         if ((rv = soc_counter_stop(unit)) != SOC_E_NONE) {
  11939             LOG_ERROR(BSL_LS_SOC_COMMON,
  11940                       (BSL_META_U(unit,
  11941                                   "TH Temp Intr, counter stop error.\n")));
  11942         }
  11943         if (SOC_SBUSDMA_DM_INFO(unit)) {
  11944             if ((rv = soc_sbusdma_desc_detach(unit)) != SOC_E_NONE) {
  11945                 LOG_ERROR(BSL_LS_SOC_COMMON,
  11946                           (BSL_META_U(unit,
  11947                                       "TH Temp Intr, sbusdma stop error.\n")));
  11948             }
  11949         }
  11950         if (soc_feature(unit, soc_feature_arl_hashed)) {
  11951             /* Stop L2X thread */
  11952             if ((rv = soc_l2x_stop(unit)) != SOC_E_NONE) {
  11953                 LOG_ERROR(BSL_LS_SOC_COMMON,
  11954                           (BSL_META_U(unit,
  11955                                       "TH Temp Intr, L2x stop error.\n")));
  11956             }
  11957 
  11958         }
  11959         if ((rv = soc_th_l2_bulk_age_stop(unit)) != SOC_E_NONE) {
  11960             LOG_ERROR(BSL_LS_SOC_COMMON,
  11961                       (BSL_META_U(unit,
  11962                                   "TH Temp Intr, L2 age stop error.\n")));
  11963         }
  11964         /* Disable all interrupts */
  11965 #ifdef BCM_CMICX_SUPPORT
  11966     if (soc_feature(unit, soc_feature_cmicx)) {
  11967         
  11968     }
  11969 #endif
  11970         SCHAN_LOCK(unit);
  11971         /* Clear all outstanding DPCs owned by this unit */
  11972         sal_dpc_cancel(INT_TO_PTR(unit));
  11973         LOG_ERROR(BSL_LS_SOC_COMMON,
  11974                   (BSL_META_U(unit,
  11975                               "\nReboot the system..")));
  11976     }
  11977 }
  11978 
  11979 int
  11980 soc_trident3_temperature_monitor_get(int unit, int temperature_max,
  11981     soc_switch_temperature_monitor_t *temperature_array, int *temperature_count)
  11982 {
  11983     soc_reg_t reg;
  11984     int index;
  11985     uint32 rval;
  11986     int fval, cur, peak;
  11987     int num_entries_out;
  11988     const soc_reg_t *pvtmon_result_register=NULL;
  11989 #ifdef BCM_MAVERICK2_SUPPORT
  11990     if (SOC_IS_MAVERICK2(unit)) {
  11991         pvtmon_result_register = &pvtmon_result_reg_mv2[0];
  11992         if (COUNTOF(pvtmon_result_reg_mv2) > temperature_max) {
  11993             num_entries_out = temperature_max;
  11994         } else {
  11995             num_entries_out = COUNTOF(pvtmon_result_reg_mv2);
  11996         }
  11997     } else
  11998 #endif
  11999     {
  12000         pvtmon_result_register = &pvtmon_result_reg[0];
  12001         if (COUNTOF(pvtmon_result_reg) > temperature_max) {
  12002             num_entries_out = temperature_max;
  12003         } else {
  12004             num_entries_out = COUNTOF(pvtmon_result_reg);
  12005         }
  12006     }
  12007     if (temperature_count) {
  12008         *temperature_count = 0;
  12009     }
  12010     /* SDK-125480 temperature reading for VTMON 11
  12011      *  Assert TOP_AVS_RST_L.
  12012      */
  12013     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
  12014     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
  12015                       TOP_AVS_RST_Lf, 0);
  12016     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
  12017 
  12018     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_3r(unit, &rval));
  12019     if ((soc_reg_field_get(unit, TOP_PVTMON_CTRL_3r, rval, PVTMON_RESET_Nf) == 0) ||
  12020         (soc_reg_field_get(unit, TOP_PVTMON_CTRL_3r, rval, PVTMON_SELECTf) != 0)) {
  12021         soc_reg_field_set(unit, TOP_PVTMON_CTRL_3r, &rval, PVTMON_RESET_Nf, 0);
  12022         SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_3r(unit, rval));
  12023         soc_reg_field_set(unit, TOP_PVTMON_CTRL_3r, &rval, PVTMON_RESET_Nf, 1);
  12024         soc_reg_field_set(unit, TOP_PVTMON_CTRL_3r, &rval, PVTMON_SELECTf, 0);
  12025         SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_3r(unit, rval));
  12026         sal_usleep(1000);
  12027     }
  12028 
  12029     for (index = 0; index < num_entries_out; index++) {
  12030         reg = pvtmon_result_register[index];
  12031         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
  12032 
  12033         fval = soc_reg_field_get(unit, reg, rval, PVT_DATAf);
  12034         cur = (4341000-(fval*5350))/1000;
  12035 
  12036         fval = soc_reg_field_get(unit, reg, rval, MIN_PVT_DATAf);
  12037         peak = (4341000-(fval*5350))/1000;
  12038 
  12039         if (temperature_array) {
  12040             (temperature_array + index)->curr = cur;
  12041             (temperature_array + index)->peak = peak;
  12042         }
  12043     }
  12044 
  12045     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
  12046     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
  12047                       TOP_PVT_MON_MIN_RST_Lf, 0);
  12048     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
  12049     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
  12050                       TOP_PVT_MON_MIN_RST_Lf, 1);
  12051     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
  12052 
  12053     if (temperature_count) {
  12054         *temperature_count=num_entries_out;
  12055     }
  12056     return SOC_E_NONE;
  12057 }
  12058 
  12059 int
  12060 soc_trident3_show_ring_osc(int unit)
  12061 {
  12062     static const struct {
  12063         int osc_sel;
  12064         soc_field_t field0;
  12065         int value0;
  12066         soc_field_t field1;
  12067         int value1;
  12068         char *name;
  12069     } osc_tbl[] = {
  12070         { 0, OSC_0_SELf, 0, INVALIDf, -1, "Core ring 0 HVT min" },
  12071         { 0, OSC_0_SELf, 1, INVALIDf, -1, "Core ring 0 HVT mid" },
  12072         { 0, OSC_0_SELf, 2, INVALIDf, -1, "Core ring 0 HVT max" },
  12073         { 0, OSC_0_SELf, 3, INVALIDf, -1, "Core ring 0 SVT min" },
  12074         { 1, OSC_1_SELf, 0, INVALIDf, -1, "Core ring 1 HVT min" },
  12075         { 1, OSC_1_SELf, 1, INVALIDf, -1, "Core ring 1 HVT mid" },
  12076         { 1, OSC_1_SELf, 2, INVALIDf, -1, "Core ring 1 HVT max" },
  12077         { 1, OSC_1_SELf, 3, INVALIDf, -1, "Core ring 1 SVT min" },
  12078         { 0, IROSC_SELf, 0, INVALIDf, -1, "Core ring 0 five stages" },
  12079         { 0, IROSC_SELf, 1, INVALIDf, -1, "Core ring 0 nine stages" },
  12080         { 1, IROSC_SELf, 0, INVALIDf, -1, "Core ring 1 five stages" },
  12081         { 1, IROSC_SELf, 1, INVALIDf, -1, "Core ring 1 nine stages" },
  12082         { 2, SRAM_OSC_0_PENf, 0, SRAM_OSC_0_NENf, 1, "SRAM ring 0 NMOS" },
  12083         { 3, SRAM_OSC_0_PENf, 1, SRAM_OSC_0_NENf, 0, "SRAM ring 0 PMOS" },
  12084         { 4, SRAM_OSC_1_PENf, 0, SRAM_OSC_1_NENf, 1, "SRAM ring 1 NMOS" },
  12085         { 5, SRAM_OSC_1_PENf, 1, SRAM_OSC_1_NENf, 0, "SRAM ring 1 PMOS" },
  12086         { 6, SRAM_OSC_2_PENf, 0, SRAM_OSC_2_NENf, 1, "SRAM ring 2 NMOS" },
  12087         { 7, SRAM_OSC_2_PENf, 1, SRAM_OSC_2_NENf, 0, "SRAM ring 2 PMOS" },
  12088         { 8, SRAM_OSC_3_PENf, 0, SRAM_OSC_3_NENf, 1, "SRAM ring 3 NMOS" },
  12089         { 9, SRAM_OSC_3_PENf, 1, SRAM_OSC_3_NENf, 0, "SRAM ring 3 PMOS" },
  12090     };
  12091     soc_reg_t ctrl_reg, stat_reg;
  12092     uint32 rval, fval;
  12093     int index, core_clk, quo, rem, frac, retry;
  12094 
  12095     core_clk = SOC_INFO(unit).frequency * 1024;
  12096     ctrl_reg = TOP_RING_OSC_CTRLr;
  12097     stat_reg = TOP_OSC_COUNT_STATr;
  12098 
  12099     for (index = 0; index < COUNTOF(osc_tbl); index++) {
  12100         rval = 0;
  12101         /*
  12102          * set OSC_CNT_RSTBf to 0 to do softreset
  12103          * set OSC_CNT_START to 0 to hold the counter until it selects
  12104          * the input signal
  12105          */
  12106         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
  12107         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_ENABLEf, 1);
  12108         soc_reg_field_set(unit, ctrl_reg, &rval, IROSC_ENf, 1);
  12109         soc_reg_field_set(unit, ctrl_reg, &rval, osc_tbl[index].field0,
  12110                           osc_tbl[index].value0);
  12111         if (osc_tbl[index].field1 != INVALIDf) {
  12112             soc_reg_field_set(unit, ctrl_reg, &rval, osc_tbl[index].field1,
  12113                               osc_tbl[index].value1);
  12114         }
  12115         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_SELf,
  12116                           osc_tbl[index].osc_sel);
  12117         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
  12118         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_CNT_RSTBf, 1);
  12119         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
  12120         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_CNT_STARTf, 1);
  12121         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
  12122 
  12123         for (retry = 0; retry < 10; retry++) {
  12124             sal_usleep(1000);
  12125             SOC_IF_ERROR_RETURN(READ_TOP_OSC_COUNT_STATr(unit, &rval));
  12126             if (!soc_reg_field_get(unit, stat_reg, rval, OSC_CNT_DONEf)) {
  12127                 continue;
  12128             }
  12129 
  12130             fval = soc_reg_field_get(unit, stat_reg, rval, OSC_CNT_VALUEf);
  12131             quo = core_clk / fval;
  12132             rem = core_clk - quo * fval;
  12133             frac = (rem * 10000) / fval;
  12134             LOG_CLI((BSL_META_U(unit,
  12135                                 "%s: %d.%04d Mhz\n"),
  12136                      osc_tbl[index].name, quo, frac));
  12137             break;
  12138         }
  12139     }
  12140 
  12141     return SOC_E_NONE;
  12142 }
  12143 
  12144 STATIC _soc_td3_bst_hw_cb td3_bst_cb;
  12145 extern int bst_td3_cfap_trigger_status[SOC_MAX_NUM_DEVICES];
  12146 int
  12147 soc_td3_process_mmu_bst(int unit, int xpe, soc_field_t field)
  12148 {
  12149     int rv = SOC_E_NONE;
  12150     if (field == BST_CFAP_INT_STATf) {
  12151         bst_td3_cfap_trigger_status[unit] = 1;
  12152     }
  12153     if (td3_bst_cb != NULL) {
  12154         rv = td3_bst_cb(unit);
  12155     }
  12156     return rv;
  12157 }
  12158 
  12159 int soc_td3_set_bst_callback(int unit, _soc_td3_bst_hw_cb cb)
  12160 {
  12161     td3_bst_cb = cb;
  12162     return SOC_E_NONE;
  12163 }
  12164 
  12165 STATIC _soc_td3_tcb_hw_cb td3_tcb_cb;
  12166 
  12167 int
  12168 soc_td3_process_mmu_tcb(int unit, int xpe, soc_field_t field)
  12169 {
  12170     int rv = SOC_E_NONE;
  12171     if (td3_tcb_cb != NULL) {
  12172         rv = td3_tcb_cb(unit);
  12173     }
  12174     return rv;
  12175 }
  12176 
  12177 int soc_td3_set_tcb_callback(int unit, _soc_td3_tcb_hw_cb cb)
  12178 {
  12179     td3_tcb_cb = cb;
  12180     return SOC_E_NONE;
  12181 }
  12182 
  12183 STATIC int
  12184 _soc_td3_mmu_config_shared_update_check(int val1, int val2, int flags)
  12185 {
  12186     int rv = 0;
  12187     if (flags == 1) {
  12188         if (val1 > val2) {
  12189             rv = 1;
  12190         }
  12191     } else {
  12192         if (val1 < val2) {
  12193             rv = 1;
  12194         }
  12195     }
  12196     return rv;
  12197 }
  12198 
  12199 #define TD3_MMU_SHARED_LIMIT_CHK(val1, val2, flags) \
  12200     _soc_td3_mmu_config_shared_update_check((val1), (val2), (flags))
  12201 
  12202 
  12203 int
  12204 soc_td3_mmu_config_shared_buf_recalc(int unit, int res, int thdi_shd,
  12205                                     int thdo_db_shd, int thdo_qe_shd,
  12206                                     int post_update)
  12207 {
  12208     soc_info_t *si;
  12209     int pipe;
  12210     uint32 entry0[SOC_MAX_MEM_WORDS], cur_limit, rval = 0, rval2 = 0;
  12211     uint64 rval64;
  12212     thdi_port_pg_config_entry_t pg_config_mem;
  12213     mmu_thdo_config_qgroup_entry_t cfg_qgrp;
  12214     int port, base, numq, idx, midx;
  12215     soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm;
  12216     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  12217     soc_reg_t reg = INVALIDr;
  12218     soc_field_t field = INVALIDf;
  12219     int granularity, index1;
  12220 
  12221     COMPILER_64_ZERO(rval64);
  12222     si = &SOC_INFO(unit);
  12223 
  12224     /***********************************
  12225      * THDI
  12226  */
  12227     if (res & 0x1) { /* if (res & THDI) { */
  12228 
  12229         for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
  12230             /* THDI SP entries */
  12231             rval = 0;
  12232             reg = THDI_BUFFER_CELL_LIMIT_SPr;
  12233             field = LIMITf;
  12234             granularity = 1;
  12235             SOC_IF_ERROR_RETURN
  12236                 (READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, idx, &rval));
  12237             cur_limit = soc_reg_field_get(unit, reg, rval, field);
  12238             if ((cur_limit != 0) &&
  12239                 TD3_MMU_SHARED_LIMIT_CHK(cur_limit, thdi_shd/granularity,
  12240                                         post_update)) {
  12241                 soc_reg_field_set(unit, reg, &rval, field, (thdi_shd/granularity));
  12242                 SOC_IF_ERROR_RETURN(
  12243                     soc_trident3_xpe_reg32_set(unit, reg,
  12244                                                -1, -1, idx, rval));
  12245             }
  12246         }
  12247 
  12248         /* Input per port settings */
  12249         base_mem = THDI_PORT_PG_CONFIGm;
  12250         PBMP_ALL_ITER(unit, port) {
  12251             pipe = si->port_pipe[port];
  12252             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  12253             field = PG_SHARED_LIMITf;
  12254             granularity = 1;
  12255             /* Input port per Port-PG settings */
  12256             for (idx = 0; idx < _TD3_MMU_NUM_PG; idx++) {
  12257                 midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, port, mem, idx);
  12258                 sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem));
  12259                 SOC_IF_ERROR_RETURN
  12260                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12261                                   midx, &pg_config_mem));
  12262                 if (!soc_mem_field32_get(unit, mem, &pg_config_mem,
  12263                                          PG_SHARED_DYNAMICf)) {
  12264                     cur_limit = soc_mem_field32_get(unit, mem, &pg_config_mem,
  12265                                                     field);
  12266                     if ((cur_limit != 0) &&
  12267                         TD3_MMU_SHARED_LIMIT_CHK(cur_limit, thdi_shd/granularity,
  12268                                                 post_update)) {
  12269                         soc_mem_field32_set(unit, mem, &pg_config_mem,
  12270                                             field, thdi_shd/granularity);
  12271                     }
  12272                 }
  12273 
  12274                 SOC_IF_ERROR_RETURN
  12275                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL,
  12276                                    midx, &pg_config_mem));
  12277             }
  12278         }
  12279     }
  12280 
  12281     /***********************************
  12282      * THDO
  12283  */
  12284     if (res & 0x2) { /* if (res & THDO) { */
  12285         /* Per SP settings */
  12286         for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
  12287             /* DB entries */
  12288             rval = 0;
  12289             reg = MMU_THDM_DB_POOL_SHARED_LIMITr;
  12290             field = SHARED_LIMITf;
  12291             granularity = 1;
  12292             SOC_IF_ERROR_RETURN
  12293                 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
  12294             cur_limit = soc_reg_field_get(unit, reg, rval, field);
  12295             if ((cur_limit != 0) &&
  12296                 TD3_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd/granularity,
  12297                                         post_update)) {
  12298                 soc_reg_field_set(unit, reg, &rval, field, (thdo_db_shd/granularity));
  12299                 SOC_IF_ERROR_RETURN
  12300                     (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval));
  12301             }
  12302 
  12303             rval = 0;
  12304             reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;
  12305             field = YELLOW_SHARED_LIMITf;
  12306             granularity = 8;
  12307             SOC_IF_ERROR_RETURN
  12308                 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
  12309             cur_limit = soc_reg_field_get(unit, reg, rval, field);
  12310             if ((cur_limit != 0) &&
  12311                 TD3_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd, granularity),
  12312                                         post_update)) {
  12313                 soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd, granularity));
  12314                 SOC_IF_ERROR_RETURN
  12315                     (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval));
  12316             }
  12317 
  12318             rval = 0;
  12319             reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;
  12320             field = RED_SHARED_LIMITf;
  12321             granularity = 8;
  12322             SOC_IF_ERROR_RETURN
  12323                 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
  12324             cur_limit = soc_reg_field_get(unit, reg, rval, field);
  12325             if ((cur_limit != 0) &&
  12326                 TD3_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd, granularity),
  12327                                         post_update)) {
  12328                 soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd, granularity));
  12329                 SOC_IF_ERROR_RETURN
  12330                     (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval));
  12331             }
  12332 
  12333             /* MCQE */
  12334             rval = 0;
  12335             reg = MMU_THDM_MCQE_POOL_SHARED_LIMITr;
  12336             field = SHARED_LIMITf;
  12337             granularity = 1; /* Value retrieved from QE. Hence no further
  12338                               * granularity for Non-color Shd Limit */
  12339             SOC_IF_ERROR_RETURN
  12340                 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
  12341             cur_limit = soc_reg_field_get(unit, reg, rval, field);
  12342             if ((cur_limit != 0) &&
  12343                 TD3_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_qe_shd/granularity,
  12344                                         post_update)) {
  12345                 soc_reg_field_set(unit, reg, &rval, field,
  12346                                   (thdo_qe_shd/granularity));
  12347                 SOC_IF_ERROR_RETURN
  12348                     (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval));
  12349             }
  12350 
  12351             rval = 0;
  12352             reg = MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr;
  12353             field = YELLOW_SHARED_LIMITf;
  12354             granularity = 8;
  12355             SOC_IF_ERROR_RETURN
  12356                 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
  12357             cur_limit = soc_reg_field_get(unit, reg, rval, field);
  12358             if ((cur_limit != 0) &&
  12359                 TD3_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_qe_shd/granularity,
  12360                                         post_update)) {
  12361                 soc_reg_field_set(unit, reg, &rval, field,
  12362                                   (thdo_qe_shd/granularity));
  12363                 SOC_IF_ERROR_RETURN
  12364                     (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval));
  12365             }
  12366 
  12367             rval = 0;
  12368             reg = MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr;
  12369             field = RED_SHARED_LIMITf;
  12370             granularity = 8;
  12371             SOC_IF_ERROR_RETURN
  12372                 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
  12373             cur_limit = soc_reg_field_get(unit, reg, rval, field);
  12374             if ((cur_limit != 0) &&
  12375                 TD3_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_qe_shd/granularity,
  12376                                         post_update)) {
  12377                 soc_reg_field_set(unit, reg, &rval, field,
  12378                                   (thdo_qe_shd/granularity));
  12379                 SOC_IF_ERROR_RETURN
  12380                     (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval));
  12381             }
  12382         }
  12383 
  12384         /* configure Q-groups */
  12385         base_mem = MMU_THDU_CONFIG_QGROUPm;
  12386         for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  12387             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  12388             for (idx = 0; idx < SOC_TD3_MMU_CFG_QGROUP_MAX; idx++) {
  12389                 sal_memset(&cfg_qgrp, 0, sizeof(cfg_qgrp));
  12390 
  12391                 SOC_IF_ERROR_RETURN
  12392                         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, idx, &cfg_qgrp));
  12393 
  12394                 field = Q_SHARED_LIMIT_CELLf;
  12395                 granularity = 1;
  12396                 if (!soc_mem_field32_get(unit, mem, &cfg_qgrp, Q_LIMIT_DYNAMIC_CELLf)) {
  12397                     cur_limit = soc_mem_field32_get(unit, mem, &cfg_qgrp, field);
  12398                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd/granularity,
  12399                                                 post_update)) {
  12400                         soc_mem_field32_set(unit, mem, &cfg_qgrp,
  12401                                             field, thdo_db_shd/granularity);
  12402                     }
  12403                 }
  12404 
  12405                 granularity = 8;
  12406                 if (!soc_mem_field32_get(unit, mem, &cfg_qgrp,
  12407                                          Q_COLOR_LIMIT_DYNAMIC_CELLf)) {
  12408                     field = LIMIT_RED_CELLf;
  12409                     cur_limit = soc_mem_field32_get(unit, mem, &cfg_qgrp, field);
  12410                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd/granularity,
  12411                                                 post_update)) {
  12412                         soc_mem_field32_set(unit, mem, &cfg_qgrp,
  12413                                             field, thdo_db_shd/granularity);
  12414                     }
  12415 
  12416                     field = LIMIT_YELLOW_CELLf;
  12417                     cur_limit = soc_mem_field32_get(unit, mem, &cfg_qgrp, field);
  12418                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd/granularity,
  12419                                                 post_update)) {
  12420                         soc_mem_field32_set(unit, mem, &cfg_qgrp,
  12421                                             field, thdo_db_shd/granularity);
  12422                     }
  12423                 }
  12424 
  12425                 SOC_IF_ERROR_RETURN
  12426                         (soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, &cfg_qgrp));
  12427             }
  12428         }
  12429 
  12430         /* Output port per port per queue setting for UC queue */
  12431         PBMP_PORT_ITER(unit, port) {
  12432             base_mem = MMU_THDU_CONFIG_QUEUEm;
  12433             pipe = si->port_pipe[port];
  12434 
  12435             /* per port UC queue */
  12436             numq = si->port_num_uc_cosq[port];
  12437             base = si->port_uc_cosq_base[port];
  12438 
  12439             if (numq == 0) {
  12440                 continue;
  12441             }
  12442             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  12443             for (idx = 0; idx < numq; idx++) {
  12444                 sal_memset(entry0, 0, sizeof(mmu_thdu_config_queue_entry_t));
  12445 
  12446                 SOC_IF_ERROR_RETURN
  12447                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
  12448 
  12449                 field = Q_SHARED_LIMIT_CELLf;
  12450                 granularity = 1;
  12451                 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMIC_CELLf)) {
  12452                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12453                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd/granularity,
  12454                                                 post_update)) {
  12455                         soc_mem_field32_set(unit, mem, entry0,
  12456                                             field, thdo_db_shd/granularity);
  12457                     }
  12458                 }
  12459 
  12460                 granularity = 8;
  12461                 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMIC_CELLf)) {
  12462                     field = LIMIT_YELLOW_CELLf;
  12463                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12464                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd, granularity),
  12465                                                 post_update)) {
  12466                         soc_mem_field32_set(unit, mem, entry0,
  12467                                             field, sal_ceil_func(thdo_db_shd, granularity));
  12468                     }
  12469                     field = LIMIT_RED_CELLf;
  12470                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12471                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12472                                 sal_ceil_func(thdo_db_shd, granularity), post_update)) {
  12473                         soc_mem_field32_set(unit, mem, entry0,
  12474                                             field, sal_ceil_func(thdo_db_shd, granularity));
  12475                     }
  12476                 }
  12477                 SOC_IF_ERROR_RETURN
  12478                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
  12479             }
  12480 
  12481             /* Per port-SP unicast */
  12482             base_mem = MMU_THDU_CONFIG_PORTm;
  12483             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  12484             for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
  12485                 index1 = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, port, mem, idx);
  12486                 sal_memset(entry0, 0, sizeof(mmu_thdu_xpipe_config_port_entry_t));
  12487 
  12488                 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12489                                     index1, entry0));
  12490 
  12491                 field = SHARED_LIMITf;
  12492                 granularity = 1;
  12493                 cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12494                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12495                             thdo_db_shd/granularity, post_update)) {
  12496                     soc_mem_field32_set(unit, mem, entry0,
  12497                                         field, thdo_db_shd/granularity);
  12498                 }
  12499 
  12500                 granularity = 8;
  12501                 field = YELLOW_LIMITf;
  12502                 cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12503                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12504                             thdo_db_shd/granularity, post_update)) {
  12505                     soc_mem_field32_set(unit, mem, entry0,
  12506                                         field, thdo_db_shd/granularity);
  12507                 }
  12508                 field = RED_LIMITf;
  12509                 cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12510                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12511                             thdo_db_shd/granularity, post_update)) {
  12512                     soc_mem_field32_set(unit, mem, entry0,
  12513                                         field, thdo_db_shd/granularity);
  12514                 }
  12515 
  12516                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
  12517                                                   index1, entry0));
  12518             }
  12519         }
  12520 
  12521         /* Output port per port per queue setting for MC queue */
  12522         PBMP_PORT_ITER(unit, port) {
  12523             base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
  12524             base_mem2 = MMU_THDM_MCQE_PORTSP_CONFIGm;
  12525             pipe = si->port_pipe[port];
  12526 
  12527             /* Per Port-SP */
  12528             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  12529             mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
  12530             for (idx = 0; idx < _TD3_MMU_NUM_POOL; idx++) {
  12531                 /* DB entries - Port-SP */
  12532                 index1 = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, port, mem, idx);
  12533                 sal_memset(entry0, 0, sizeof(mmu_thdm_db_portsp_config_entry_t));
  12534 
  12535                 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  12536                                     index1, entry0));
  12537 
  12538                 field = SHARED_LIMITf;
  12539                 granularity = 1;
  12540                 cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12541                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12542                             thdo_db_shd/granularity, post_update)) {
  12543                     soc_mem_field32_set(unit, mem, entry0,
  12544                                         field, thdo_db_shd/granularity);
  12545                 }
  12546 
  12547                 field = RED_SHARED_LIMITf;
  12548                 granularity = 8;
  12549                 cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12550                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12551                             thdo_db_shd/granularity, post_update)) {
  12552                     soc_mem_field32_set(unit, mem, entry0,
  12553                                         field, thdo_db_shd/granularity);
  12554                 }
  12555 
  12556                 field = YELLOW_SHARED_LIMITf;
  12557                 granularity = 8;
  12558                 cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12559                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12560                             thdo_db_shd/granularity, post_update)) {
  12561                     soc_mem_field32_set(unit, mem, entry0,
  12562                                         field, thdo_db_shd/granularity);
  12563                 }
  12564 
  12565                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
  12566                                     index1, entry0));
  12567 
  12568                 /* MCQE - Port-SP*/
  12569                 sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_portsp_config_entry_t));
  12570 
  12571                 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL,
  12572                                     index1, entry0));
  12573                 field = SHARED_LIMITf;
  12574                 granularity = 4;
  12575                 cur_limit = soc_mem_field32_get(unit, mem2, entry0, field);
  12576                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12577                             thdo_qe_shd/granularity, post_update)) {
  12578                     soc_mem_field32_set(unit, mem2, entry0,
  12579                                         field, thdo_qe_shd/granularity);
  12580                 }
  12581 
  12582                 field = RED_SHARED_LIMITf;
  12583                 granularity = 8;
  12584                 cur_limit = soc_mem_field32_get(unit, mem2, entry0, field);
  12585                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12586                             thdo_qe_shd/granularity, post_update)) {
  12587                     soc_mem_field32_set(unit, mem2, entry0,
  12588                                         field, thdo_qe_shd/granularity);
  12589                 }
  12590 
  12591                 field = YELLOW_SHARED_LIMITf;
  12592                 granularity = 8;
  12593                 cur_limit = soc_mem_field32_get(unit, mem2, entry0, field);
  12594                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12595                             thdo_qe_shd/granularity, post_update)) {
  12596                     soc_mem_field32_set(unit, mem2, entry0,
  12597                                         field, thdo_qe_shd/granularity);
  12598                 }
  12599                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL,
  12600                                     index1, entry0));
  12601 
  12602             }
  12603 
  12604             /* DB entries - Queue */
  12605             numq = si->port_num_cosq[port];
  12606             base = si->port_cosq_base[port];
  12607             if (numq == 0) {
  12608                 continue;
  12609             }
  12610 
  12611             base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
  12612             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  12613 
  12614             for (idx = 0; idx < numq; idx++) {
  12615                 sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_config_entry_t));
  12616 
  12617                 SOC_IF_ERROR_RETURN
  12618                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
  12619 
  12620                 field = Q_SHARED_LIMITf;
  12621                 granularity = 1;
  12622                 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMICf)) {
  12623                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12624                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12625                                 thdo_db_shd/granularity, post_update)) {
  12626                         soc_mem_field32_set(unit, mem, entry0,
  12627                                             field, thdo_db_shd/granularity);
  12628                     }
  12629                 }
  12630 
  12631                 granularity = 8;
  12632                 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMICf)) {
  12633                     field = YELLOW_SHARED_LIMITf;
  12634                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12635                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12636                                 sal_ceil_func(thdo_db_shd, granularity), post_update)) {
  12637                         soc_mem_field32_set(unit, mem, entry0,
  12638                                             field, sal_ceil_func(thdo_db_shd, granularity));
  12639                     }
  12640                     field = RED_SHARED_LIMITf;
  12641                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12642                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12643                                 sal_ceil_func(thdo_db_shd, granularity), post_update)) {
  12644                         soc_mem_field32_set(unit, mem, entry0,
  12645                                             field, sal_ceil_func(thdo_db_shd, granularity));
  12646                     }
  12647                 }
  12648                 SOC_IF_ERROR_RETURN
  12649                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx,
  12650                                    entry0));
  12651             }
  12652 
  12653             /* MCQE - Queue */
  12654             base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
  12655             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  12656             for (idx = 0; idx < numq; idx++) {
  12657                 sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_config_entry_t));
  12658 
  12659                 SOC_IF_ERROR_RETURN
  12660                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
  12661 
  12662                 field = Q_SHARED_LIMITf;
  12663                 granularity = 4;
  12664                 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMICf)) {
  12665                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12666                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12667                                 thdo_qe_shd/granularity, post_update)) {
  12668                         soc_mem_field32_set(unit, mem, entry0,
  12669                                             field, thdo_qe_shd/granularity);
  12670                     }
  12671                 }
  12672 
  12673                 granularity = 8;
  12674                 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMICf)) {
  12675                     field = YELLOW_SHARED_LIMITf;
  12676                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12677                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12678                                 thdo_qe_shd/granularity, post_update)) {
  12679                         soc_mem_field32_set(unit, mem, entry0,
  12680                                             field, thdo_qe_shd/granularity);
  12681                     }
  12682                     field = RED_SHARED_LIMITf;
  12683                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  12684                     if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12685                                 thdo_qe_shd/granularity, post_update)) {
  12686                         soc_mem_field32_set(unit, mem, entry0,
  12687                                             field, thdo_qe_shd/granularity);
  12688                     }
  12689                 }
  12690                 SOC_IF_ERROR_RETURN
  12691                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx,
  12692                                    entry0));
  12693             }
  12694         }
  12695 
  12696         /* RQE */
  12697         for (idx = 0; idx < 11; idx++) {
  12698             rval = 0;
  12699             COMPILER_64_ZERO(rval64);
  12700 
  12701             SOC_IF_ERROR_RETURN
  12702                 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, idx, &rval));
  12703 
  12704             reg = MMU_THDR_DB_CONFIG_PRIQr;
  12705             field = SHARED_LIMITf;
  12706             granularity = 1;
  12707             SOC_IF_ERROR_RETURN
  12708                 (soc_reg64_get(unit, reg, REG_PORT_ANY, idx, &rval64));
  12709             if (!soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval,
  12710                                    DYNAMIC_ENABLEf)) {
  12711                 cur_limit = soc_reg64_field32_get(unit, reg, rval64, field);
  12712                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12713                             thdo_db_shd/granularity, post_update)) {
  12714                     soc_reg64_field32_set(unit, reg, &rval64, field,
  12715                                       (thdo_db_shd/granularity));
  12716                     SOC_IF_ERROR_RETURN
  12717                         (soc_reg64_set(unit, reg, REG_PORT_ANY, idx, rval64));
  12718                 }
  12719             }
  12720 
  12721             rval2 = 0;
  12722             reg = MMU_THDR_DB_LIMIT_COLOR_PRIQr;
  12723             granularity = 8;
  12724             SOC_IF_ERROR_RETURN
  12725                 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval2));
  12726 
  12727             if (!soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval,
  12728                                    COLOR_LIMIT_DYNAMICf)) {
  12729                 field = SHARED_RED_LIMITf;
  12730                 cur_limit = soc_reg_field_get(unit, reg, rval2, field);
  12731                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12732                             thdo_db_shd/granularity, post_update)) {
  12733                     soc_reg_field_set(unit, reg, &rval2, field, (thdo_db_shd/granularity));
  12734                 }
  12735 
  12736                 field = SHARED_YELLOW_LIMITf;
  12737                 cur_limit = soc_reg_field_get(unit, reg, rval2, field);
  12738                 if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12739                             thdo_db_shd/granularity, post_update)) {
  12740                     soc_reg_field_set(unit, reg, &rval2, field, (thdo_db_shd/granularity));
  12741                 }
  12742                 SOC_IF_ERROR_RETURN
  12743                     (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval2));
  12744             }
  12745 
  12746         }
  12747         /* per pool RQE settings */
  12748         for (idx = 0; idx < 4; idx++) {
  12749             reg = MMU_THDR_DB_CONFIG_SPr;
  12750             field = SHARED_LIMITf;
  12751             granularity = 1;
  12752 
  12753             SOC_IF_ERROR_RETURN
  12754                 (soc_reg64_get(unit, reg, REG_PORT_ANY, idx, &rval64));
  12755             cur_limit = soc_reg_field_get(unit, reg, rval, field);
  12756 
  12757             if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12758                         thdo_db_shd/granularity, post_update)) {
  12759                 soc_reg64_field32_set
  12760                     (unit, reg, &rval64, field, (thdo_db_shd/granularity));
  12761                 SOC_IF_ERROR_RETURN
  12762                     (soc_reg64_set(unit, reg, REG_PORT_ANY, idx, rval64));
  12763             }
  12764 
  12765             reg = MMU_THDR_DB_SP_SHARED_LIMITr;
  12766             granularity = 8;
  12767 
  12768             SOC_IF_ERROR_RETURN
  12769                 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval2));
  12770 
  12771             field = SHARED_YELLOW_LIMITf;
  12772             cur_limit = soc_reg_field_get(unit, reg, rval, field);
  12773 
  12774             if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12775                         thdo_db_shd/granularity, post_update)) {
  12776                 soc_reg_field_set
  12777                     (unit, reg, &rval2, field, (thdo_db_shd/granularity));
  12778             }
  12779 
  12780             field = SHARED_RED_LIMITf;
  12781             cur_limit = soc_reg_field_get(unit, reg, rval, field);
  12782 
  12783             if (TD3_MMU_SHARED_LIMIT_CHK(cur_limit,
  12784                         thdo_db_shd/granularity, post_update)) {
  12785                 soc_reg_field_set
  12786                     (unit, reg, &rval2, field, (thdo_db_shd/granularity));
  12787             }
  12788             SOC_IF_ERROR_RETURN
  12789                 (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval2));
  12790         }
  12791     }
  12792     return SOC_E_NONE;
  12793 }
  12794 
  12795 void
  12796 soc_trident3_process_func_intr(void *unit_vp, void *d1, void *d2, void *d3, void *d4)
  12797 {
  12798     int rv = SOC_E_NONE;
  12799     int unit = PTR_TO_INT(unit_vp);
  12800     uint32 rval;
  12801     char       prefix_str[10];
  12802     sal_sprintf(prefix_str, "Unit: %d \n", unit);
  12803 
  12804     rv = READ_L2_MGMT_INTRr(unit, &rval);
  12805     if (SOC_FAILURE(rv)) {
  12806         LOG_ERROR(BSL_LS_SOC_COMMON,
  12807                   (BSL_META_U(unit, "Error reading %s reg !!\n"),
  12808                               SOC_REG_NAME(unit, L2_MGMT_INTRr)));
  12809         return;
  12810     }
  12811 
  12812     if (soc_reg_field_get(unit, L2_MGMT_INTRr, rval, SER_FIFO_NOT_EMPTYf)) {
  12813         (void) soc_trident3_process_ser_fifo(unit, SOC_BLK_IPIPE,
  12814                                              0, /* pipe */
  12815                                              prefix_str,
  12816                                              1); /* l2_mgmt_ser_fifo */
  12817     }
  12818     if (soc_reg_field_get(unit, L2_MGMT_INTRr, rval, L2_LEARN_INSERT_FAILUREf)) {
  12819         soc_td2_l2_overflow_interrupt_handler(unit);
  12820     }
  12821 
  12822     sal_usleep(SAL_BOOT_QUICKTURN ? 100000 : 1000); /* Don't reenable too soon */
  12823     if (d4 != NULL) {
  12824 #ifdef BCM_CMICX_SUPPORT
  12825         if (soc_feature(unit, soc_feature_cmicx)) {
  12826             (void)soc_cmic_intr_enable(unit, PTR_TO_INT(d4));
  12827         }
  12828 #endif
  12829     }
  12830 }
  12831 
  12832 
  12833 /*
  12834  * All non-parity related interrupts must be handled in this function.
  12835  * All unserviced intr_status bits must either be serviced or disabled.
  12836  *
  12837  * Note:
  12838  * 1. MEM_PAR_ERR_STATf is handled by trident3/ser.c, so ignore this
  12839  * 2. blocktype (in) can only be SOC_BLK_MMU_XPE/SC/SED
  12840  */
  12841 int
  12842 soc_td3_mmu_non_ser_intr_handler(int unit, soc_block_t blocktype,
  12843                                 int mmu_base_index,
  12844                                 uint32 rval_intr_status_reg)
  12845 {
  12846     /*This need each other block to implement the non-ser interrupt handler */
  12847     int i;
  12848     uint32 rval = 0;
  12849     soc_reg_t intr_stat_reg, intr_clr_reg;
  12850 
  12851     static soc_field_t xpe_intr_field_list[] = {
  12852         MEM_PAR_ERR_STATf, /* handled by trident3/ser.c, so ignore this */
  12853         BST_THDI_INT_STATf,
  12854         BST_THDO_INT_STATf,
  12855         DEQ0_NOT_IP_ERR_STATf,
  12856         DEQ1_NOT_IP_ERR_STATf,
  12857         ENQX_TO_CFG_MAX_CELL_INTR_0_STATf,
  12858         ENQX_TO_CFG_MAX_CELL_INTR_1_STATf,
  12859         TCB_FREEZE_INT_STATf,
  12860         INVALIDf
  12861     };
  12862 
  12863     static soc_field_t sed_intr_field_list[] = {
  12864         CFAP_MEM_FAIL_STATf,
  12865         MEM_PAR_ERR_STATf,
  12866         BST_CFAP_INT_STATf,
  12867         START_BY_START_ERR_STATf,
  12868         INVALIDf
  12869     };
  12870 
  12871     if (blocktype == SOC_BLK_MMU_XPE) {
  12872         intr_stat_reg = MMU_XCFG_XPE_CPU_INT_STATr;
  12873         intr_clr_reg = MMU_XCFG_XPE_CPU_INT_CLEARr;
  12874         for (i = 0; xpe_intr_field_list[i] != INVALIDf; i++) {
  12875             if (!soc_reg_field_valid(unit, intr_stat_reg, xpe_intr_field_list[i])) {
  12876                 continue;
  12877             }
  12878             if (!soc_reg_field_get(unit, intr_stat_reg,
  12879                                    rval_intr_status_reg,
  12880                                    xpe_intr_field_list[i])) {
  12881                 continue;
  12882             }
  12883             switch (xpe_intr_field_list[i]) {
  12884             case BST_THDI_INT_STATf:
  12885             case BST_THDO_INT_STATf:
  12886                 /* interrupt processing */
  12887                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  12888                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
  12889                                               "from xpe = %0d \n"),
  12890                              unit, SOC_FIELD_NAME(unit, xpe_intr_field_list[i]),
  12891                              mmu_base_index));
  12892 
  12893                 /* clear the interrupt */
  12894                 SOC_IF_ERROR_RETURN
  12895                     (soc_trident3_xpe_reg32_get(unit, intr_clr_reg,
  12896                                                 mmu_base_index, mmu_base_index,
  12897                                                 0, &rval));
  12898                 rval |= (1 << i);
  12899                 SOC_IF_ERROR_RETURN
  12900                     (soc_trident3_xpe_reg32_set(unit, intr_clr_reg,
  12901                                                 mmu_base_index, mmu_base_index,
  12902                                                 0, rval));
  12903                 SOC_IF_ERROR_RETURN
  12904                     (soc_td3_process_mmu_bst(unit, mmu_base_index,
  12905                                              xpe_intr_field_list[i]));
  12906                 break;
  12907             case TCB_FREEZE_INT_STATf:
  12908                 /* interrupt processing */
  12909                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  12910                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
  12911                                               "from xpe = %0d \n"),
  12912                              unit, SOC_FIELD_NAME(unit, xpe_intr_field_list[i]),
  12913                              mmu_base_index));
  12914 
  12915                 /* clear the interrupt */
  12916                 SOC_IF_ERROR_RETURN
  12917                     (soc_trident3_xpe_reg32_get(unit, intr_clr_reg,
  12918                                                 mmu_base_index, mmu_base_index,
  12919                                                 0, &rval));
  12920                 rval |= (1 << i);
  12921                 SOC_IF_ERROR_RETURN
  12922                     (soc_trident3_xpe_reg32_set(unit, intr_clr_reg,
  12923                                                 mmu_base_index, mmu_base_index,
  12924                                                 0, rval));
  12925                 SOC_IF_ERROR_RETURN
  12926                     (soc_td3_process_mmu_tcb(unit, mmu_base_index,
  12927                                              xpe_intr_field_list[i]));
  12928                 break;
  12929             default:
  12930                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12931                           (BSL_META_U(unit, "Unit: %0d -- Could not service %s "
  12932                                             "intr from xpe = %0d \n"),
  12933                            unit, SOC_FIELD_NAME(unit, xpe_intr_field_list[i]),
  12934                            mmu_base_index));
  12935                 break;
  12936             }
  12937         }
  12938         return SOC_E_NONE;
  12939     }
  12940 
  12941     if (blocktype == SOC_BLK_MMU_SED) {
  12942         intr_stat_reg = MMU_SEDCFG_SED_CPU_INT_STATr;
  12943         intr_clr_reg = MMU_SEDCFG_SED_CPU_INT_CLEARr;
  12944         for (i = 0; sed_intr_field_list[i] != INVALIDf; i++) {
  12945             if (!soc_reg_field_valid(unit, intr_stat_reg, sed_intr_field_list[i])) {
  12946                 continue;
  12947             }
  12948             if (!soc_reg_field_get(unit, intr_stat_reg,
  12949                                    rval_intr_status_reg,
  12950                                    sed_intr_field_list[i])) {
  12951                 continue;
  12952             }
  12953             switch (sed_intr_field_list[i]) {
  12954             case BST_CFAP_INT_STATf:
  12955                 /* interrupt processing */
  12956                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  12957                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
  12958                                               "from sed = %0d \n"),
  12959                              unit, SOC_FIELD_NAME(unit, sed_intr_field_list[i]),
  12960                              mmu_base_index));
  12961 
  12962                 /* clear the interrupt */
  12963                 SOC_IF_ERROR_RETURN
  12964                     (soc_trident3_sed_reg32_get(unit, intr_clr_reg,
  12965                                                 mmu_base_index, mmu_base_index,
  12966                                                 0, &rval));
  12967                 rval |= (1 << i);
  12968                 SOC_IF_ERROR_RETURN
  12969                     (soc_trident3_sed_reg32_set(unit, intr_clr_reg,
  12970                                                 mmu_base_index, mmu_base_index,
  12971                                                 0, rval));
  12972                 SOC_IF_ERROR_RETURN
  12973                     (soc_td3_process_mmu_bst(unit, mmu_base_index,
  12974                                              sed_intr_field_list[i]));
  12975                 break;
  12976             case CFAP_MEM_FAIL_STATf:
  12977                 /* interrupt processing */
  12978                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  12979                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
  12980                                               "from sed = %0d \n"),
  12981                              unit, SOC_FIELD_NAME(unit, sed_intr_field_list[i]),
  12982                              mmu_base_index));
  12983 
  12984                 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR,
  12985                                    SOC_SWITCH_EVENT_DATA_ERROR_CFAP_MEM_FAIL, -1, -1);
  12986 
  12987                 /* clear the interrupt */
  12988                 SOC_IF_ERROR_RETURN
  12989                     (soc_trident3_sed_reg32_get(unit, intr_clr_reg,
  12990                                                 mmu_base_index, mmu_base_index,
  12991                                                 0, &rval));
  12992                 rval |= (1 << i);
  12993                 SOC_IF_ERROR_RETURN
  12994                     (soc_trident3_sed_reg32_set(unit, intr_clr_reg,
  12995                                                 mmu_base_index, mmu_base_index,
  12996                                                 0, rval));
  12997                 break;
  12998             default:
  12999                 LOG_ERROR(BSL_LS_SOC_COMMON,
  13000                           (BSL_META_U(unit, "Unit: %0d -- Could not service %s "
  13001                                             "intr from sed = %0d \n"),
  13002                            unit, SOC_FIELD_NAME(unit, sed_intr_field_list[i]),
  13003                            mmu_base_index));
  13004                 break;
  13005             }
  13006         }
  13007         return SOC_E_NONE;
  13008     }
  13009 
  13010     return SOC_E_NONE;
  13011 }
  13012 
  13013 /*
  13014  * Function:
  13015  *      soc_td3_subport_init
  13016  * Purpose:
  13017  *      Setup the pbm fields from config variables for the COE application
  13018  * Parameters:
  13019  *      unit    -  (IN) Device number.
  13020  * Returns:
  13021  *      NONE
  13022  */
  13023 void soc_td3_subport_init(int unit)
  13024 {
  13025     soc_port_t  port;
  13026     soc_info_t *si=&SOC_INFO(unit);
  13027     soc_pbmp_t  pbmp_subport;
  13028     int         num_subport = 0;
  13029 
  13030     SOC_PBMP_CLEAR(si->subtag_pbm);
  13031     SOC_PBMP_CLEAR(si->subtag_allowed_pbm);
  13032     SOC_PBMP_CLEAR(si->subtag.bitmap);
  13033 
  13034     for (port = 0; port < SOC_MAX_NUM_PORTS; port++) {
  13035         si->port_num_subport[port] = 0;
  13036     }
  13037 
  13038     pbmp_subport = soc_property_get_pbmp(unit, spn_PBMP_SUBPORT, 0);
  13039 
  13040     SOC_PBMP_ASSIGN(si->subtag_allowed_pbm, pbmp_subport);
  13041 
  13042     if (SOC_PBMP_NOT_NULL(si->subtag_allowed_pbm)) {
  13043         /* Iterate through SubTag ports and reserve subport indices */
  13044         SOC_PBMP_ITER(si->subtag_allowed_pbm, port) {
  13045 
  13046             num_subport =
  13047                 soc_property_port_get(unit, port, spn_NUM_SUBPORTS, 0);
  13048 
  13049             if (num_subport > TD3_MAX_SUBPORT_COE_PORT_PER_CASPORT) {
  13050                 LOG_ERROR(BSL_LS_SOC_COMMON,
  13051                           (BSL_META_U(unit,
  13052                               "\nCONFIG ERROR\n"
  13053                               "num_subports_%d on port %d exceed max value,"
  13054                               "setting it to the max allowed value %d\n\n"),
  13055                               num_subport, port,
  13056                               TD3_MAX_SUBPORT_COE_PORT_PER_CASPORT));
  13057                 num_subport = TD3_MAX_SUBPORT_COE_PORT_PER_CASPORT;
  13058             }
  13059 
  13060             if (port < SOC_MAX_NUM_PORTS) {
  13061                 si->port_num_subport[port] = num_subport;
  13062 
  13063             }
  13064         }
  13065     }
  13066 
  13067     /* Initialize the number of COE modules */
  13068     si->num_coe_modules = TD3_MAX_COE_MODULES;
  13069 }
  13070 
  13071 soc_pstats_tbl_desc_t
  13072 _soc_td3_pstats_tbl_desc_all = {SOC_BLK_NONE, INVALIDm, FALSE, FALSE};
  13073 /* pstats support */
  13074 soc_pstats_tbl_desc_t _soc_td3_pstats_tbl_desc[] = {
  13075     /* List all the potential memories */
  13076 #ifdef BCM_PSTATS_MEASURE
  13077     {
  13078         SOC_BLK_MMU_GLB,
  13079         INVALIDm,
  13080         FALSE, FALSE,
  13081         {
  13082             {MMU_INTFO_TIMESTAMPm},
  13083             {INVALIDm}
  13084         }
  13085     },
  13086 #endif
  13087     {
  13088         SOC_BLK_MMU_GLB,
  13089         INVALIDm,
  13090         FALSE, FALSE,
  13091         {
  13092             {MMU_INTFO_UTC_TIMESTAMPm},
  13093             {INVALIDm}
  13094         }
  13095     },
  13096     {
  13097         SOC_BLK_MMU_XPE,
  13098         MMU_THDU_UCQ_STATS_TABLEm,
  13099         TRUE, TRUE
  13100     },
  13101     {
  13102         SOC_BLK_MMU_XPE,
  13103         THDI_PKT_STAT_SP_SHARED_COUNTm,
  13104         FALSE, FALSE
  13105     },
  13106     {
  13107         SOC_BLK_MMU_XPE,
  13108         MMU_THDM_DB_POOL_MCUC_PKSTATm,
  13109         FALSE, FALSE
  13110 #ifdef BCM_PSTATS_MEASURE
  13111     },
  13112     {
  13113         SOC_BLK_MMU_GLB,
  13114         INVALIDm,
  13115         FALSE, FALSE,
  13116         {
  13117             {MMU_INTFO_TIMESTAMPm},
  13118             {INVALIDm}
  13119         }
  13120 #endif
  13121     }
  13122 };
  13123 
  13124 void
  13125 soc_trident3_mmu_pstats_tbl_config_all(int unit)
  13126 {
  13127     soc_control_t *soc = SOC_CONTROL(unit);
  13128     soc_pstats_mem_desc_t *desc, *desc_all;
  13129     int ti, mi, di = 0;
  13130 
  13131     desc_all = _soc_td3_pstats_tbl_desc_all.desc;
  13132     /* Check and strip invalid memories */
  13133     for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) {
  13134         mi = 0;
  13135         desc = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].desc;
  13136         while (desc[mi].mem != INVALIDm) {
  13137             desc_all[di] = desc[mi];
  13138             di++;
  13139             mi++;
  13140         }
  13141     }
  13142     desc_all[di].mem = INVALIDm;
  13143 
  13144     soc->pstats_tbl_desc = &_soc_td3_pstats_tbl_desc_all;
  13145     soc->pstats_tbl_desc_count = 1;
  13146 }
  13147 
  13148 void
  13149 soc_trident3_mmu_pstats_tbl_config(int unit)
  13150 {
  13151     soc_control_t *soc = SOC_CONTROL(unit);
  13152     soc_pstats_mem_desc_t *desc;
  13153     soc_mem_t bmem;
  13154     int pe, mor_dma;
  13155     int ti, mi, xpe, pipe;
  13156 
  13157     soc->pstats_tbl_desc = _soc_td3_pstats_tbl_desc;
  13158     soc->pstats_tbl_desc_count = COUNTOF(_soc_td3_pstats_tbl_desc);
  13159     soc->pstats_mode = PSTATS_MODE_NULL;
  13160 
  13161     /* Check and strip invalid memories */
  13162     for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) {
  13163         mi = 0;
  13164         desc = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].desc;
  13165         bmem = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].bmem;
  13166         if (bmem == INVALIDm) {
  13167             while (desc[mi].mem != INVALIDm) {
  13168                 desc[mi].width = soc_mem_entry_words(unit, desc[mi].mem);
  13169                 desc[mi].entries = soc_mem_index_count(unit, desc[mi].mem);
  13170                 mi++;
  13171             }
  13172             continue;
  13173         }
  13174         pe = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].pipe_enum;
  13175         mor_dma = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].mor_dma;
  13176         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
  13177             for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  13178                 desc[mi].mem = pe ? SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, bmem, xpe, pipe) :
  13179                                     SOC_MEM_UNIQUE_ACC(unit, bmem)[xpe];
  13180                 if (desc[mi].mem == INVALIDm) {
  13181                     continue;
  13182                 }
  13183                 desc[mi].width = soc_mem_entry_words(unit, desc[mi].mem);
  13184                 desc[mi].entries = soc_mem_index_count(unit, desc[mi].mem);
  13185                 if (mor_dma) {
  13186                     desc[mi].mor_dma = TRUE;
  13187                 }
  13188                 mi++;
  13189                 if (!pe) {
  13190                     break;
  13191                 }
  13192             }
  13193         }
  13194         desc[mi].mem = INVALIDm;
  13195     }
  13196 
  13197     if (soc_property_get(unit, "pstats_desc_all", 1)) {
  13198         /* Use single desc chain */
  13199         soc_trident3_mmu_pstats_tbl_config_all(unit);
  13200     }
  13201 }
  13202 
  13203 int
  13204 soc_trident3_mmu_pstats_mode_set(int unit, uint32 flags)
  13205 {
  13206     soc_control_t *soc = SOC_CONTROL(unit);
  13207     int pf = 0;
  13208     uint32 rval = 0;
  13209     int rv;
  13210 
  13211     SOC_PSTATS_LOCK(unit);
  13212 
  13213     if (flags & _TD3_MMU_PSTATS_HWM_MOD) {
  13214         soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval,
  13215                           HWM_MODEf, 1);
  13216         pf |= _TD3_MMU_PSTATS_HWM_MOD;
  13217         if (flags & _TD3_MMU_PSTATS_RESET_ON_READ) {
  13218             soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval,
  13219                               HWM_RESET_ON_READf, 1);
  13220             pf |= _TD3_MMU_PSTATS_RESET_ON_READ;
  13221         }
  13222     }
  13223 
  13224     if (flags & _TD3_MMU_PSTATS_PKT_MOD) {
  13225         soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval,
  13226                           SELECTf, 1);
  13227         pf |= _TD3_MMU_PSTATS_PKT_MOD;
  13228         if (soc_feature(unit, soc_feature_mor_dma) &&
  13229             (flags & _TD3_MMU_PSTATS_MOR_EN)) {
  13230             soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval,
  13231                               MOR_ENf, 1);
  13232         }
  13233         if (flags & _TD3_MMU_PSTATS_MOR_EN) {
  13234             pf |= _TD3_MMU_PSTATS_MOR_EN;
  13235         }
  13236     }
  13237 
  13238     if (flags & _TD3_MMU_PSTATS_ENABLE) {
  13239         soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval,
  13240                           ENABLEf, 1);
  13241         pf |= _TD3_MMU_PSTATS_ENABLE;
  13242         if (flags & _TD3_MMU_PSTATS_PKT_MOD) {
  13243             if ((flags & _TD3_MMU_PSTATS_SYNC) ||
  13244                 (flags & _TD3_MMU_PSTATS_HWM_MOD &&
  13245                  flags & _TD3_MMU_PSTATS_RESET_ON_READ)) {
  13246                 soc->pstats_mode = PSTATS_MODE_PKT_SYNC;
  13247                 pf |= _TD3_MMU_PSTATS_SYNC;
  13248             } else {
  13249                 soc->pstats_mode = PSTATS_MODE_PKT_BUFF;
  13250             }
  13251         } else {
  13252             soc->pstats_mode = PSTATS_MODE_OOB;
  13253         }
  13254     } else {
  13255         soc->pstats_mode = PSTATS_MODE_NULL;
  13256     }
  13257 
  13258     soc->pstats_flags = pf;
  13259 
  13260     rv = WRITE_MMU_GCFG_PKTSTAT_OOBSTATr(unit, rval);
  13261 
  13262     SOC_PSTATS_UNLOCK(unit);
  13263 
  13264     return rv;
  13265 }
  13266 
  13267 int
  13268 soc_trident3_mmu_pstats_mode_get(int unit, uint32 *flags)
  13269 {
  13270     int pf = 0;
  13271     uint32 rval = 0;
  13272     int rv;
  13273     soc_reg_t reg = MMU_GCFG_PKTSTAT_OOBSTATr;
  13274 
  13275     SOC_PSTATS_LOCK(unit);
  13276 
  13277     rv = READ_MMU_GCFG_PKTSTAT_OOBSTATr(unit, &rval);
  13278     if (SOC_FAILURE(rv)) {
  13279         SOC_PSTATS_UNLOCK(unit);
  13280         return rv;
  13281     }
  13282 
  13283     if (soc_reg_field_get(unit, reg, rval, ENABLEf)) {
  13284         pf |= _TD3_MMU_PSTATS_ENABLE;
  13285         if (soc_reg_field_get(unit, reg, rval, SELECTf)) {
  13286             pf |= _TD3_MMU_PSTATS_PKT_MOD;
  13287         }
  13288     }
  13289     if (soc_reg_field_get(unit, reg, rval, HWM_MODEf)) {
  13290         pf |= _TD3_MMU_PSTATS_HWM_MOD;
  13291         if (soc_reg_field_get(unit, reg, rval, HWM_RESET_ON_READf)) {
  13292             pf |= _TD3_MMU_PSTATS_RESET_ON_READ;
  13293         }
  13294     }
  13295 
  13296     SOC_PSTATS_UNLOCK(unit);
  13297 
  13298     *flags = pf;
  13299 
  13300     return SOC_E_NONE;
  13301 }
  13302 
  13303 int
  13304 soc_trident3_mmu_pstats_mor_enable(int unit)
  13305 {
  13306     soc_control_t *soc = SOC_CONTROL(unit);
  13307     uint32 rval;
  13308 
  13309 
  13310     if (soc->pstats_flags & _TD3_MMU_PSTATS_MOR_EN) {
  13311         SOC_IF_ERROR_RETURN(READ_MMU_GCFG_PKTSTAT_OOBSTATr(unit, &rval));
  13312         if ( ! soc_reg_field_get(unit,
  13313                                  MMU_GCFG_PKTSTAT_OOBSTATr, rval, MOR_ENf)) {
  13314             soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval, MOR_ENf, 1);
  13315             SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_PKTSTAT_OOBSTATr(unit, rval));
  13316         }
  13317     }
  13318 
  13319     return SOC_E_NONE;
  13320 }
  13321 
  13322 int
  13323 soc_trident3_mmu_pstats_mor_disable(int unit)
  13324 {
  13325     soc_control_t *soc = SOC_CONTROL(unit);
  13326     uint32 rval;
  13327 
  13328     if (!soc_feature(unit, soc_feature_mor_dma) &&
  13329         (soc->pstats_flags & _TD3_MMU_PSTATS_MOR_EN)) {
  13330         SOC_IF_ERROR_RETURN(READ_MMU_GCFG_PKTSTAT_OOBSTATr(unit, &rval));
  13331         soc_reg_field_set(unit, MMU_GCFG_PKTSTAT_OOBSTATr, &rval, MOR_ENf, 0);
  13332         SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_PKTSTAT_OOBSTATr(unit, rval));
  13333     }
  13334 
  13335     return SOC_E_NONE;
  13336 }
  13337 
  13338 int
  13339 soc_trident3_mmu_splitter_reset(int unit)
  13340 {
  13341     uint32 rval;
  13342 
  13343     SOC_IF_ERROR_RETURN(READ_MMU_GCFG_SPLITTERr(unit, &rval));
  13344     soc_reg_field_set(unit, MMU_GCFG_SPLITTERr, &rval, RESET_SBUSf, 1);
  13345     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_SPLITTERr(unit, rval));
  13346 
  13347     return SOC_E_NONE;
  13348 }
  13349 /*
  13350  * Function:
  13351  *      soc_td3_port_schedule_tdm_init
  13352  * Purpose:
  13353  *      Initialize TDM information in port_schedule_state that will be passed
  13354  *      to DV FlexPort API
  13355  * Parameters:
  13356  *      unit                 - (IN)  Unit number.
  13357  *      port_schedule_state  - (OUT) Port resource state.
  13358  * Returns:
  13359  *      BCM_E_xxx
  13360  * Notes:
  13361  *      If called during Scheduler Initialization, only below values need to be
  13362  *      properly set:
  13363  *        soc_tdm_schedule_pipe_t::num_slices
  13364  *        soc_tdm_schedule_t:: cal_len
  13365  *        soc_tdm_schedule_t:: num_ovs_groups
  13366  *        soc_tdm_schedule_t:: ovs_group_len
  13367  *        soc_tdm_schedule_t:: num_pkt_sch_or_ovs_space
  13368  *        soc_tdm_schedule_t:: pkt_sch_or_ovs_space_len
  13369  */
  13370 int
  13371 soc_td3_port_schedule_tdm_init(int unit,
  13372                             soc_port_schedule_state_t *port_schedule_state)
  13373 {
  13374     soc_control_t *soc = SOC_CONTROL(unit);
  13375     _soc_trident3_tdm_temp_t *tdm = soc->tdm_info;
  13376     /*soc_info_t *si = &SOC_INFO(unit);*/
  13377     soc_tdm_schedule_pipe_t *tdm_ischd, *tdm_eschd;
  13378     soc_tdm_schedule_t *sched;
  13379     int pipe, hpipe, phy_port, is_flexport, group, slot;
  13380     int *port_p2PBLK_inst_mapping;
  13381 
  13382     if (tdm == NULL) {
  13383         return SOC_E_INIT;
  13384     }
  13385 
  13386     is_flexport = port_schedule_state->is_flexport;
  13387 	/*
  13388     port_schedule_state->calendar_type = si->fabric_port_enable ?
  13389                                         _TD3_TDM_CALENDAR_UNIVERSAL :
  13390                                         _TD3_TDM_CALENDAR_ETHERNET_OPTIMIZED;
  13391 	*/
  13392     /* Construct tdm_ingress_schedule_pipe and tdm_egress_schedule_pipe */
  13393     for (pipe = 0; pipe <  TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
  13394         tdm_ischd = &port_schedule_state->tdm_ingress_schedule_pipe[pipe];
  13395         tdm_eschd = &port_schedule_state->tdm_egress_schedule_pipe[pipe];
  13396 
  13397         tdm_ischd->num_slices = TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE;
  13398         tdm_eschd->num_slices = TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE;
  13399 
  13400         if (is_flexport) {
  13401             /* TDM Calendar is always in slice 0 */
  13402             sal_memcpy(tdm_ischd->tdm_schedule_slice[0].linerate_schedule,
  13403                         tdm->tdm_pipe[pipe].idb_tdm,
  13404                         sizeof(int)*_TD3_TDM_LENGTH);
  13405             sal_memcpy(tdm_eschd->tdm_schedule_slice[0].linerate_schedule,
  13406                         tdm->tdm_pipe[pipe].mmu_tdm,
  13407                         sizeof(int)*_TD3_TDM_LENGTH);
  13408         }
  13409 
  13410         /* OVS */
  13411         for (hpipe = 0; hpipe < TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
  13412             /* IDB OVERSUB*/
  13413             sched = &tdm_ischd->tdm_schedule_slice[hpipe];
  13414             sched->cal_len = _TD3_TDM_LENGTH;
  13415             sched->num_ovs_groups = TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE;
  13416             sched->ovs_group_len = TRIDENT3_TDM_OVS_GROUP_LENGTH;
  13417             sched->num_pkt_sch_or_ovs_space = 1;
  13418             sched->pkt_sch_or_ovs_space_len = _TD3_PKT_SCH_LENGTH;
  13419 
  13420             if (is_flexport) {
  13421                 for (group = 0; group < TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE; group++) {
  13422                     for (slot = 0; slot < TRIDENT3_TDM_OVS_GROUP_LENGTH; slot++) {
  13423                         sched->oversub_schedule[group][slot] =
  13424                             tdm->tdm_pipe[pipe].ovs_tdm[hpipe][group][slot];
  13425                     }
  13426                 }
  13427                 for (slot = 0; slot < _TD3_PKT_SCH_LENGTH; slot++) {
  13428                     sched->pkt_sch_or_ovs_space[0][slot] =
  13429                         tdm->tdm_pipe[pipe].pkt_shaper_tdm[hpipe][slot];
  13430                 }
  13431             }
  13432 
  13433             /* MMU OVERSUB */
  13434             sched = &tdm_eschd->tdm_schedule_slice[hpipe];
  13435             sched->cal_len = _TD3_TDM_LENGTH;
  13436             sched->num_ovs_groups = TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE;
  13437             sched->ovs_group_len = TRIDENT3_TDM_OVS_GROUP_LENGTH;
  13438             sched->num_pkt_sch_or_ovs_space = 1;
  13439             sched->pkt_sch_or_ovs_space_len = _TD3_PKT_SCH_LENGTH;
  13440 
  13441             if (is_flexport) {
  13442                 for (group = 0; group < TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE; group++) {
  13443                     for (slot = 0; slot < TRIDENT3_TDM_OVS_GROUP_LENGTH; slot++) {
  13444                         sched->oversub_schedule[group][slot] =
  13445                             tdm->tdm_pipe[pipe].ovs_tdm[hpipe][group][slot];
  13446                         }
  13447                     }
  13448                 for (slot = 0; slot < _TD3_PKT_SCH_LENGTH; slot++) {
  13449                     sched->pkt_sch_or_ovs_space[0][slot] =
  13450                         tdm->tdm_pipe[pipe].pkt_shaper_tdm[hpipe][slot];
  13451                 }
  13452             }
  13453         }
  13454     }
  13455 
  13456     if (is_flexport) {
  13457         port_p2PBLK_inst_mapping =
  13458             port_schedule_state->in_port_map.port_p2PBLK_inst_mapping;
  13459         /* pblk info for phy_port */
  13460         for (phy_port = 1; phy_port < TD3_NUM_EXT_PORTS; phy_port++) {
  13461             if (tdm->pblk_info[phy_port].pblk_cal_idx == -1) {
  13462                 continue;
  13463             }
  13464             port_p2PBLK_inst_mapping[phy_port] =
  13465                                         tdm->pblk_info[phy_port].pblk_cal_idx;
  13466         }
  13467     }
  13468     return SOC_E_NONE;
  13469 }
  13470 
  13471 /*
  13472  * Function:
  13473  *      soc_td3_soc_tdm_update
  13474  * Purpose:
  13475  *      Update TDM information in SOC with TDM state return from DV FlexPort API
  13476  * Parameters:
  13477  *      unit                 - (IN)  Unit number.
  13478  *      port_schedule_state  - (OUT) Port resource state.
  13479  * Returns:
  13480  *      BCM_E_xxx
  13481  * Notes:
  13482  */
  13483 int
  13484 soc_td3_soc_tdm_update(int unit,
  13485                             soc_port_schedule_state_t *port_schedule_state)
  13486 {
  13487     soc_control_t *soc = SOC_CONTROL(unit);
  13488     soc_info_t *si = &SOC_INFO(unit);
  13489     _soc_trident3_tdm_temp_t *tdm = soc->tdm_info;
  13490     soc_tdm_schedule_pipe_t *tdm_ischd, *tdm_eschd;
  13491     soc_tdm_schedule_t *sched;
  13492     int pipe, hpipe, port, phy_port, clport, slot;
  13493     int length, ovs_core_slot_count, ovs_io_slot_count, port_slot_count;
  13494     int index, group;
  13495 
  13496     if (tdm == NULL) {
  13497         return SOC_E_INIT;
  13498     }
  13499 
  13500     /* Copy info from soc_port_schedule_state_t to _soc_trident3_tdm_temp_t */
  13501     for (pipe = 0; pipe <  TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
  13502         tdm_ischd = &port_schedule_state->tdm_ingress_schedule_pipe[pipe];
  13503         tdm_eschd = &port_schedule_state->tdm_egress_schedule_pipe[pipe];
  13504 
  13505         /* TDM Calendar is always in slice 0 */
  13506         sal_memcpy(tdm->tdm_pipe[pipe].idb_tdm,
  13507                     tdm_ischd->tdm_schedule_slice[0].linerate_schedule,
  13508                     sizeof(int)*_TD3_TDM_LENGTH);
  13509         sal_memcpy(tdm->tdm_pipe[pipe].mmu_tdm,
  13510                     tdm_eschd->tdm_schedule_slice[0].linerate_schedule,
  13511                     sizeof(int)*_TD3_TDM_LENGTH);
  13512 
  13513         for (hpipe = 0; hpipe < TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
  13514             sched = &tdm_ischd->tdm_schedule_slice[hpipe];
  13515             for (group = 0; group < TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE; group++) {
  13516                 for (slot = 0; slot < TRIDENT3_TDM_OVS_GROUP_LENGTH; slot++) {
  13517                     tdm->tdm_pipe[pipe].ovs_tdm[hpipe][group][slot] =
  13518                         sched->oversub_schedule[group][slot];
  13519                 }
  13520             }
  13521             for (slot = 0; slot < _TD3_PKT_SCH_LENGTH; slot++) {
  13522                 tdm->tdm_pipe[pipe].pkt_shaper_tdm[hpipe][slot] =
  13523                     sched->pkt_sch_or_ovs_space[0][slot];
  13524 
  13525             }
  13526         }
  13527     }
  13528 
  13529     /* pblk info init  */
  13530     for (phy_port = 1; phy_port < TD3_NUM_EXT_PORTS; phy_port++) {
  13531         tdm->pblk_info[phy_port].pblk_cal_idx = -1;
  13532         tdm->pblk_info[phy_port].pblk_hpipe_num = -1;
  13533     }
  13534 
  13535     /* pblk info for phy_port */
  13536     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
  13537         tdm_ischd = &port_schedule_state->tdm_ingress_schedule_pipe[pipe];
  13538         for (hpipe = 0; hpipe < TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
  13539             for (group = 0; group < TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE; group++) {
  13540                 for (index = 0; index < TRIDENT3_TDM_OVS_GROUP_LENGTH; index++) {
  13541                     phy_port =
  13542                         tdm_ischd->tdm_schedule_slice[hpipe].oversub_schedule[group][index];
  13543                     if (phy_port < TD3_NUM_EXT_PORTS) {
  13544                         tdm->pblk_info[phy_port].pblk_hpipe_num = hpipe;
  13545                         tdm->pblk_info[phy_port].pblk_cal_idx =
  13546                             port_schedule_state->out_port_map.port_p2PBLK_inst_mapping[phy_port];
  13547                     }
  13548                 }
  13549             }
  13550         }
  13551     }
  13552 
  13553     /* CLPORT port ratio */
  13554     for (clport = 0; clport < TRIDENT3_TDM_PBLKS_PER_DEV; clport++) {
  13555         soc_td3_tdm_get_port_ratio(unit, port_schedule_state, clport,
  13556             &tdm->port_ratio[clport], 1);
  13557     }
  13558 
  13559     /* Calculate the oversub ratio */
  13560     for (pipe = 0; pipe < TRIDENT3_TDM_PIPES_PER_DEV; pipe++) {
  13561         tdm_ischd = &port_schedule_state->tdm_ingress_schedule_pipe[pipe];
  13562         /* Count number of OVSB_TOKEN assigned by the TDM code */
  13563         for (length = _TD3_TDM_LENGTH; length > 0; length--) {
  13564             if (tdm_ischd->tdm_schedule_slice[0].linerate_schedule[length - 1]
  13565                     != TD3_NUM_EXT_PORTS) {
  13566                 break;
  13567             }
  13568         }
  13569         ovs_core_slot_count = 0;
  13570         for (index = 0; index < length; index++) {
  13571             if (tdm_ischd->tdm_schedule_slice[0].linerate_schedule[index]
  13572                     == TD3_OVSB_TOKEN) {
  13573                 ovs_core_slot_count++;
  13574             }
  13575         }
  13576 
  13577         /* Count number of slot needed for half-pipe's oversub I/O bandwidth */
  13578         for (hpipe = 0; hpipe < TRIDENT3_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
  13579             ovs_io_slot_count = 0;
  13580             for (group = 0; group < TRIDENT3_TDM_OVS_GROUPS_PER_HPIPE; group++) {
  13581                 for (index = 0; index < TRIDENT3_TDM_OVS_GROUP_LENGTH; index++) {
  13582                     phy_port = tdm_ischd->tdm_schedule_slice[hpipe].oversub_schedule[group][index];
  13583                     if (phy_port == TD3_NUM_EXT_PORTS) {
  13584                         continue;
  13585                     }
  13586                     port = si->port_p2l_mapping[phy_port];
  13587 					
  13588                     if ((port == -1) || IS_CPU_PORT(unit, port) ||
  13589                         IS_LB_PORT(unit, port) ||
  13590                         (phy_port ==TRIDENT3_TDM_PHY_MGMT0)) {
  13591                         LOG_ERROR(BSL_LS_SOC_PORT,
  13592                                   (BSL_META_U(unit,
  13593                                               "Flexport: Invalid physical "
  13594                                               "port %d in OverSub table.\n"),
  13595                                    phy_port));
  13596                         continue;
  13597                     }
  13598                     port_slot_count = si->port_speed_max[port] / 2500;
  13599                     ovs_io_slot_count += port_slot_count;
  13600                 }
  13601             }
  13602             if (ovs_core_slot_count != 0) {
  13603                 tdm->ovs_ratio_x1000[pipe][hpipe] =
  13604                     ovs_io_slot_count * 1000 / (ovs_core_slot_count / 2);
  13605             }
  13606         }
  13607     }
  13608 
  13609     return SOC_E_NONE;
  13610 }
  13611 
  13612 STATIC int
  13613 _soc_trident3_mmu_port_empty_check(int unit, soc_port_t port, int *empty)
  13614 {
  13615     soc_reg_t status_reg[2] = {Q_SCHED_PORT_EMPTY_STATUS_SPLIT0r,
  13616                                Q_SCHED_PORT_EMPTY_STATUS_SPLIT1r};
  13617     soc_reg_t reg;
  13618     int pipe, split, pos;
  13619     uint64 rval64;
  13620 
  13621     SOC_IF_ERROR_RETURN(
  13622         soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos));
  13623     reg = status_reg[split];
  13624 
  13625     COMPILER_64_ZERO(rval64);
  13626     SOC_IF_ERROR_RETURN
  13627         (soc_reg_get(unit, reg, pipe, 0, &rval64));
  13628 
  13629     if (pos < 32) {
  13630         *empty = COMPILER_64_LO(rval64) & (1 << pos) ? TRUE : FALSE;
  13631     } else {
  13632         *empty = COMPILER_64_HI(rval64) & (1 << (pos - 32)) ?
  13633                  TRUE : FALSE;
  13634     }
  13635 
  13636     return SOC_E_NONE;
  13637 }
  13638 
  13639 int
  13640 soc_trident3_mmu_port_flush_hw(int unit, soc_port_t port, uint32 drain_timeout)
  13641 {
  13642     uint64 rval64;
  13643     uint64 pbits64, mtro64;
  13644     uint32 rval;
  13645     int pipe, split;
  13646     int empty, pos;
  13647     soc_timeout_t to;
  13648     soc_reg_t flush_reg, mtro_reg;
  13649     soc_field_t initiate_val;
  13650     soc_reg_t reg_flush[2] = {Q_SCHED_PORT_FLUSH_SPLIT0r,
  13651                               Q_SCHED_PORT_FLUSH_SPLIT1r};
  13652     soc_reg_t reg_mtro[2] = {MTRO_PORT_ENTITY_DISABLE_SPLIT0r,
  13653                              MTRO_PORT_ENTITY_DISABLE_SPLIT1r};
  13654 
  13655     COMPILER_64_ZERO(rval64);
  13656     COMPILER_64_ZERO(pbits64);
  13657 
  13658     SOC_IF_ERROR_RETURN(
  13659         soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos));
  13660     flush_reg = reg_flush[split];
  13661     mtro_reg = reg_mtro[split];
  13662 
  13663     if (pos < 32) {
  13664         COMPILER_64_SET(pbits64, 0, (1 << pos));
  13665     } else {
  13666         COMPILER_64_SET(pbits64, (1 << (pos - 32)), 0);
  13667     }
  13668 
  13669     SOC_IF_ERROR_RETURN
  13670         (_soc_trident3_mmu_port_empty_check(unit, port, &empty));
  13671     if (empty) {
  13672         return SOC_E_NONE;
  13673     }
  13674 
  13675     /* Read the Port flush Register */
  13676     SOC_IF_ERROR_RETURN
  13677         (soc_reg_get(unit, flush_reg, pipe, 0, &rval64));
  13678 
  13679     COMPILER_64_OR(rval64, pbits64);
  13680 
  13681     /* Port Not Empty - Initiate Flush */
  13682     /* ENABLEf is the only field in FLUSH reg. Hence writing it directly */
  13683     SOC_IF_ERROR_RETURN
  13684         (soc_reg_set(unit, flush_reg, pipe, 0, rval64));
  13685 
  13686     /* Disable Shaper Updates */
  13687     SOC_IF_ERROR_RETURN
  13688         (soc_reg_get(unit, mtro_reg, pipe, 0, &rval64));
  13689     COMPILER_64_COPY(mtro64, rval64);
  13690     COMPILER_64_AND(mtro64, pbits64);
  13691 
  13692     COMPILER_64_OR(rval64, pbits64);
  13693 
  13694     /* METERING_DISABLEf is the only field in reg. Hence writing it directly */
  13695     SOC_IF_ERROR_RETURN
  13696         (soc_reg_set(unit, mtro_reg, pipe, 0, rval64));
  13697 
  13698     /* Initiate RQE FIFO Flush */
  13699     SOC_IF_ERROR_RETURN
  13700         (soc_reg32_get(unit, Q_SCHED_RQE_SNAPSHOTr, pipe, 0, &rval));
  13701     initiate_val = 0x1;
  13702     soc_reg_field_set(unit, Q_SCHED_RQE_SNAPSHOTr, &rval,
  13703                       INITIATEf, initiate_val);
  13704     SOC_IF_ERROR_RETURN
  13705         (soc_reg32_set(unit, Q_SCHED_RQE_SNAPSHOTr, pipe, 0, rval));
  13706 
  13707     /* Restart timeout */
  13708     initiate_val = 0x1;
  13709     empty = 0;
  13710     soc_timeout_init(&to, drain_timeout, 0);
  13711     for (;;) {
  13712         if (initiate_val != 0) {
  13713             SOC_IF_ERROR_RETURN
  13714                 (soc_reg32_get(unit, Q_SCHED_RQE_SNAPSHOTr, pipe, 0, &rval));
  13715             initiate_val = soc_reg_field_get(unit, Q_SCHED_RQE_SNAPSHOTr,
  13716                                              rval, INITIATEf);
  13717         } else {    /* Completion of Snapshot Process */
  13718             SOC_IF_ERROR_RETURN
  13719                 (_soc_trident3_mmu_port_empty_check(unit, port, &empty));
  13720             if (empty) {
  13721                 break;
  13722             }
  13723         }
  13724 
  13725         if (soc_timeout_check(&to)) {
  13726             SOC_IF_ERROR_RETURN
  13727                 (soc_reg32_get(unit, Q_SCHED_RQE_SNAPSHOTr, pipe, 0, &rval));
  13728             initiate_val = soc_reg_field_get(unit, Q_SCHED_RQE_SNAPSHOTr,
  13729                                              rval, INITIATEf);
  13730             if (initiate_val == 0) {
  13731                 /* Completion of Snapshot Process */
  13732                 SOC_IF_ERROR_RETURN
  13733                     (_soc_trident3_mmu_port_empty_check(unit, port, &empty));
  13734             }
  13735             break;
  13736         }
  13737     }
  13738 
  13739     COMPILER_64_NOT(pbits64);
  13740     /* Restore Shaper Updates */
  13741     SOC_IF_ERROR_RETURN
  13742         (soc_reg_get(unit, mtro_reg, pipe, 0, &rval64));
  13743     COMPILER_64_AND(rval64, pbits64);
  13744     COMPILER_64_OR(rval64, mtro64);
  13745     /* METERING_DISABLEf is the only field in reg. Hence writing it directly */
  13746     SOC_IF_ERROR_RETURN
  13747         (soc_reg_set(unit, mtro_reg, pipe, 0, rval64));
  13748 
  13749     /* Read the Port flush Register */
  13750     SOC_IF_ERROR_RETURN
  13751         (soc_reg_get(unit, flush_reg, pipe, 0, &rval64));
  13752     COMPILER_64_AND(rval64, pbits64);
  13753     /* Port Empty - Disable Flush */
  13754     /* ENABLEf is the only field in FLUSH reg. Hence writing it directly */
  13755     SOC_IF_ERROR_RETURN
  13756         (soc_reg_set(unit, flush_reg, pipe, 0, rval64));
  13757 
  13758     if ((initiate_val == 0) && (empty)) {
  13759         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  13760                     (BSL_META_U(unit,
  13761                     "MacDrain:port %d,%s, "
  13762                     "Drained successfully\n"),
  13763                     unit, SOC_PORT_NAME(unit, port)));
  13764     } else {
  13765         LOG_ERROR(BSL_LS_SOC_COMMON,
  13766                   (BSL_META_U(unit,
  13767                   "MacDrainError:port %d,%s, "
  13768                   "Unable to drain packets from MMU\n"),
  13769                   unit, SOC_PORT_NAME(unit, port)));
  13770         return SOC_E_INTERNAL;
  13771     }
  13772     return SOC_E_NONE;
  13773 }
  13774 
  13775 soc_error_t
  13776 soc_td3_subsidiary_ports_get(int unit, soc_port_t port, soc_pbmp_t *pbmp)
  13777 {
  13778     soc_info_t *si = &SOC_INFO(unit);
  13779     soc_port_t phy_port_base, phy_port;
  13780     soc_pbmp_t pbm;
  13781     int max_subport;
  13782 
  13783     if (!SOC_PORT_VALID(unit, port) || IS_CPU_PORT(unit, port) ||
  13784         IS_LB_PORT(unit, port) ||
  13785         SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
  13786          /* CPU, LB and Management ports do not support flexport */
  13787         return SOC_E_PORT;
  13788     }
  13789 
  13790     phy_port = si->port_l2p_mapping[port];
  13791     if (-1 == phy_port) {
  13792         return SOC_E_PORT;
  13793     }
  13794     phy_port_base = PORT_BLOCK_BASE_PORT(port);
  13795 
  13796     /* Only lane 0 and lane 2 of a PM can be controlling ports */
  13797     if ((phy_port_base != phy_port) && ((phy_port_base + 2) != phy_port)) {
  13798         /* Not a controlling port */
  13799         return SOC_E_PORT;
  13800     }
  13801     max_subport = phy_port + (4 - ((phy_port - 1) % 4));
  13802     SOC_PBMP_CLEAR(pbm);
  13803     for (; phy_port < max_subport; phy_port++) {
  13804         if (si->port_p2l_mapping[phy_port] == -1) {
  13805             continue;
  13806         }
  13807         SOC_PBMP_PORT_ADD(pbm, si->port_p2l_mapping[phy_port]);
  13808     }
  13809     SOC_PBMP_ASSIGN(*pbmp, pbm);
  13810 
  13811     return SOC_E_NONE;
  13812 }
  13813 
  13814 int
  13815 soc_td3_mpls_hash_control_set(int *hash_entry)
  13816 {
  13817     int unit = 0;
  13818     int mpls_16k_banks = 0,mpls_8k_banks = 0;
  13819     int uat_16k_banks = 0,uat_8k_banks = 0;
  13820     int index = 0;
  13821     int num_entries = 0, shared_hash_offset = 0;
  13822     int hash_control_entry[2];
  13823     uint32 shared_hash_control_entry[4];
  13824     uint32 shared_8k_hash_control_entry[4];
  13825 
  13826     static const soc_field_t logical_to_physical_fields[] = {
  13827         LOGICAL_BANK_0_PHYSICAL_BANK_LOCATIONf,
  13828         LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf,
  13829         LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf,
  13830         LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf,
  13831         LOGICAL_BANK_4_PHYSICAL_BANK_LOCATIONf,
  13832         LOGICAL_BANK_5_PHYSICAL_BANK_LOCATIONf,
  13833         LOGICAL_BANK_6_PHYSICAL_BANK_LOCATIONf,
  13834         LOGICAL_BANK_7_PHYSICAL_BANK_LOCATIONf,
  13835         LOGICAL_BANK_8_PHYSICAL_BANK_LOCATIONf,
  13836         LOGICAL_BANK_9_PHYSICAL_BANK_LOCATIONf
  13837     };
  13838 
  13839     static const soc_field_t shared_fields[] = {
  13840         B0_HASH_OFFSETf, B1_HASH_OFFSETf, B2_HASH_OFFSETf, B3_HASH_OFFSETf,
  13841         B4_HASH_OFFSETf, B5_HASH_OFFSETf, B6_HASH_OFFSETf, B7_HASH_OFFSETf
  13842     };
  13843 
  13844     sal_memset(hash_control_entry, 0,
  13845             sizeof(mpls_entry_hash_control_entry_t));
  13846     sal_memset(shared_hash_control_entry, 0,
  13847             sizeof(uft_shared_banks_control_entry_t));
  13848     sal_memset(shared_8k_hash_control_entry, 0,
  13849             sizeof(ip_uat_8k_shared_banks_control_entry_t));
  13850 
  13851     SOC_IF_ERROR_RETURN
  13852         (READ_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ANY, 0,
  13853                                         shared_hash_control_entry));
  13854     SOC_IF_ERROR_RETURN
  13855         (READ_IP_UAT_8K_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ANY, 0,
  13856                                               shared_8k_hash_control_entry));
  13857     SOC_IF_ERROR_RETURN
  13858         (READ_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
  13859                                        hash_control_entry));
  13860     sal_memcpy(hash_entry, hash_control_entry, sizeof(hash_control_entry));
  13861 
  13862     num_entries = soc_mem_index_count(unit, MPLS_ENTRY_SINGLEm);
  13863     SOC_IF_ERROR_RETURN(soc_trident3_iuat_sizing(unit, num_entries,
  13864                 &uat_16k_banks, &uat_8k_banks));
  13865     mpls_16k_banks = uat_16k_banks;
  13866     mpls_8k_banks = uat_8k_banks;
  13867 
  13868     soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, hash_control_entry,
  13869             HASH_TABLE_BANK_CONFIGf, (((1 << mpls_8k_banks) - 1) |
  13870                 (((1 << mpls_16k_banks) - 1) << 4)));
  13871 
  13872     for(index = 0; index < mpls_8k_banks; index++) {
  13873         shared_hash_offset = (index == (mpls_8k_banks-1))?
  13874                                TD3_UAT_8K_HASH_OFFSET_MAX :
  13875                                ((index * TD3_UAT_8K_HASH_OFFSET_MAX) / (mpls_8k_banks-1));
  13876         soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, hash_control_entry,
  13877                 logical_to_physical_fields[index], index);
  13878         soc_mem_field32_set(unit, IP_UAT_8K_SHARED_BANKS_CONTROLm,
  13879                 shared_8k_hash_control_entry, shared_fields[index],
  13880                 shared_hash_offset);
  13881     }
  13882 
  13883     for(index = 0; index < mpls_16k_banks; index++) {
  13884         shared_hash_offset = (index == (mpls_16k_banks-1))?
  13885                                TD3_UAT_16K_HASH_OFFSET_MAX :
  13886                                ((index * TD3_UAT_16K_HASH_OFFSET_MAX) / (mpls_16k_banks-1));
  13887         soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm,
  13888                 hash_control_entry,
  13889                 logical_to_physical_fields[index], index + 4);
  13890         soc_mem_field32_set(unit, IP_UAT_16K_SHARED_BANKS_CONTROLm,
  13891                 shared_hash_control_entry, shared_fields[index],
  13892                 shared_hash_offset);
  13893     }
  13894 
  13895     SOC_IF_ERROR_RETURN
  13896         (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
  13897                                         hash_control_entry));
  13898 
  13899     return SOC_E_NONE;
  13900 }
  13901 void soc_td3_hgoe_feature_update(int unit) {
  13902     if (!soc_feature(unit, soc_feature_higig_over_ethernet)) {
  13903         return;
  13904     }
  13905     /* if HGOE is enabled, disable the following features */
  13906     /* L3 */
  13907     SOC_FEATURE_CLEAR(unit, soc_feature_l3);
  13908     SOC_FEATURE_CLEAR(unit, soc_feature_l3_ip6);
  13909     SOC_FEATURE_CLEAR(unit, soc_feature_l3_entry_key_type);
  13910     SOC_FEATURE_CLEAR(unit, soc_feature_lpm_tcam);
  13911     SOC_FEATURE_CLEAR(unit, soc_feature_ip_mcast);
  13912     SOC_FEATURE_CLEAR(unit, soc_feature_ip_mcast_repl);
  13913     SOC_FEATURE_CLEAR(unit, soc_feature_ipmc_unicast);
  13914     SOC_FEATURE_CLEAR(unit, soc_feature_ipmc_use_configured_dest_mac);
  13915     SOC_FEATURE_CLEAR(unit, soc_feature_urpf);
  13916     SOC_FEATURE_CLEAR(unit, soc_feature_l3mc_use_egress_next_hop);
  13917     SOC_FEATURE_CLEAR(unit, soc_feature_l3_sgv);
  13918     SOC_FEATURE_CLEAR(unit, soc_feature_l3_dynamic_ecmp_group);
  13919     SOC_FEATURE_CLEAR(unit, soc_feature_l3_ingress_interface);
  13920     SOC_FEATURE_CLEAR(unit, soc_feature_l3_iif_zero_invalid);
  13921     SOC_FEATURE_CLEAR(unit, soc_feature_l3_iif_under_4k);
  13922     SOC_FEATURE_CLEAR(unit, soc_feature_ecmp_dlb);
  13923     SOC_FEATURE_CLEAR(unit, soc_feature_ecmp_dlb_optimized);
  13924     SOC_FEATURE_CLEAR(unit, soc_feature_ecmp_dlb_property_force_set);
  13925     SOC_FEATURE_CLEAR(unit, soc_feature_l3_iif_profile);
  13926     SOC_FEATURE_CLEAR(unit, soc_feature_l3_ingress_interface);
  13927     SOC_FEATURE_CLEAR(unit, soc_feature_nat);
  13928     SOC_FEATURE_CLEAR(unit, soc_feature_l2gre);
  13929     SOC_FEATURE_CLEAR(unit, soc_feature_l2gre_default_tunnel);
  13930     SOC_FEATURE_CLEAR(unit, soc_feature_l3_lookup_cmd);
  13931     SOC_FEATURE_CLEAR(unit, soc_feature_l3_shared_defip_table);
  13932     SOC_FEATURE_CLEAR(unit, soc_feature_l3_ip4_options_profile);
  13933     SOC_FEATURE_CLEAR(unit, soc_feature_repl_l3_intf_use_next_hop);
  13934     SOC_FEATURE_CLEAR(unit, soc_feature_l3_extended_host_entry);
  13935     SOC_FEATURE_CLEAR(unit, soc_feature_l3_ecmp_1k_groups);
  13936     SOC_FEATURE_CLEAR(unit, soc_feature_l3_defip_map);
  13937     SOC_FEATURE_CLEAR(unit, soc_feature_l3_host_ecmp_group);
  13938     SOC_FEATURE_CLEAR(unit, soc_feature_niv);
  13939     SOC_FEATURE_CLEAR(unit, soc_feature_vlan_vp);
  13940     SOC_FEATURE_CLEAR(unit, soc_feature_vp_lag);
  13941     SOC_FEATURE_CLEAR(unit, soc_feature_virtual_switching);
  13942     SOC_FEATURE_SET(unit, soc_feature_int_common_init);
  13943     SOC_FEATURE_CLEAR(unit, soc_feature_mim);
  13944 
  13945     /* ALPM */
  13946     SOC_FEATURE_CLEAR(unit, soc_feature_alpm);
  13947     SOC_FEATURE_CLEAR(unit, soc_feature_alpm2);
  13948 
  13949     /* MPLS */
  13950 
  13951     SOC_FEATURE_CLEAR(unit, soc_feature_mpls);
  13952     SOC_FEATURE_CLEAR(unit, soc_feature_mpls_enhanced);
  13953     SOC_FEATURE_CLEAR(unit, soc_feature_mpls_entropy);
  13954     SOC_FEATURE_CLEAR(unit, soc_feature_td2p_mpls_entropy_label);
  13955     SOC_FEATURE_CLEAR(unit, soc_feature_mpls_lsr_ecmp);
  13956     SOC_FEATURE_CLEAR(unit, soc_feature_mpls_segment_routing);
  13957     SOC_FEATURE_CLEAR(unit, soc_feature_mpls_failover);
  13958     SOC_FEATURE_CLEAR(unit, soc_feature_flex_ctr_mpls_3_label_count);
  13959     SOC_FEATURE_CLEAR(unit, soc_feature_mpls_exp_to_phb_cng_map);
  13960     SOC_FEATURE_CLEAR(unit, soc_feature_mpls_software_failover);
  13961     SOC_FEATURE_CLEAR(unit, soc_feature_mpls_frr);
  13962 
  13963     /* VXLAN */
  13964     SOC_FEATURE_CLEAR(unit, soc_feature_vxlan);
  13965     SOC_FEATURE_CLEAR(unit, soc_feature_vrf_aware_vxlan_termination);
  13966 
  13967     /* TRILL */
  13968     SOC_FEATURE_CLEAR(unit, soc_feature_trill);
  13969     SOC_FEATURE_CLEAR(unit, soc_feature_fcoe);
  13970 
  13971 }
  13972 
  13973 /*
  13974  * Enable flow based UDF extraction.
  13975  * Few containers are disabled by default for certain flows.
  13976  * This routine enables UDF extraction for various protocols
  13977  */
  13978 
  13979 int
  13980 soc_td3_flow_based_udf_enable(int unit)
  13981 {
  13982 
  13983     uint32 rval = 0;
  13984 
  13985     if (!soc_feature(unit, soc_feature_enable_flow_based_udf_extraction)) {
  13986         return SOC_E_NONE;
  13987     }
  13988 
  13989 
  13990     SOC_IF_ERROR_RETURN(READ_EGR_FLEX_CONFIGr(unit, &rval));
  13991     soc_reg_field_set(unit, EGR_FLEX_CONFIGr, &rval,
  13992                       ENABLE_FLEX_MIM_ISID_EXTRACTIONf, 1);
  13993     SOC_IF_ERROR_RETURN(WRITE_EGR_FLEX_CONFIGr(unit, rval));
  13994 
  13995     rval = 0;
  13996     SOC_IF_ERROR_RETURN(READ_ING_FLEX_CONFIGr(unit, &rval));
  13997     soc_reg_field_set(unit, ING_FLEX_CONFIGr, &rval,
  13998                       ENABLE_BFD_VER_EXTRACTIONf, 1);
  13999     soc_reg_field_set(unit, ING_FLEX_CONFIGr, &rval,
  14000                       ENABLE_IPSEC_SPI_EXTRACTIONf, 1);
  14001     soc_reg_field_set(unit, ING_FLEX_CONFIGr, &rval,
  14002                       ENABLE_IPV4_FLAGS_FRAG_OFFSET_EXTRACTIONf, 1);
  14003     soc_reg_field_set(unit, ING_FLEX_CONFIGr, &rval,
  14004                       ENABLE_LLC_HDR_EXTRACTIONf, 1);
  14005     soc_reg_field_set(unit, ING_FLEX_CONFIGr, &rval,
  14006                       GPE_IOAM_ENABLEf, 1);
  14007     SOC_IF_ERROR_RETURN(WRITE_ING_FLEX_CONFIGr(unit, rval));
  14008 
  14009     return SOC_E_NONE;
  14010 }
  14011 
  14012 /*
  14013  * Trident3 chip driver functions.
  14014  * Pls keep at the end of this file for easy access.
  14015  */
  14016 soc_functions_t soc_trident3_drv_funs = {
  14017     _soc_trident3_misc_init,
  14018     _soc_trident3_mmu_init,
  14019     soc_trident3_age_timer_get,
  14020     soc_trident3_age_timer_max_get,
  14021     soc_trident3_age_timer_set,
  14022     soc_trident3_tscx_firmware_set,
  14023     _soc_trident3_tscx_reg_read,
  14024     _soc_trident3_tscx_reg_write,
  14025     soc_trident3_bond_info_init,
  14026 };
  14027 #endif /* BCM_TOMAHAWK_SUPPORT */