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

tomahawk.c (550491B)


      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:        tomahawk.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 #ifdef BCM_CMICX_SUPPORT
     20 #include <soc/cmicx.h>
     21 #endif
     22 #include <soc/bradley.h>
     23 #include <soc/drv.h>
     24 #include <soc/error.h>
     25 #include <soc/debug.h>
     26 #include <soc/mem.h>
     27 #include <soc/i2c.h>
     28 #include <soc/l2x.h>
     29 #include <soc/soc_ser_log.h>
     30 
     31 #ifdef BCM_TOMAHAWK_SUPPORT
     32 
     33 #ifdef ALPM_ENABLE
     34 #include <soc/lpm.h>
     35 #include <soc/alpm.h>
     36 #include <soc/esw/alpm_int.h>
     37 #endif /* ALPM_ENABLE */
     38 
     39 #include <soc/mmu_config.h>
     40 #include <soc/tomahawk.h>
     41 #include <soc/trident2.h>
     42 
     43 #ifdef BCM_TOMAHAWK2_SUPPORT
     44 #include <soc/tomahawk2.h>
     45 #endif
     46 
     47 #ifdef BCM_TOMAHAWK3_SUPPORT
     48 #include <soc/tomahawk3.h>
     49 #endif
     50 
     51 #include <soc/drv.h>
     52 #ifdef BCM_IPROC_SUPPORT
     53 #include <soc/iproc.h>
     54 #endif
     55 
     56 
     57 #define PORT_BLOCK_BASE_PORT(port) \
     58         (1 + ((SOC_INFO(unit).port_l2p_mapping[port] - 1) & ~0x3));
     59 
     60 #define _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ptype) \
     61     si->ptype.num = 0; \
     62     si->ptype.min = si->ptype.max = -1; \
     63     PBMP_ITER(si->ptype.bitmap, it_port) { \
     64         si->ptype.port[si->ptype.num++] = it_port; \
     65         if (si->ptype.min < 0) { \
     66             si->ptype.min = it_port; \
     67         } \
     68         if (it_port > si->ptype.max) { \
     69             si->ptype.max = it_port; \
     70         } \
     71     }
     72 
     73 #define _TH_SUBS_ACC_TYPE_DUPLICATE            9
     74 
     75 static const soc_reg_t idb_grp_tbl_regs[] = {
     76     IS_OVR_SUB_GRP0_TBLr, IS_OVR_SUB_GRP1_TBLr,
     77     IS_OVR_SUB_GRP2_TBLr, IS_OVR_SUB_GRP3_TBLr,
     78     IS_OVR_SUB_GRP4_TBLr, IS_OVR_SUB_GRP5_TBLr
     79 };
     80 
     81 static const soc_reg_t mmu_grp_tbl_regs[] = {
     82     OVR_SUB_GRP0_TBLr, OVR_SUB_GRP1_TBLr,
     83     OVR_SUB_GRP2_TBLr, OVR_SUB_GRP3_TBLr,
     84     OVR_SUB_GRP4_TBLr, OVR_SUB_GRP5_TBLr
     85 };
     86 
     87 static soc_speed_group_info_t  soc_speed_group_info[] = {
     88     {SOC_TH_SPEED_CLASS_10G, SOC_TH_PORT_MODE_QUAD,    4, 3,  "10G_SPEED_CLASS"},
     89     {SOC_TH_SPEED_CLASS_20G, SOC_TH_PORT_MODE_DUAL,    2, 6,  "20G_SPEED_CLASS"},
     90     {SOC_TH_SPEED_CLASS_25G, SOC_TH_PORT_MODE_QUAD,    4, 3,  "25G_SPEED_CLASS"},
     91     {SOC_TH_SPEED_CLASS_40G, SOC_TH_PORT_MODE_DUAL,    2, 6,  "40Gd_SPEED_CLASS"},
     92     {SOC_TH_SPEED_CLASS_40G, SOC_TH_PORT_MODE_SINGLE,  1, 12, "40Gs_SPEED_CLASS"},
     93     {SOC_TH_SPEED_CLASS_50G, SOC_TH_PORT_MODE_DUAL,    2, 6,  "50G_SPEED_CLASS"},
     94     {SOC_TH_SPEED_CLASS_100G, SOC_TH_PORT_MODE_SINGLE, 1, 12, "100G_SPEED_CLASS"}
     95 };
     96 
     97 static int soc_speed_group_info_size = sizeof(soc_speed_group_info) / sizeof(soc_speed_group_info_t);
     98 
     99 static int num_shared_alpm_banks[SOC_MAX_NUM_DEVICES] = {0};
    100 
    101 static soc_mem_t *_soc_th_alpm_bkt_view_map[SOC_MAX_NUM_DEVICES];
    102 static soc_mem_t *_soc_th_lpm_view_map[SOC_MAX_NUM_DEVICES];
    103 
    104 
    105 static uint32 _soc_th_iss_log_to_phy_bank_map_shadow[SOC_MAX_NUM_DEVICES];
    106 
    107 soc_pbmp_t loopback_disable[SOC_MAX_NUM_DEVICES];
    108 
    109 typedef void (*soc_mmu_config_buf_default_f)(int unit, _soc_mmu_cfg_buf_t *buf,
    110                                              _soc_mmu_device_info_t *devcfg,
    111                                              int lossless);
    112 STATIC soc_error_t
    113 _soc_tomahawk_flexed_port_speed_get(int unit, soc_th_port_lanes_t *lanes_ctrl,
    114                                      uint32 *port_speed);
    115 STATIC int
    116 soc_th_port_lanes_ctrl_info_diag(int unit, soc_th_port_lanes_t *lanes_ctrl);
    117 STATIC int
    118 soc_tomahawk_oversub_group_find(int unit, soc_th_port_lanes_t *lanes_ctrl);
    119 STATIC int
    120 _soc_tomahawk_port_lanes_update_tdm(int unit, soc_th_port_lanes_t *lanes_ctrl);
    121 STATIC int
    122 _soc_th_default_pg_headroom(int unit, soc_port_t port, int lossless);
    123 STATIC soc_error_t
    124 soc_th_os_mixed_sister_port_mode_get(int unit, int initTime, soc_th_port_lanes_t *lanes_ctrl);
    125 STATIC int
    126 _soc_tomahawk_obm_thresholds_reconfigure(int unit, soc_port_t port_conf);
    127 STATIC int
    128 soc_th_speed_group_consolidate_check(int unit, soc_th_port_lanes_t *lanes_ctrl, int flag);
    129 STATIC int
    130 soc_th_speed_group_migrate(int unit, soc_th_port_lanes_t *lanes_ctrl, int flag);
    131 
    132 STATIC int
    133 _soc_tomahawk_mmu_port_empty_check(int unit, soc_port_t port, int *empty)
    134 {
    135     soc_reg_t status_reg = Q_SCHED_PORT_EMPTY_STATUSr;
    136     soc_info_t *si = &SOC_INFO(unit);
    137     int pipe, phy_port, mmu_port;
    138     uint64 rval64;
    139 
    140     pipe = si->port_pipe[port];
    141     phy_port = si->port_l2p_mapping[port];
    142     mmu_port = si->port_p2m_mapping[phy_port];
    143     COMPILER_64_ZERO(rval64);
    144     SOC_IF_ERROR_RETURN
    145         (soc_reg_get(unit, status_reg, pipe, 0, &rval64));
    146 
    147     /* Reg config is per pipe */
    148     mmu_port %= SOC_TH_MMU_PORT_STRIDE;
    149 
    150     if (mmu_port < 32) {
    151         *empty = COMPILER_64_LO(rval64) & (1 << mmu_port) ? TRUE : FALSE;
    152     } else {
    153         *empty = COMPILER_64_HI(rval64) & (1 << (mmu_port - 32)) ?
    154                  TRUE : FALSE;
    155     }
    156 
    157     return SOC_E_NONE;
    158 }
    159 
    160 int
    161 soc_tomahawk_mmu_port_flush_hw(int unit, soc_port_t port, uint32 drain_timeout)
    162 {
    163     soc_info_t *si;
    164     uint64 rval64;
    165     uint64 temp64;
    166     uint32 rval;
    167     int pipe;
    168     int empty;
    169     soc_timeout_t to;
    170     int phy_port, mmu_port;
    171     soc_field_t initiate_val;
    172 
    173     COMPILER_64_ZERO(rval64);
    174     COMPILER_64_ZERO(temp64);
    175     si = &SOC_INFO(unit);
    176     pipe = si->port_pipe[port];
    177 
    178     phy_port = si->port_l2p_mapping[port];
    179     mmu_port = si->port_p2m_mapping[phy_port];
    180 
    181     /* Reg config is per pipe */
    182     mmu_port %= SOC_TH_MMU_PORT_STRIDE;
    183 
    184     if (mmu_port < 32) {
    185         COMPILER_64_SET(temp64, 0, (1 << mmu_port));
    186     } else {
    187         COMPILER_64_SET(temp64, (1 << (mmu_port - 32)), 0);
    188     }
    189 
    190     SOC_IF_ERROR_RETURN
    191         (_soc_tomahawk_mmu_port_empty_check(unit, port, &empty));
    192 
    193     if (empty) {
    194         return SOC_E_NONE;
    195     }
    196 
    197     /* Read the Port flush Register */
    198     SOC_IF_ERROR_RETURN
    199         (soc_reg_get(unit, Q_SCHED_PORT_FLUSHr, pipe, 0, &rval64));
    200 
    201     COMPILER_64_OR(rval64, temp64);
    202 
    203     /* Port Not Empty - Initiate Flush */
    204     /* ENABLEf is the only field in FLUSH reg. Hence writing it directly */
    205     SOC_IF_ERROR_RETURN
    206         (soc_reg_set(unit, Q_SCHED_PORT_FLUSHr, pipe, 0, rval64));
    207 
    208     /* Disable Shaper Updates */
    209     SOC_IF_ERROR_RETURN
    210         (soc_reg_get(unit, MTRO_PORT_ENTITY_DISABLEr, pipe, 0, &rval64));
    211 
    212     COMPILER_64_OR(rval64, temp64);
    213 
    214     /* METERING_DISABLEf is the only field in reg. Hence writing it directly */
    215     SOC_IF_ERROR_RETURN
    216         (soc_reg_set(unit, MTRO_PORT_ENTITY_DISABLEr, pipe, 0, rval64));
    217 
    218     /* Initiate RQE FIFO Flush */
    219     SOC_IF_ERROR_RETURN
    220         (soc_reg32_get(unit, Q_SCHED_RQE_SNAPSHOTr, pipe, 0, &rval));
    221     initiate_val = 0x1;
    222     soc_reg_field_set(unit, Q_SCHED_RQE_SNAPSHOTr, &rval, INITIATEf, initiate_val);
    223     SOC_IF_ERROR_RETURN
    224         (soc_reg32_set(unit, Q_SCHED_RQE_SNAPSHOTr, pipe, 0, rval));
    225 
    226     /* Restart timeout */
    227     soc_timeout_init(&to, drain_timeout, 0);
    228     for (;;) {
    229         if (soc_timeout_check(&to)) {
    230             SOC_IF_ERROR_RETURN
    231                 (soc_reg32_get(unit, Q_SCHED_RQE_SNAPSHOTr, pipe, 0, &rval));
    232             initiate_val = soc_reg_field_get(unit, Q_SCHED_RQE_SNAPSHOTr,
    233                                                rval, INITIATEf);
    234             if (initiate_val == 0) {
    235                 /* Completion of Snapshot Process */
    236                 break;
    237             } else {
    238                 LOG_ERROR(BSL_LS_SOC_COMMON,
    239                           (BSL_META_U(unit,
    240                           "MacDrainTimeOut:port %d,%s, "
    241                           "Unable to drain packets from MMU\n"),
    242                           unit, SOC_PORT_NAME(unit, port)));
    243                 return SOC_E_INTERNAL;
    244             }
    245         }
    246     }
    247 
    248     COMPILER_64_NOT(temp64);
    249     /* Reenable Shaper Updates */
    250     SOC_IF_ERROR_RETURN
    251         (soc_reg_get(unit, MTRO_PORT_ENTITY_DISABLEr, pipe, 0, &rval64));
    252     COMPILER_64_AND(rval64, temp64);
    253     /* METERING_DISABLEf is the only field in reg. Hence writing it directly */
    254     SOC_IF_ERROR_RETURN
    255         (soc_reg_set(unit, MTRO_PORT_ENTITY_DISABLEr, pipe, 0, rval64));
    256 
    257     /* Read the Port flush Register */
    258     SOC_IF_ERROR_RETURN
    259         (soc_reg_get(unit, Q_SCHED_PORT_FLUSHr, pipe, 0, &rval64));
    260     COMPILER_64_AND(rval64, temp64);
    261     /* Port Empty - Disable Flush */
    262     /* ENABLEf is the only field in FLUSH reg. Hence writing it directly */
    263     SOC_IF_ERROR_RETURN
    264         (soc_reg_set(unit, Q_SCHED_PORT_FLUSHr, pipe, 0, rval64));
    265 
    266     SOC_IF_ERROR_RETURN
    267         (_soc_tomahawk_mmu_port_empty_check(unit, port, &empty));
    268     if (empty) {
    269         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    270                     (BSL_META_U(unit,
    271                     "MacDrain:port %d,%s, "
    272                     "Drained successfully\n"),
    273                     unit, SOC_PORT_NAME(unit, port)));
    274     } else {
    275         LOG_ERROR(BSL_LS_SOC_COMMON,
    276                   (BSL_META_U(unit,
    277                   "MacDrainError:port %d,%s, "
    278                   "Unable to drain packets from MMU\n"),
    279                   unit, SOC_PORT_NAME(unit, port)));
    280         return SOC_E_INTERNAL;
    281     }
    282     return SOC_E_NONE;
    283 }
    284 
    285 soc_th_latency_table_cfg_t
    286 soc_th_tbl_cfg[SOC_MAX_NUM_DEVICES] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    287 
    288 STATIC int
    289 soc_bcm56168_mem_config(int unit)
    290 {
    291     soc_persist_t *sop;
    292 
    293     sop = SOC_PERSIST(unit);
    294     sop->memState[VFIm].index_max = 4095;
    295     sop->memState[VFI_1m].index_max = 4095;
    296     sop->memState[EGR_VFIm].index_max = 4095;
    297     sop->memState[L2MCm].index_max = 4095;
    298     sop->memState[L3_IPMCm].index_max = 2047;
    299     sop->memState[L3_IPMC_REMAPm].index_max = 2047;
    300     sop->memState[EGR_IPMCm].index_max = 2047;
    301     sop->memState[EGR_L3_NEXT_HOPm].index_max = 4095;
    302     sop->memState[ING_L3_NEXT_HOPm].index_max = 4095;
    303     sop->memState[INITIAL_ING_L3_NEXT_HOPm].index_max = 4095;
    304 
    305     return SOC_E_NONE;
    306 }
    307 
    308 int
    309 soc_tomahawk_mem_config(int unit)
    310 {
    311 #define _SOC_TH_DEFIP_MAX_TCAMS   8
    312 #define _SOC_TH_DEFIP_REDUCED_TCAMS   3
    313 #define _SOC_TH_DEFIP_TCAM_DEPTH  SOC_IS_TOMAHAWK2(unit) ? 2048 : 1024
    314 #define _SOC_TH_FIXED_TBL_SZ      (8 * 1024)
    315     soc_persist_t *sop;
    316     int l2_entries, fixed_l2_entries = 0, shared_l2_banks = 0;
    317     int num_ipv6_128b_entries = 0;
    318     int config_v6_entries = 0;
    319     int defip_config = 0;
    320     int l3_entries, fixed_l3_entries = 0, shared_l3_banks = 0;
    321     int fpem_entries, shared_fpem_banks = 0;
    322     int num_share_banks_enabled = 4;
    323     int share_banks_bitmap_enabled = 0xf;
    324     int alpm_enable;
    325     int latency;
    326     int max_tcams  = _SOC_TH_DEFIP_MAX_TCAMS;
    327     int tcam_depth = _SOC_TH_DEFIP_TCAM_DEPTH;
    328     uint16 dev_id = 0;
    329     uint8 rev_id = 0;
    330 
    331     soc_cm_get_id(unit, &dev_id, &rev_id);
    332 
    333     sop = SOC_PERSIST(unit);
    334 
    335     l2_entries   = soc_property_get(unit, spn_L2_MEM_ENTRIES, _SOC_TH_FIXED_TBL_SZ);
    336     l3_entries   = soc_property_get(unit, spn_L3_MEM_ENTRIES, _SOC_TH_FIXED_TBL_SZ);
    337     fpem_entries = soc_property_get(unit, spn_FPEM_MEM_ENTRIES, 0);
    338     alpm_enable  = soc_property_get(unit, spn_L3_ALPM_ENABLE, 0);
    339 
    340     if ((dev_id == BCM56168_DEVICE_ID) || (dev_id == BCM56169_DEVICE_ID)) {
    341         max_tcams = _SOC_TH_DEFIP_REDUCED_TCAMS;
    342     }
    343 
    344     /* switch latency bypass */
    345     SOC_IF_ERROR_RETURN(soc_th_latency_get(unit, &latency));
    346 
    347     switch(latency) {
    348         case SOC_SWITCH_BYPASS_MODE_NONE:
    349             /*
    350              * bank 0-1 are dedicated L2 banks (4k entries per bank)
    351              * bank 6-9 are dedicated L3 banks (2k entries per bank)
    352              * bank 2-5 are shared banks (32k L2/L3 or ALPM(uses all 4 or banks 2,3)
    353              *          or 16k FPEM entres per bank)
    354              */
    355             fixed_l2_entries = _SOC_TH_FIXED_TBL_SZ;  /* 8k dedicated L2 entries */
    356             if (l2_entries < fixed_l2_entries) {
    357                 l2_entries = fixed_l2_entries;
    358                 shared_l2_banks = 0;
    359             } else {
    360                 l2_entries -= fixed_l2_entries;
    361 #if defined(BCM_TOMAHAWK2_SUPPORT)
    362                 if (SOC_IS_TOMAHAWK2(unit)) {
    363                     shared_l2_banks = (l2_entries + (64 * 1024 - 1)) / (64 * 1024);
    364                     l2_entries = fixed_l2_entries + shared_l2_banks * 64 * 1024;
    365                 } else
    366 #endif
    367                 {
    368                     shared_l2_banks = (l2_entries + (32 * 1024 - 1)) / (32 * 1024);
    369                     l2_entries = fixed_l2_entries + shared_l2_banks * 32 * 1024;
    370                 }
    371             }
    372 
    373             fixed_l3_entries = _SOC_TH_FIXED_TBL_SZ;  /* 8k dedicated L3 entries */
    374             if (l3_entries < fixed_l3_entries) {
    375                 l3_entries = fixed_l3_entries;
    376                 shared_l3_banks = 0;
    377             } else {
    378                 l3_entries -= fixed_l3_entries;
    379 #if defined(BCM_TOMAHAWK2_SUPPORT)
    380                 if (SOC_IS_TOMAHAWK2(unit)) {
    381                     shared_l3_banks = (l3_entries + (64 * 1024 - 1)) / (64 * 1024);
    382                     l3_entries = fixed_l3_entries + shared_l3_banks * 64 * 1024;
    383                 } else
    384 #endif
    385                 if ((dev_id == BCM56168_DEVICE_ID) || (dev_id == BCM56169_DEVICE_ID)) {
    386                     shared_l3_banks = 0;
    387                     l3_entries = fixed_l3_entries;
    388                 } else {
    389                     shared_l3_banks = (l3_entries + (32 * 1024 - 1)) / (32 * 1024);
    390                     l3_entries = fixed_l3_entries + shared_l3_banks * 32 * 1024;
    391                 }
    392             }
    393 
    394 #if defined(BCM_TOMAHAWK2_SUPPORT)
    395             if (SOC_IS_TOMAHAWK2(unit)) {
    396                 shared_fpem_banks = (fpem_entries + (32 * 1024 - 1)) / (32 * 1024);
    397                 fpem_entries = shared_fpem_banks * 32 * 1024;
    398             } else
    399 #endif
    400             {
    401                 shared_fpem_banks = (fpem_entries + (16 * 1024 - 1)) / (16 * 1024);
    402                 fpem_entries = shared_fpem_banks * 16 * 1024;
    403             }
    404 
    405             if ((dev_id == BCM56168_DEVICE_ID) || (dev_id == BCM56169_DEVICE_ID)) {
    406                 if (shared_l2_banks  + shared_fpem_banks > 1) {
    407                     return SOC_E_PARAM;
    408                 }
    409             }
    410 
    411 #ifdef BCM_TOMAHAWK2_SUPPORT            
    412             if (soc_feature(unit, soc_feature_untethered_otp)) {
    413                 soc_th2_uft_otp_info_get(unit, &num_share_banks_enabled,
    414                     &share_banks_bitmap_enabled);
    415             }
    416 #endif
    417 
    418             if (shared_l2_banks + shared_l3_banks + shared_fpem_banks 
    419                 > num_share_banks_enabled) {
    420                 return SOC_E_PARAM;
    421             }
    422 
    423             if (alpm_enable && soc_feature(unit, soc_feature_alpm)) {
    424                 if (((shared_l2_banks + shared_l3_banks + shared_fpem_banks + 2) 
    425                     > num_share_banks_enabled)
    426                     /* If any of B2, B3 banks is disabled */
    427                     || (~share_banks_bitmap_enabled & 0x3)) {
    428                     return SOC_E_PARAM;
    429                 }
    430             }
    431 
    432             break;
    433 
    434         case SOC_SWITCH_BYPASS_MODE_LOW:
    435             if (l2_entries > _SOC_TH_FIXED_TBL_SZ) {
    436                 LOG_CLI(("ERROR: Unsupported L2 table size specified in "
    437                          "config.bcm\n"));
    438                 LOG_CLI(("INFO : L2 table size reduced to 8K in "
    439                          "low (L2) latency mode\n"));
    440             }
    441             if (l3_entries) {
    442                 LOG_CLI(("ERROR: L3 tables unsupported in "
    443                          "low (L2) latency mode\n"));
    444                 LOG_CLI(("INFO : Ignored L3 table config specified "
    445                          "in config.bcm\n"));
    446             }
    447             if (alpm_enable) {
    448                 LOG_CLI(("ERROR: ALPM unsupported in "
    449                          "low (L2) latency mode\n"));
    450                 LOG_CLI(("INFO : Ignored ALPM config specified "
    451                          "in config.bcm\n"));
    452             }
    453 
    454             l2_entries = _SOC_TH_FIXED_TBL_SZ;
    455             fixed_l2_entries = _SOC_TH_FIXED_TBL_SZ;
    456             l3_entries = 0;
    457             fixed_l3_entries = 0;
    458             max_tcams = tcam_depth = 0;
    459 
    460             fpem_entries = 0;
    461             shared_l2_banks = 0;
    462             shared_l3_banks = 0;
    463             shared_fpem_banks = 0;
    464 
    465             alpm_enable = 0;
    466 
    467             sop->memState[VLAN_MPLSm].index_max = -1;
    468             SOC_MEM_PTR(unit, VLAN_MPLSm) = 0;
    469             break;
    470 
    471         case SOC_SWITCH_BYPASS_MODE_BALANCED:
    472             if (l2_entries > _SOC_TH_FIXED_TBL_SZ) {
    473                 LOG_CLI(("ERROR: Unsupported L2 table size specified in "
    474                          "config.bcm\n"));
    475                 LOG_CLI(("INFO : L2 table size reduced to 8K in "
    476                          "balanced (L2/L3) latency mode\n"));
    477             }
    478             if (l3_entries > _SOC_TH_FIXED_TBL_SZ) {
    479 
    480                 LOG_CLI(("ERROR: Unsupported L3 table size specified in"
    481                          "config.bcm\n"));
    482                 LOG_CLI(("INFO : L3 table size reduced to 8K in "
    483                          "balanced (L2/L3) latency mode\n"));
    484             }
    485             if (alpm_enable) {
    486                 LOG_CLI(("ERROR: ALPM unsupported in "
    487                          "balanced (L2/L3) latency mode\n"));
    488                 LOG_CLI(("INFO : Ignored ALPM config specified "
    489                          "in config.bcm\n"));
    490             }
    491 
    492             l2_entries = _SOC_TH_FIXED_TBL_SZ;
    493             fixed_l2_entries = _SOC_TH_FIXED_TBL_SZ;
    494             l3_entries = _SOC_TH_FIXED_TBL_SZ;
    495             fixed_l3_entries = _SOC_TH_FIXED_TBL_SZ;
    496 
    497             fpem_entries = 0;
    498             shared_l2_banks = 0;
    499             shared_l3_banks = 0;
    500             shared_fpem_banks = 0;
    501 
    502             alpm_enable = 0;
    503 
    504             /* In balanced latency mode, only first half of ecmp tables are active */
    505             sop->memState[L3_ECMPm].index_max =
    506                                    sop->memState[L3_ECMPm].index_max/2;
    507             sop->memState[L3_ECMP_COUNTm].index_max =
    508                              sop->memState[L3_ECMP_COUNTm].index_max/2;
    509             sop->memState[INITIAL_L3_ECMP_COUNTm].index_max =
    510                              sop->memState[INITIAL_L3_ECMP_COUNTm].index_max/2;
    511             sop->memState[INITIAL_L3_ECMPm].index_max =
    512                              sop->memState[INITIAL_L3_ECMPm].index_max/2;
    513             break;
    514 
    515             default:
    516                 return SOC_E_INTERNAL;
    517     }
    518 
    519     if (soc_feature(unit, soc_feature_alpm)) {
    520         _soc_alpm_mode[unit] = alpm_enable;
    521     }
    522 
    523     if (SAL_BOOT_QUICKTURN) {
    524         sop->memState[MY_STATION_TCAMm].index_max = 7;
    525     }  
    526 
    527     /* Adjust L2 table size */
    528     sop->memState[L2Xm].index_max = l2_entries - 1;
    529     sop->memState[L2_ENTRY_TILEm].index_max = l2_entries - 1;
    530     sop->memState[L2_ENTRY_ONLY_TILEm].index_max = l2_entries - 1;
    531     sop->memState[L2_ENTRY_ONLY_ECCm].index_max = l2_entries - 1;
    532     sop->memState[L2_HITDA_ONLYm].index_max = l2_entries / 4 - 1;
    533     sop->memState[L2_HITSA_ONLYm].index_max = l2_entries / 4 - 1;
    534     sop->memState[L2_ENTRY_ISS_LPm].index_max =
    535         (l2_entries - fixed_l2_entries) / 4 - 1;
    536 
    537     /* Adjust L3 table size */
    538     sop->memState[L3_ENTRY_ONLYm].index_max = l3_entries - 1;
    539     sop->memState[L3_ENTRY_IPV4_UNICASTm].index_max = l3_entries - 1;
    540     sop->memState[L3_ENTRY_IPV4_MULTICASTm].index_max = l3_entries / 2 - 1;
    541     sop->memState[L3_ENTRY_IPV6_UNICASTm].index_max = l3_entries/ 2 - 1;
    542     sop->memState[L3_ENTRY_IPV6_MULTICASTm].index_max = l3_entries / 4 - 1;
    543     sop->memState[L3_ENTRY_ONLY_ECCm].index_max = l3_entries - 1;
    544     sop->memState[L3_ENTRY_HIT_ONLYm].index_max = l3_entries / 4 - 1;
    545     sop->memState[L3_ENTRY_ISS_LPm].index_max =
    546         (l3_entries - fixed_l3_entries) / 4 - 1;
    547 
    548     /* Adjust FP exact match table size */
    549     sop->memState[EXACT_MATCH_2m].index_max = fpem_entries - 1;
    550     sop->memState[EXACT_MATCH_2_PIPE0m].index_max = fpem_entries - 1;
    551     sop->memState[EXACT_MATCH_2_PIPE1m].index_max = fpem_entries - 1;
    552     sop->memState[EXACT_MATCH_2_PIPE2m].index_max = fpem_entries - 1;
    553     sop->memState[EXACT_MATCH_2_PIPE3m].index_max = fpem_entries - 1;
    554     sop->memState[EXACT_MATCH_2_ENTRY_ONLYm].index_max = fpem_entries - 1;
    555     sop->memState[EXACT_MATCH_2_ENTRY_ONLY_PIPE0m].index_max =
    556         fpem_entries - 1;
    557     sop->memState[EXACT_MATCH_2_ENTRY_ONLY_PIPE1m].index_max =
    558         fpem_entries - 1;
    559     sop->memState[EXACT_MATCH_2_ENTRY_ONLY_PIPE2m].index_max =
    560         fpem_entries - 1;
    561     sop->memState[EXACT_MATCH_2_ENTRY_ONLY_PIPE3m].index_max =
    562         fpem_entries - 1;
    563     sop->memState[EXACT_MATCH_4m].index_max = fpem_entries / 2 - 1;
    564     sop->memState[EXACT_MATCH_4_PIPE0m].index_max = fpem_entries / 2 - 1;
    565     sop->memState[EXACT_MATCH_4_PIPE1m].index_max = fpem_entries / 2 - 1;
    566     sop->memState[EXACT_MATCH_4_PIPE2m].index_max = fpem_entries / 2 - 1;
    567     sop->memState[EXACT_MATCH_4_PIPE3m].index_max = fpem_entries / 2 - 1;
    568     sop->memState[EXACT_MATCH_4_ENTRY_ONLYm].index_max = fpem_entries / 2 - 1;
    569     sop->memState[EXACT_MATCH_4_ENTRY_ONLY_PIPE0m].index_max =
    570         fpem_entries / 2 - 1;
    571     sop->memState[EXACT_MATCH_4_ENTRY_ONLY_PIPE1m].index_max =
    572         fpem_entries / 2 - 1;
    573     sop->memState[EXACT_MATCH_4_ENTRY_ONLY_PIPE2m].index_max =
    574         fpem_entries / 2 - 1;
    575     sop->memState[EXACT_MATCH_4_ENTRY_ONLY_PIPE3m].index_max =
    576         fpem_entries / 2 - 1;
    577     sop->memState[EXACT_MATCH_HIT_ONLYm].index_max = fpem_entries / 2 - 1;
    578     sop->memState[FPEM_LPm].index_max = fpem_entries / 2 - 1;
    579     sop->memState[FPEM_ECCm].index_max = fpem_entries * 2 - 1;
    580     sop->memState[FPEM_ECC_PIPE0m].index_max = fpem_entries * 2 - 1;
    581     sop->memState[FPEM_ECC_PIPE1m].index_max = fpem_entries * 2 - 1;
    582     sop->memState[FPEM_ECC_PIPE2m].index_max = fpem_entries * 2 - 1;
    583     sop->memState[FPEM_ECC_PIPE3m].index_max = fpem_entries * 2 - 1;
    584 
    585     SOC_CONTROL(unit)->l3_defip_max_tcams = max_tcams;
    586     SOC_CONTROL(unit)->l3_defip_tcam_size = tcam_depth;
    587 
    588     if (SOC_SWITCH_BYPASS_MODE_LOW == latency) {
    589         sop->memState[L3_DEFIP_PAIR_128m].index_max = -1;
    590         sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max = -1;
    591         sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max = -1;
    592         sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max = -1;
    593         sop->memState[L3_DEFIPm].index_max = -1;
    594         sop->memState[L3_DEFIP_ONLYm].index_max = -1;
    595         sop->memState[L3_DEFIP_DATA_ONLYm].index_max = -1;
    596         sop->memState[L3_DEFIP_HIT_ONLYm].index_max = -1;
    597     } else {
    598         if (soc_property_get(unit, "l3_defip_sizing", TRUE)) {
    599             if (!(soc_feature(unit, soc_feature_alpm) &&
    600                   soc_property_get(unit, spn_L3_ALPM_ENABLE, 0))) {
    601                 defip_config = soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1);
    602 
    603                 if (SOC_IS_TOMAHAWK2(unit)) {
    604                     num_ipv6_128b_entries = soc_property_get(unit,
    605                                                 spn_NUM_IPV6_LPM_128B_ENTRIES,
    606                                                 (defip_config ? 4096 : 0));
    607                 } else if ((dev_id == BCM56168_DEVICE_ID) || (dev_id == BCM56169_DEVICE_ID)) {
    608                     num_ipv6_128b_entries =  soc_property_get(unit,
    609                                                 spn_NUM_IPV6_LPM_128B_ENTRIES,
    610                                                 (defip_config ? 512 : 0));
    611                     if (num_ipv6_128b_entries > 512) {
    612                         num_ipv6_128b_entries = 512;
    613                     }
    614                 } else {
    615                     num_ipv6_128b_entries = soc_property_get(unit,
    616                                                 spn_NUM_IPV6_LPM_128B_ENTRIES,
    617                                                 (defip_config ? 2048 : 0));
    618                 }
    619                 num_ipv6_128b_entries = num_ipv6_128b_entries +
    620                                         (num_ipv6_128b_entries % 2);
    621 
    622                 config_v6_entries = num_ipv6_128b_entries;
    623                 if (soc_property_get(unit, spn_LPM_SCALING_ENABLE, 0)) {
    624                     num_ipv6_128b_entries = 0;
    625                     if (!soc_property_get(unit, spn_LPM_IPV6_128B_RESERVED, 1)) {
    626                         config_v6_entries = ((config_v6_entries /
    627                                             SOC_CONTROL(unit)->l3_defip_tcam_size) +
    628                                             ((config_v6_entries %
    629                                              SOC_CONTROL(unit)->l3_defip_tcam_size)
    630                                             ? 1 : 0)) * SOC_CONTROL(unit)->l3_defip_tcam_size;
    631                     }
    632                 }
    633                 sop->memState[L3_DEFIP_PAIR_128m].index_max =
    634                                                   num_ipv6_128b_entries - 1;
    635                 sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max =
    636                                                   num_ipv6_128b_entries - 1;
    637                 sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max =
    638                                                   num_ipv6_128b_entries - 1;
    639                 sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max =
    640                                                   num_ipv6_128b_entries - 1;
    641                 sop->memState[L3_DEFIPm].index_max =
    642                                          (SOC_CONTROL(unit)->l3_defip_max_tcams *
    643                                          SOC_CONTROL(unit)->l3_defip_tcam_size) -
    644                                          (num_ipv6_128b_entries * 2) - 1;
    645 
    646                 if (soc_feature(unit, soc_feature_l3_1k_defip_table)) {
    647                     sop->memState[L3_DEFIPm].index_max = 1023;
    648                 }
    649 
    650                 sop->memState[L3_DEFIP_ONLYm].index_max =
    651                                               sop->memState[L3_DEFIPm].index_max;
    652                 sop->memState[L3_DEFIP_DATA_ONLYm].index_max =
    653                                               sop->memState[L3_DEFIPm].index_max;
    654                 sop->memState[L3_DEFIP_HIT_ONLYm].index_max =
    655                                               sop->memState[L3_DEFIPm].index_max;
    656                 SOC_CONTROL(unit)->l3_defip_index_remap = num_ipv6_128b_entries;
    657             } else {
    658                 if (soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1)) {
    659                     /* slightly different processing for v6-128 */
    660                     if (SOC_IS_TOMAHAWK2(unit)) {
    661                         num_ipv6_128b_entries = soc_property_get(unit,
    662                                                     spn_NUM_IPV6_LPM_128B_ENTRIES,
    663                                                     4096);
    664                     } else {
    665                         num_ipv6_128b_entries = soc_property_get(unit,
    666                                                     spn_NUM_IPV6_LPM_128B_ENTRIES,
    667                                                     2048);
    668                     }
    669                     num_ipv6_128b_entries = num_ipv6_128b_entries +
    670                                             (num_ipv6_128b_entries % 2);
    671                     if (soc_tomahawk_alpm_mode_get(unit) == 1 ||
    672                         soc_tomahawk_alpm_mode_get(unit) == 3) {
    673                         num_ipv6_128b_entries = (num_ipv6_128b_entries + 3) / 4 * 4;
    674                     }
    675                     config_v6_entries = num_ipv6_128b_entries;
    676                     sop->memState[L3_DEFIP_PAIR_128m].index_max =
    677                                                     num_ipv6_128b_entries - 1;
    678                     sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max =
    679                                                     num_ipv6_128b_entries - 1;
    680                     sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max =
    681                                                     num_ipv6_128b_entries - 1;
    682                     sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max =
    683                                                     num_ipv6_128b_entries - 1;
    684                     sop->memState[L3_DEFIPm].index_max =
    685                                       (SOC_CONTROL(unit)->l3_defip_max_tcams *
    686                                       SOC_CONTROL(unit)->l3_defip_tcam_size) -
    687                                       (num_ipv6_128b_entries * 2) - 1;
    688 
    689                     sop->memState[L3_DEFIP_ONLYm].index_max =
    690                                            sop->memState[L3_DEFIPm].index_max;
    691                     sop->memState[L3_DEFIP_DATA_ONLYm].index_max =
    692                                            sop->memState[L3_DEFIPm].index_max;
    693                     sop->memState[L3_DEFIP_HIT_ONLYm].index_max =
    694                                            sop->memState[L3_DEFIPm].index_max;
    695                     SOC_CONTROL(unit)->l3_defip_index_remap =
    696                                            (num_ipv6_128b_entries / 2) * 2;
    697                 } else {
    698                     sop->memState[L3_DEFIP_PAIR_128m].index_max = -1;
    699                     sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max = -1;
    700                     sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max = -1;
    701                     sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max = -1;
    702                 }
    703             }
    704             soc_l3_defip_indexes_init(unit, config_v6_entries);
    705         }
    706     }/* switch latency bypass */
    707 
    708     /* Adjust ALPM table size */
    709     if ((SOC_SWITCH_BYPASS_MODE_NONE == latency) &&
    710          soc_feature(unit, soc_feature_alpm) &&
    711          soc_property_get(unit, spn_L3_ALPM_ENABLE, 0)) {
    712         /* The check below is sufficient because if ALPM mode is enabled
    713          * and number of shared banks used is > 2 we return SOC_E_PARAM
    714          * in code at the top of this function.
    715          */
    716         if ((shared_l2_banks + shared_l3_banks + shared_fpem_banks > 0)
    717               /* If any of B4, B5 banks is disabled, ALPM can only use Bank B2, B3 */
    718             || (~share_banks_bitmap_enabled & 0xc)){
    719             sop->memState[L3_DEFIP_ALPM_RAWm].index_max =
    720                 sop->memState[L3_DEFIP_ALPM_RAWm].index_max/2;
    721             sop->memState[L3_DEFIP_ALPM_IPV4m].index_max =
    722                 sop->memState[L3_DEFIP_ALPM_IPV4m].index_max/2;
    723             sop->memState[L3_DEFIP_ALPM_IPV4_1m].index_max =
    724                 sop->memState[L3_DEFIP_ALPM_IPV4_1m].index_max/2;
    725             sop->memState[L3_DEFIP_ALPM_IPV6_64m].index_max =
    726                 sop->memState[L3_DEFIP_ALPM_IPV6_64m].index_max/2;
    727             sop->memState[L3_DEFIP_ALPM_IPV6_64_1m].index_max =
    728                 sop->memState[L3_DEFIP_ALPM_IPV6_64_1m].index_max/2;
    729             sop->memState[L3_DEFIP_ALPM_IPV6_128m].index_max =
    730                 sop->memState[L3_DEFIP_ALPM_IPV6_128m].index_max/2;
    731             sop->memState[L3_DEFIP_ALPM_HIT_ONLYm].index_max =
    732                 sop->memState[L3_DEFIP_ALPM_HIT_ONLYm].index_max/2;
    733             sop->memState[L3_DEFIP_ALPM_ECCm].index_max =
    734                 sop->memState[L3_DEFIP_ALPM_ECCm].index_max/2;
    735         }
    736     } else {
    737         sop->memState[L3_DEFIP_ALPM_RAWm].index_max = -1;
    738         sop->memState[L3_DEFIP_ALPM_IPV4m].index_max = -1;
    739         sop->memState[L3_DEFIP_ALPM_IPV4_1m].index_max = -1;
    740         sop->memState[L3_DEFIP_ALPM_IPV6_64m].index_max = -1;
    741         sop->memState[L3_DEFIP_ALPM_IPV6_64_1m].index_max = -1;
    742         sop->memState[L3_DEFIP_ALPM_IPV6_128m].index_max = -1;
    743         sop->memState[L3_DEFIP_ALPM_HIT_ONLYm].index_max = -1;
    744         sop->memState[L3_DEFIP_ALPM_ECCm].index_max = -1;
    745     }
    746 
    747     if (_soc_th_alpm_bkt_view_map[unit] != NULL) {
    748         sal_free(_soc_th_alpm_bkt_view_map[unit]);
    749         _soc_th_alpm_bkt_view_map[unit] = NULL;
    750     }
    751 
    752     if (NULL == _soc_th_alpm_bkt_view_map[unit]) {
    753         if ((_soc_th_alpm_bkt_view_map[unit] =
    754             sal_alloc(sizeof(soc_mem_t) * SOC_TH_ALPM_MAX_BKTS(unit),
    755                       "alpm_bkt_map")) == NULL) {
    756             return SOC_E_MEMORY;
    757         }
    758     }
    759 
    760     sal_memset(_soc_th_alpm_bkt_view_map[unit], INVALIDm,
    761                sizeof(soc_mem_t) * SOC_TH_ALPM_MAX_BKTS(unit));
    762 
    763     if (_soc_th_lpm_view_map[unit] != NULL) {
    764         sal_free(_soc_th_lpm_view_map[unit]);
    765         _soc_th_lpm_view_map[unit] = NULL;
    766     }
    767 
    768     if (NULL == _soc_th_lpm_view_map[unit]) {
    769         if ((_soc_th_lpm_view_map[unit] =
    770             sal_alloc(sizeof(soc_mem_t) *
    771                       SOC_L3_DEFIP_MAX_TCAMS_GET(unit) *
    772                       SOC_L3_DEFIP_TCAM_DEPTH_GET(unit),
    773                       "lpm_view_map")) == NULL) {
    774             return SOC_E_MEMORY;
    775         }
    776     }
    777 
    778     sal_memset(_soc_th_lpm_view_map[unit], INVALIDm,
    779                sizeof(soc_mem_t) *
    780                SOC_L3_DEFIP_MAX_TCAMS_GET(unit) *
    781                SOC_L3_DEFIP_TCAM_DEPTH_GET(unit));
    782     if ((dev_id == BCM56168_DEVICE_ID) || (dev_id == BCM56169_DEVICE_ID)) {
    783         soc_bcm56168_mem_config(unit);
    784     }
    785 
    786     /* update tbl cfg to latency subsystem for diag purposes */
    787     soc_th_tbl_cfg[unit].l2_entries = l2_entries;
    788     soc_th_tbl_cfg[unit].fixed_l2_entries = fixed_l2_entries;
    789     soc_th_tbl_cfg[unit].shared_l2_banks = shared_l2_banks;
    790     soc_th_tbl_cfg[unit].l3_entries = l3_entries;
    791     soc_th_tbl_cfg[unit].fixed_l3_entries = fixed_l3_entries;
    792     soc_th_tbl_cfg[unit].shared_l3_banks = shared_l3_banks;
    793     soc_th_tbl_cfg[unit].fpem_entries = fpem_entries;
    794     soc_th_tbl_cfg[unit].shared_fpem_banks = shared_fpem_banks;
    795     soc_th_tbl_cfg[unit].alpm_enable = alpm_enable;
    796     soc_th_tbl_cfg[unit].max_tcams = max_tcams;
    797     soc_th_tbl_cfg[unit].tcam_depth = tcam_depth;
    798 
    799     return SOC_E_NONE;
    800 }
    801 
    802 int
    803 soc_tomahawk_mem_cpu_write_control(int unit, soc_mem_t mem, int copyno,
    804                                    int enable, int *orig_enable)
    805 {
    806     soc_reg_t reg;
    807     soc_field_t field;
    808     uint32 rval, fval;
    809     int blk, port, block_info_index;
    810     uint32 orig_fval, enable_fval, disable_fval;
    811 
    812     enable_fval = 1;
    813     disable_fval = 0;
    814 
    815     switch (mem) {
    816     case CLPORT_WC_UCMEM_DATAm:
    817         reg = CLPORT_WC_UCMEM_CTRLr;
    818         field = ACCESS_MODEf;
    819         SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
    820             port = SOC_BLOCK_PORT(unit, blk);
    821             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    822             /* It will use the setting from the last block */
    823             *orig_enable = soc_reg_field_get(unit, reg, rval, field);
    824             soc_reg_field_set(unit, reg, &rval, field, enable ? 1 : 0);
    825             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
    826         }
    827         return SOC_E_NONE;
    828     default:
    829         block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
    830         if ((SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_XPE) ||
    831 #if defined(BCM_TOMAHAWK2_SUPPORT)
    832             (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_SED) ||
    833 #endif
    834             (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_SC)){
    835             reg = MMU_GCFG_MISCCONFIGr;
    836             field = REFRESH_ENf;
    837             enable_fval = 0;
    838             disable_fval = 1;
    839             SOC_IF_ERROR_RETURN
    840                 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    841             orig_fval = soc_reg_field_get(unit, reg, rval, field);
    842             fval = enable ? enable_fval : disable_fval;
    843             *orig_enable = orig_fval == enable_fval;
    844             if (fval != orig_fval) {
    845                 soc_reg_field_set(unit, reg, &rval, field, fval);
    846                 SOC_IF_ERROR_RETURN
    847                     (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    848             }
    849         }
    850         return _soc_trident2_mem_cpu_write_control(unit, mem, copyno,
    851                                                    enable, orig_enable);
    852     }
    853     return SOC_E_NONE;
    854 }
    855 
    856 int
    857 soc_tomahawk_reg_cpu_write_control(int unit, int enable)
    858 {
    859     uint32 intfo_dis = 0;
    860 
    861     if (enable) {
    862         /* Disable HW updates */
    863         soc_reg_field_set(unit, INTFO_HW_UPDATE_DISr, &intfo_dis,
    864                           EG_SPf, 1);
    865         soc_reg_field_set(unit, INTFO_HW_UPDATE_DISr, &intfo_dis,
    866                           ING_SPf, 1);
    867         soc_reg_field_set(unit, INTFO_HW_UPDATE_DISr, &intfo_dis,
    868                           CONGST_STf, 1);
    869     }
    870     SOC_IF_ERROR_RETURN(WRITE_INTFO_HW_UPDATE_DISr(unit, intfo_dis));
    871 
    872     return SOC_E_NONE;
    873 }
    874 
    875 uint32 _soc_th_mmu_port(int unit, int port)
    876 {
    877     soc_info_t *si = &SOC_INFO(unit);
    878     return si->port_p2m_mapping[si->port_l2p_mapping[port]];
    879 }
    880 
    881 /*
    882  * CPU port (mmu port 32): 48 MC queues
    883  * Loopback port (mmu port 33,97,161,225): 10 MC queues
    884  * Mgmt port (mmu port 96,160): 10 UC, 10 MC queues
    885  */
    886 int
    887 soc_tomahawk_num_cosq_init_port(int unit, int port)
    888 {
    889 #define CPU_MCQ_BASE  330 /* CPU port MC queue base index */
    890 #define LB_MCQ_BASE   320 /* LB ports MC queue base index */
    891 #define MGMT_UCQ_BASE 320 /* Mgmt ports UC queue base index */
    892 #define MGMT_MCQ_BASE 330 /* Mgmt ports MC queue base index */
    893     soc_info_t *si;
    894     int mmu_port;
    895 
    896     si = &SOC_INFO(unit);
    897     mmu_port = SOC_TH_MMU_PORT(unit, port);
    898 
    899     if (IS_CPU_PORT(unit, port)) {
    900         si->port_num_cosq[port] = 48;
    901         si->port_cosq_base[port] = CPU_MCQ_BASE;
    902     } else if (IS_LB_PORT(unit, port)) {
    903         si->port_num_cosq[port] = 10;
    904         si->port_cosq_base[port] = LB_MCQ_BASE;
    905     } else if (SOC_PBMP_MEMBER(si->management_pbm, port)) {
    906         si->port_num_cosq[port] = 10;
    907         si->port_cosq_base[port] = MGMT_MCQ_BASE;
    908         si->port_num_uc_cosq[port] = 10;
    909         si->port_uc_cosq_base[port] = MGMT_UCQ_BASE;
    910     } else {
    911         if (mmu_port == -1) {
    912             return SOC_E_INTERNAL;
    913         }
    914 
    915         si->port_num_cosq[port] = 10;
    916         si->port_cosq_base[port] =
    917                     (mmu_port % SOC_TH_MMU_PORT_STRIDE) * 10;
    918         si->port_num_uc_cosq[port] = 10;
    919         si->port_uc_cosq_base[port] =
    920                     (mmu_port % SOC_TH_MMU_PORT_STRIDE) * 10;
    921         si->port_num_ext_cosq[port] = 0;
    922     }
    923 
    924     return SOC_E_NONE;
    925 }
    926 
    927 
    928 /*
    929  * CPU port (mmu port 32): 48 MC queues
    930  * Loopback port (mmu port 33,97,161,225): 10 MC queues
    931  * Mgmt port (mmu port 96,160): 10 UC, 10 MC queues
    932  */
    933 int
    934 soc_tomahawk_num_cosq_init(int unit)
    935 {
    936     int port;
    937 
    938     PBMP_ALL_ITER(unit, port) {
    939         SOC_IF_ERROR_RETURN
    940             (soc_tomahawk_num_cosq_init_port(unit, port));
    941     }
    942 
    943     return SOC_E_NONE;
    944 }
    945 
    946 STATIC int
    947 soc_tomahawk_max_frequency_get(int unit,  uint16 dev_id, uint8 rev_id,
    948                                int skew_id, int *frequency)
    949 {
    950     switch (dev_id) {
    951     default:
    952         *frequency = 850;
    953     }
    954 
    955     return SOC_E_NONE;
    956 }
    957 
    958 void
    959 soc_tomahawk_tsc_map_get(int unit, uint32 *tsc_map)
    960 {
    961     *tsc_map = 0xffffffff;
    962 }
    963 
    964 void
    965 soc_tomahawk_pipe_map_get(int unit, uint32 *pipe_map)
    966 {
    967     soc_info_t *si;
    968     int port;
    969 
    970     si = &SOC_INFO(unit);
    971 
    972     *pipe_map = 0;
    973     PBMP_LB_ITER(unit, port) {
    974         *pipe_map |= 1 << si->port_pipe[port];
    975     }
    976 }
    977 
    978 /*
    979  * #1   single: 100  -   x  -   x  -   x  SOC_TH_PORT_RATIO_SINGLE
    980  * #2   single:  40  -   x  -   x  -   x  SOC_TH_PORT_RATIO_TRI_023_2_1_1
    981  * #3   dual:    50  -   x  -  50  -   x  SOC_TH_PORT_RATIO_DUAL_1_1
    982  * #4   dual:    40  -   x  -  40  -   x  SOC_TH_PORT_RATIO_DUAL_1_1
    983  * #5   dual:    20  -   x  -  20  -   x  SOC_TH_PORT_RATIO_DUAL_1_1
    984  * #6   dual:    40  -   x  -  20  -   x  SOC_TH_PORT_RATIO_DUAL_2_1
    985  * #7   dual:    20  -   x  -  40  -   x  SOC_TH_PORT_RATIO_DUAL_1_2
    986  * #8   tri:     50  -   x  - 25/x - 25/x SOC_TH_PORT_RATIO_TRI_023_2_1_1
    987  * #9   tri:     20  -   x  - 10/x - 10/x SOC_TH_PORT_RATIO_TRI_023_2_1_1
    988  * #10  tri:     40  -   x  - 10/x - 10/x SOC_TH_PORT_RATIO_TRI_023_4_1_1
    989  * #11  tri:    25/x - 25/x -  50  -   x  SOC_TH_PORT_RATIO_TRI_012_1_1_2
    990  * #12  tri:    10/x - 10/x -  20  -   x  SOC_TH_PORT_RATIO_TRI_012_1_1_2
    991  * #13  tri:    10/x - 10/x -  40  -   x  SOC_TH_PORT_RATIO_TRI_012_1_1_4
    992  * #14  quad:   25/x - 25/x - 25/x - 25/x SOC_TH_PORT_RATIO_QUAD
    993  * #15  quad:   10/x - 10/x - 10/x - 10/x SOC_TH_PORT_RATIO_QUAD
    994  */
    995 void
    996 soc_tomahawk_port_ratio_get(int unit, int initTime, int clport, int *mode)
    997 {
    998     soc_info_t *si;
    999     int port, phy_port_base, lane;
   1000     int num_lanes[_TH_PORTS_PER_PBLK];
   1001     int speed_max[_TH_PORTS_PER_PBLK];
   1002     int cur_mode;
   1003     int port_sub, port_sis;
   1004 
   1005     si = &SOC_INFO(unit);
   1006     phy_port_base = 1 + clport * _TH_PORTS_PER_PBLK;
   1007     for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane += 2) {
   1008         port = si->port_p2l_mapping[phy_port_base + lane];
   1009         if (port == -1 || SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   1010             num_lanes[lane] = -1;
   1011             speed_max[lane] = -1;
   1012         } else {
   1013             num_lanes[lane] = si->port_num_lanes[port];
   1014             /* At init time port_speed_max_max contains port init speed_max and
   1015              * at run time during flex port opeartion, init_speed_max
   1016              * contains current port speed_max
   1017              */
   1018             speed_max[lane] = initTime ? si->port_speed_max[port] :
   1019                               si->port_init_speed[port];
   1020         }
   1021     }
   1022 
   1023     if (num_lanes[0] == 4) {
   1024         *mode = SOC_TH_PORT_RATIO_SINGLE;
   1025     } else if (num_lanes[0] == 2 && num_lanes[2] == 2) {
   1026         if (speed_max[0] == speed_max[2]) {
   1027             *mode = SOC_TH_PORT_RATIO_DUAL_1_1;
   1028         } else if (speed_max[0] > speed_max[2]) {
   1029             *mode = SOC_TH_PORT_RATIO_DUAL_2_1;
   1030         } else {
   1031             *mode = SOC_TH_PORT_RATIO_DUAL_1_2;
   1032         }
   1033     } else if (num_lanes[0] == 2) {
   1034         if (num_lanes[2] == -1) {
   1035             *mode = SOC_TH_PORT_RATIO_DUAL_1_1;
   1036         } else {
   1037             *mode = cur_mode = (speed_max[0] == 20000 || speed_max[0] == 21000 ||
   1038                      speed_max[0] == 50000 || speed_max[0] == 53000) ?
   1039                 SOC_TH_PORT_RATIO_TRI_023_2_1_1 : SOC_TH_PORT_RATIO_TRI_023_4_1_1;
   1040             if (initTime && si->os_mixed_sister_25_50_enable) {
   1041                 *mode = ((speed_max[0] == 50000 && speed_max[2] == 25000) ||
   1042                          (speed_max[0] == 53000 && speed_max[2] == 27000)) ?
   1043                     SOC_TH_PORT_RATIO_DUAL_1_1 : cur_mode;
   1044             }
   1045         }
   1046     } else if (num_lanes[2] == 2) {
   1047         if (num_lanes[0] == -1) {
   1048             *mode = SOC_TH_PORT_RATIO_DUAL_1_1;
   1049         } else {
   1050             *mode = cur_mode = (speed_max[2] == 20000 || speed_max[2] == 21000 ||
   1051                      speed_max[2] == 50000 || speed_max[2] == 53000) ?
   1052                 SOC_TH_PORT_RATIO_TRI_012_1_1_2 : SOC_TH_PORT_RATIO_TRI_012_1_1_4;
   1053             if (initTime && si->os_mixed_sister_25_50_enable) {
   1054                 *mode = ((speed_max[0] == 25000 && speed_max[2] == 50000) ||
   1055                          (speed_max[0] == 27000 && speed_max[2] == 53000)) ?
   1056                     SOC_TH_PORT_RATIO_DUAL_1_1 : cur_mode;
   1057             }
   1058         }
   1059     } else {
   1060         *mode = cur_mode = SOC_TH_PORT_RATIO_QUAD;
   1061 
   1062         if (initTime && si->os_mixed_sister_25_50_enable) {
   1063             port_sub = si->port_p2l_mapping[phy_port_base + 1];
   1064             port_sis = si->port_p2l_mapping[phy_port_base + 3];
   1065             *mode = (((speed_max[0] == 25000 && speed_max[2] == 25000) ||
   1066                       (speed_max[0] == 27000 && speed_max[2] == 27000)) &&
   1067                      SOC_PBMP_MEMBER(si->all.disabled_bitmap, port_sub) &&
   1068                      SOC_PBMP_MEMBER(si->all.disabled_bitmap, port_sis)) ?
   1069                      SOC_TH_PORT_RATIO_DUAL_1_1 : cur_mode;
   1070         }
   1071     }
   1072 }
   1073 
   1074 #if 0
   1075 STATIC void
   1076 _soc_tomahawk_pipe_bandwidth_get(int unit, int pipe,
   1077                                  int *max_pipe_core_bandwidth,
   1078                                  int *pipe_linerate_bandwidth,
   1079                                  int *pipe_oversub_bandwidth)
   1080 {
   1081     soc_info_t *si;
   1082     int port;
   1083     int bandwidth;
   1084 
   1085     si = &SOC_INFO(unit);
   1086 
   1087     *max_pipe_core_bandwidth = si->bandwidth / 4;
   1088 
   1089     *pipe_linerate_bandwidth = 0;
   1090     *pipe_oversub_bandwidth = 0;
   1091     PBMP_PORT_ITER(unit, port) {
   1092         if (si->port_pipe[port] != pipe) {
   1093             continue;
   1094         }
   1095         bandwidth = si->port_speed_max[port] >= 2500 ?
   1096             si->port_speed_max[port] : 2500;
   1097         if (SOC_PBMP_MEMBER(si->oversub_pbm, port)) {
   1098             *pipe_oversub_bandwidth += bandwidth;
   1099         } else {
   1100             *pipe_linerate_bandwidth += bandwidth;
   1101         }
   1102     }
   1103     /* 10G cpu/management, 5G loopback, 10G purge/refresh */
   1104     *pipe_linerate_bandwidth += 25;
   1105 }
   1106 #endif
   1107 
   1108 /*
   1109  * Oversubscription group speed class encoding
   1110  * 0 - 0
   1111  * 1 - 2 (10G)
   1112  * 2 - 4 (20G)
   1113  * 3 - 5 (25G)
   1114  * 4 - 8 (40G)
   1115  * 5 - 10 (50G)
   1116  * 6 - 20 (100G)
   1117  */
   1118 void
   1119 _soc_tomahawk_speed_to_ovs_class_mapping(int unit, int speed, int *ovs_class)
   1120 {
   1121     if (speed >= 40000) {
   1122         if (speed >= 100000) {
   1123             *ovs_class = 6;
   1124         } else if (speed >= 50000) {
   1125             *ovs_class = 5;
   1126         } else {
   1127             *ovs_class = 4;
   1128         }
   1129     } else {
   1130         if (speed >= 25000) {
   1131             *ovs_class = 3;
   1132         } else if (speed >= 20000) {
   1133             *ovs_class = 2;
   1134         } else {
   1135             *ovs_class = 1;
   1136         }
   1137     }
   1138 }
   1139 
   1140 void
   1141 _soc_tomahawk_speed_to_slot_mapping(int unit, int speed, int *slot)
   1142 {
   1143     if (speed >= 40000) {
   1144         if (speed >= 100000) {
   1145             *slot = 40;
   1146         } else if (speed >= 50000) {
   1147             *slot = 20;
   1148         } else {
   1149             *slot = 16;
   1150         }
   1151     } else {
   1152         if (speed >= 25000) {
   1153             *slot = 10;
   1154         } else if (speed >= 20000) {
   1155             *slot = 8;
   1156         } else if (speed >= 10000) {
   1157             *slot = 4;
   1158         } else {
   1159             *slot = 1;
   1160         }
   1161     }
   1162 }
   1163 
   1164 static int _soc_th_port_speed_cap[SOC_MAX_NUM_DEVICES][132] = {{ 0 }};
   1165 
   1166 STATIC int
   1167 _soc_th_post_mmu_init_update(int unit)
   1168 {
   1169     int port;
   1170     soc_info_t *si = &SOC_INFO(unit);
   1171 
   1172 #ifdef BCM_TOMAHAWK2_SUPPORT
   1173     if (SOC_IS_TOMAHAWK2(unit)) {
   1174         return soc_th2_post_mmu_init_update(unit);
   1175     }
   1176 #endif
   1177 
   1178     PBMP_ALL_ITER(unit, port) {
   1179         /* Set init speed to max speed by default */
   1180         si->port_init_speed[port] = si->port_speed_max[port];
   1181         if (_soc_th_port_speed_cap[unit][port]) {
   1182             /* If cap speed is available then adjust max speed for further use */
   1183             si->port_speed_max[port] = _soc_th_port_speed_cap[unit][port];
   1184         }
   1185     }
   1186     return SOC_E_NONE;
   1187 }
   1188 
   1189 /*
   1190  * FUNCTION : soc_th_bypass_unused_pm
   1191  * ARGS:
   1192  *         unit    -    IN, unit number
   1193  * Description :
   1194  * Bypass unused port blocks, by programming TOP_TSC_ENABLEr
   1195  * appropriately.
   1196  */
   1197 soc_error_t
   1198 soc_th_bypass_unused_pm(int unit)
   1199 {
   1200     int port, phy_port, pm, block, bn;
   1201     uint32 rval = 0, orval, xrval;
   1202     soc_info_t *si = &SOC_INFO(unit);
   1203     uint8 used_pm_map[_TH_PBLKS_PER_DEV + 1]; /* #CLPORT + #XLPORT */
   1204     soc_reg_t reg = TOP_TSC_ENABLEr;
   1205     soc_field_t reg_field[_TH_PBLKS_PER_DEV] = {
   1206         TSC_0_ENABLEf, TSC_1_ENABLEf, TSC_2_ENABLEf, TSC_3_ENABLEf,
   1207         TSC_4_ENABLEf, TSC_5_ENABLEf, TSC_6_ENABLEf, TSC_7_ENABLEf,
   1208         TSC_8_ENABLEf, TSC_9_ENABLEf, TSC_10_ENABLEf, TSC_11_ENABLEf,
   1209         TSC_12_ENABLEf, TSC_13_ENABLEf, TSC_14_ENABLEf, TSC_15_ENABLEf,
   1210         TSC_16_ENABLEf, TSC_17_ENABLEf, TSC_18_ENABLEf, TSC_19_ENABLEf,
   1211         TSC_20_ENABLEf, TSC_21_ENABLEf, TSC_22_ENABLEf, TSC_23_ENABLEf,
   1212         TSC_24_ENABLEf, TSC_25_ENABLEf, TSC_26_ENABLEf, TSC_27_ENABLEf,
   1213         TSC_28_ENABLEf, TSC_29_ENABLEf, TSC_30_ENABLEf, TSC_31_ENABLEf
   1214     };
   1215 
   1216     sal_memset(used_pm_map, 0, sizeof(used_pm_map));
   1217     for (phy_port = 1; phy_port <= _TH_PORTS_PER_DEV; phy_port++) {
   1218         port = si->port_p2l_mapping[phy_port];
   1219         pm = si->port_serdes[port];
   1220         if ((-1 != pm) && (0 == used_pm_map[pm])) {
   1221             used_pm_map[pm] = 1;
   1222         }
   1223     }
   1224     SOC_IF_ERROR_RETURN(READ_TOP_TSC_ENABLEr(unit, &rval));
   1225     orval = rval;
   1226     /* Upper loop bound omits XLPORT block intentionally */
   1227     for (pm = 0; pm < _TH_PBLKS_PER_DEV; pm++) {
   1228         /* If PM is not used, bypass it */
   1229         if (0 == used_pm_map[pm]) {
   1230             soc_reg_field_set(unit, reg, &rval, reg_field[pm], 0);
   1231             phy_port = 1 + (pm * _TH_PORTS_PER_PBLK);
   1232             block = SOC_PORT_BLOCK(unit, phy_port);
   1233             /* Invalidate port block in soc info */
   1234             if (SOC_BLK_CLPORT == SOC_BLOCK_INFO(unit, block).type) {
   1235                 si->block_valid[block] = 0;
   1236             }
   1237         }
   1238     }
   1239     if (rval != orval) {
   1240         /*Calculate different bits number between old and new*/
   1241         xrval = rval ^ orval;
   1242         for (bn = 0; xrval != 0; bn++) {
   1243             xrval &= (xrval - 1);
   1244         }
   1245 
   1246         /*Do two steps configuration change for the case of different bits number beyond 10*/
   1247         if (bn > 10) {
   1248             /*Change half of those different bits to new at first*/
   1249             bn /= 2;
   1250             xrval = rval ^ orval;
   1251             do {
   1252                 xrval &= (xrval-1);
   1253             } while (bn-- > 0);
   1254             xrval ^= rval;
   1255             SOC_IF_ERROR_RETURN(WRITE_TOP_TSC_ENABLEr(unit, xrval));
   1256             sal_usleep(100000);
   1257         }
   1258         SOC_IF_ERROR_RETURN(WRITE_TOP_TSC_ENABLEr(unit, rval));
   1259         sal_usleep(100000);
   1260     }
   1261 
   1262     return SOC_E_NONE;
   1263 }
   1264 
   1265 #ifdef BCM_TOMAHAWKX_SUPPORT
   1266 static int
   1267  _soc_tomahawk_phy_dev_port_check(int unit, int phy_port, int dev_port)
   1268 {
   1269     int num_phy_port = 136;
   1270 
   1271     if( phy_port < 0 || phy_port >= num_phy_port) {
   1272         return FALSE;
   1273     } else if ( phy_port >= 1 && phy_port <= 32) {
   1274         return ( dev_port >= 1 && dev_port <=32 );
   1275     } else if ( phy_port >= 33 && phy_port <= 64) {
   1276         return ( dev_port >= 34 && dev_port <= 66 );
   1277     } else if ( phy_port >= 65 && phy_port <= 96) {
   1278         return ( dev_port >= 68 && dev_port <= 100 );
   1279     } else if ( phy_port >= 97 && phy_port <= 128) {
   1280         return ( dev_port >= 102 && dev_port <= 133 );
   1281     } else if ( phy_port == 129) {
   1282         return ( dev_port >= 34 && dev_port <= 66 );
   1283     } else if ( phy_port == 131) {
   1284         return ( dev_port >= 68 && dev_port <= 100 );
   1285     } else {
   1286         /*skip LBPORT(132,133,134,135) , CPU port(0) and hole (130)*/
   1287         return TRUE;
   1288     }
   1289 
   1290 }
   1291 #endif
   1292 
   1293 /*
   1294  * Tomahawk port mapping
   1295  *
   1296  *                   physical   idb/       device   mmu
   1297  *                   port       idb port   port     port
   1298  *     CMIC          0          0/32       0        32
   1299  *     CLPORT0-7     1-32       0/0-31     1-32     0-31
   1300  *     CLPORT8-15    33-64      1/0-31     34-66    64-95
   1301  *     CLPORT16-23   65-96      2/0-31     68-100   128-159
   1302  *     CLPORT24-31   97-128     3/0-31     102-133  192-223
   1303  *     XLPORT0/0     129        1/32       34-66    96
   1304  *     hole          130        3/32       134      224
   1305  *     XLPORT0/2     131        2/32       68-100   160
   1306  *     LBPORT0       132        0/33       33       33
   1307  *     LBPORT1       133        1/33       67       97
   1308  *     LBPORT2       134        2/33       101      161
   1309  *     LBPORT3       135        3/33       135      225
   1310  * Software uses device port 135 for LBPORT3 although it can be 134
   1311  * Device port number is flexible within the above range
   1312  * Although MMU port number is flexible within the above range, it is
   1313  *     configured as a fixed mapped to physical port number
   1314  */
   1315 int
   1316 soc_tomahawk_port_config_init(int unit, uint16 dev_id)
   1317 {
   1318 #ifdef BCM_TOMAHAWKX_SUPPORT
   1319     soc_info_t *si;
   1320     char *config_str, *sub_str, *sub_str_end;
   1321     static const char str_2p5[] = "2.5";
   1322     char str_buf[8];
   1323     int rv, oversub_mode, frequency, os_mixed_sister_25_50_enable;
   1324     int num_port, num_phy_port, num_mmu_port;
   1325     int port, phy_port, mmu_port, idb_port;
   1326     int pipe, xpe, sc, index, bandwidth_cap;
   1327     int port_bandwidth, freq_list_len;
   1328     char option1, option2;
   1329     uint32 pipe_map, xpe_map, sc_map, ipipe_map, epipe_map;
   1330     soc_pbmp_t oversub_pbm;
   1331     static const int freq_list[] = { 850, 765, 672, 645, 545 };
   1332     static const struct {
   1333         int port;
   1334         int phy_port;
   1335         int pipe;
   1336         int idb_port;
   1337         int mmu_port;
   1338     } fixed_ports[] = {
   1339         { 0,   0,   0, 32, 32 },    /* cpu port */
   1340         { 33,  132, 0, 33, 33 },    /* loopback port 0 */
   1341         { 67,  133, 1, 33, 97 },    /* loopback port 1 */
   1342         { 101, 134, 2, 33, 161 },   /* loopback port 2 */
   1343         { 135, 135, 3, 33, 225 }    /* loopback port 3 */
   1344     };
   1345 
   1346     si = &SOC_INFO(unit);
   1347 
   1348     si->flex_eligible = FALSE;
   1349 
   1350     num_phy_port = 136;
   1351     num_port = 136;
   1352     num_mmu_port = 226;
   1353 
   1354     /* Can't read TOP register at this point */
   1355     soc_tomahawk_max_frequency_get(unit, dev_id, -1, -1, &si->frequency);
   1356     frequency = soc_property_get(unit, spn_CORE_CLOCK_FREQUENCY, -1);
   1357     /*frequency = rev_id == BCM56965_A0_REV_ID ? 545 : frequency;*/
   1358 
   1359     si->bandwidth = /*rev_id == BCM56965_A0_REV_ID ? 1024000 :*/ 2048000;
   1360 
   1361     if (frequency != -1 && frequency < si->frequency) {
   1362         freq_list_len = COUNTOF(freq_list);
   1363         for (index = 1; index < freq_list_len; index++) { /* skip index 0 */
   1364             if (freq_list[index] < si->frequency &&
   1365                 frequency == freq_list[index]) {
   1366                 break;
   1367             }
   1368         }
   1369 
   1370         if (index < freq_list_len) {
   1371             si->frequency = frequency;
   1372         } else {
   1373             LOG_CLI((BSL_META_U(unit,
   1374                                 "*** Input core clock frequency %dMHz is not "
   1375                                 "supported!\n"), frequency));
   1376         }
   1377     } else if (frequency > si->frequency) {
   1378         LOG_CLI((BSL_META_U(unit,
   1379                             "*** Input core clock frequency %dMHz is not supported!\n"),
   1380                  frequency));
   1381     }
   1382 
   1383 
   1384     SOC_PBMP_CLEAR(oversub_pbm);
   1385     oversub_mode = soc_property_get(unit, spn_OVERSUBSCRIBE_MODE, 0);
   1386     oversub_pbm  = soc_property_get_pbmp(unit, spn_PBMP_OVERSUBSCRIBE, 0);
   1387     oversub_mode = oversub_mode || SOC_PBMP_NOT_NULL(oversub_pbm);
   1388     si->oversub_mode = oversub_mode;
   1389     os_mixed_sister_25_50_enable = soc_property_get(unit, spn_OVERSUBSCRIBE_MIXED_SISTER_25_50_ENABLE, 0);
   1390     if (oversub_mode) {
   1391         si->os_mixed_sister_25_50_enable = os_mixed_sister_25_50_enable;
   1392     } else {
   1393         si->os_mixed_sister_25_50_enable = 0;
   1394     }
   1395 
   1396     for (phy_port = 0; phy_port < num_phy_port; phy_port++) {
   1397         si->port_p2l_mapping[phy_port] = -1;
   1398         si->port_p2m_mapping[phy_port] = -1;
   1399     }
   1400     for (port = 0; port < num_port; port++) {
   1401         si->port_l2p_mapping[port] = -1;
   1402         si->port_l2i_mapping[port] = -1;
   1403         si->port_speed_max[port] = -1;
   1404         si->port_group[port] = -1;
   1405         si->port_serdes[port] = -1;
   1406         si->port_pipe[port] = -1;
   1407         si->port_num_lanes[port] = -1;
   1408     }
   1409     for (mmu_port = 0; mmu_port < num_mmu_port; mmu_port++) {
   1410         si->port_m2p_mapping[mmu_port] = -1;
   1411     }
   1412     SOC_PBMP_CLEAR(si->eq_pbm);
   1413     SOC_PBMP_CLEAR(si->management_pbm);
   1414     for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) {
   1415         SOC_PBMP_CLEAR(si->pipe_pbm[pipe]);
   1416     };
   1417     SOC_PBMP_CLEAR(si->oversub_pbm);
   1418     SOC_PBMP_CLEAR(si->all.disabled_bitmap);
   1419 
   1420     /* Populate the fixed mapped ports */
   1421     for (index = 0; index < COUNTOF(fixed_ports); index++) {
   1422         port = fixed_ports[index].port;
   1423         phy_port = fixed_ports[index].phy_port;
   1424         pipe = fixed_ports[index].pipe;;
   1425 
   1426         si->port_l2p_mapping[port] = phy_port;
   1427         si->port_l2i_mapping[port] = fixed_ports[index].idb_port;
   1428         si->port_p2l_mapping[phy_port] = port;
   1429         si->port_p2m_mapping[phy_port] = fixed_ports[index].mmu_port;
   1430         si->port_pipe[port] = pipe;
   1431     }
   1432 
   1433     rv = SOC_E_NONE;
   1434     for (port = 1; port < num_port; port++) {
   1435         if (si->port_l2p_mapping[port] != -1) { /* fixed mapped port */
   1436             continue;
   1437         }
   1438         if (port == 134) { /* SDK uses device port 135 for loopback port 3 */
   1439             continue;
   1440         }
   1441 
   1442         config_str = soc_property_port_get_str(unit, port, spn_PORTMAP);
   1443         if (config_str == NULL) {
   1444             continue;
   1445         }
   1446 
   1447         /*
   1448          * portmap_<port>=<physical port number>:<bandwidth in Gb>[:<bandwidth cap in Gb/i(inactive)/1/2/4(num lanes)>][:<i>]
   1449          * eg:    portmap_1=1:100
   1450          *     or portmap_1=1:40
   1451          *     or portmap_1=1:40:i
   1452          *     or portmap_1=1:40:2
   1453          *     or portmap_1=1:40:2:i
   1454          *     or portmap_1=1:10:100
   1455          */
   1456         sub_str = config_str;
   1457 
   1458         /* Parse physical port number */
   1459         phy_port = sal_ctoi(sub_str, &sub_str_end);
   1460         if (sub_str == sub_str_end) {
   1461             LOG_CLI((BSL_META_U(unit,
   1462                                 "Port %d: Missing physical port information \"%s\"\n"),
   1463                      port, config_str));
   1464             rv = SOC_E_FAIL;
   1465             continue;
   1466         }
   1467         if (phy_port < 0 || phy_port >= num_phy_port) {
   1468             LOG_CLI((BSL_META_U(unit,
   1469                                 "Port %d: Invalid physical port number %d\n"),
   1470                      port, phy_port));
   1471             rv = SOC_E_FAIL;
   1472             continue;
   1473         }
   1474         if (!_soc_tomahawk_phy_dev_port_check(unit, phy_port, port)) {
   1475             LOG_CLI((BSL_META_U(unit,
   1476                                 "Port %d: Invalid mapping physical port number %d\n"),
   1477                      port, phy_port));
   1478             rv = SOC_E_FAIL;
   1479             continue;
   1480         }
   1481         /* coverity[check_after_sink : FALSE] */
   1482         if (si->port_p2l_mapping[phy_port] != -1) {
   1483             LOG_CLI((BSL_META_U(unit,
   1484                                 "Port %d: Physical port %d is used by port %d\n"),
   1485                      port, phy_port, si->port_p2l_mapping[phy_port]));
   1486             rv = SOC_E_FAIL;
   1487             continue;
   1488         }
   1489 
   1490         /* Skip ':' between physical port number and bandwidth */
   1491         sub_str = sub_str_end;
   1492         if (*sub_str != '\0') {
   1493             if (*sub_str != ':') {
   1494                 LOG_CLI((BSL_META_U(unit,
   1495                                     "Port %d: Bad config string \"%s\"\n"),
   1496                          port, config_str));
   1497                 rv = SOC_E_FAIL;
   1498                 continue;
   1499             }
   1500             sub_str++;
   1501         }
   1502 
   1503         /* Parse bandwidth */
   1504         for (index = 0; index < sizeof(str_2p5) - 1; index++) {
   1505             if (sub_str[index] == '\0') {
   1506                 break;
   1507             }
   1508             str_buf[index] = sub_str[index];
   1509         }
   1510         str_buf[index] = '\0';
   1511         if (!sal_strcmp(str_buf, str_2p5)) {
   1512             port_bandwidth = 2500;
   1513             sub_str_end = &sub_str[sizeof(str_2p5) - 1];
   1514         } else {
   1515             port_bandwidth = sal_ctoi(sub_str, &sub_str_end) * 1000;
   1516             if (sub_str == sub_str_end) {
   1517                 LOG_CLI((BSL_META_U(unit,
   1518                                     "Port %d: Missing bandwidth information \"%s\"\n"),
   1519                          port, config_str));
   1520                 rv = SOC_E_FAIL;
   1521                 continue;
   1522             }
   1523             switch (port_bandwidth) {
   1524             case 1000:
   1525             case 10000:
   1526             case 11000:
   1527             case 20000:
   1528             case 21000:
   1529             case 25000:
   1530             case 27000:
   1531             case 40000:
   1532             case 42000:
   1533             case 50000:
   1534             case 53000:
   1535             case 100000:
   1536             case 106000:
   1537                 break;
   1538             default:
   1539                 LOG_CLI((BSL_META_U(unit,
   1540                                     "Port %d: Invalid bandwidth %d Gb\n"),
   1541                          port, port_bandwidth / 1000));
   1542                 rv = SOC_E_FAIL;
   1543                 continue;
   1544             }
   1545         }
   1546 
   1547         /* Check if option presents */
   1548         option1 = 0; option2 = 0;
   1549         sub_str = sub_str_end;
   1550         if (*sub_str != '\0') {
   1551             /* Skip ':' between bandwidth and cap or options */
   1552             if (*sub_str != ':') {
   1553                 LOG_CLI((BSL_META_U(unit,
   1554                                     "Port %d: Bad config string \"%s\"\n"),
   1555                          port, config_str));
   1556                 rv = SOC_E_FAIL;
   1557                 continue;
   1558             }
   1559             sub_str++;
   1560 
   1561             if (*sub_str != '\0') {
   1562                 /* Parse bandwidth cap or options */
   1563                 bandwidth_cap = sal_ctoi(sub_str, &sub_str_end) * 1000;
   1564                 /* For distinguish 1G cap or lane 1, left-to-right */
   1565                 if ((bandwidth_cap == 1000) &&
   1566                     (bandwidth_cap < port_bandwidth)) {
   1567                     bandwidth_cap = 0;
   1568                 }
   1569                 switch (bandwidth_cap) {
   1570                 case 1000:
   1571                 case 10000:
   1572                 case 11000:
   1573                 case 20000:
   1574                 case 21000:
   1575                 case 25000:
   1576                 case 27000:
   1577                 case 40000:
   1578                 case 42000:
   1579                 case 50000:
   1580                 case 53000:
   1581                 case 100000:
   1582                 case 106000:
   1583                     sub_str = sub_str_end;
   1584                     _soc_th_port_speed_cap[unit][port] = bandwidth_cap;
   1585                     /* Flex config detected, port speed cap specified */
   1586                     si->flex_eligible = TRUE;
   1587                     break;
   1588                 default:
   1589                     if (!(*sub_str == 'i' || *sub_str == '1' || *sub_str == '2' ||
   1590                           *sub_str == '4')) {
   1591                         LOG_CLI((BSL_META_U(unit,
   1592                                             "Port %d: Bad config string \"%s\"\n"),
   1593                                  port, config_str));
   1594                         rv = SOC_E_FAIL;
   1595                         continue;
   1596                     } else {
   1597                         option1 = *sub_str;
   1598                         sub_str++;
   1599                     }
   1600                 }
   1601                 /* Check if more options present */
   1602                 if (*sub_str != '\0') {
   1603                     /* Skip ':' between options */
   1604                     if (*sub_str != ':') {
   1605                         LOG_CLI((BSL_META_U(unit,
   1606                                             "Port %d: Bad config string \"%s\"\n"),
   1607                                  port, config_str));
   1608                         rv = SOC_E_FAIL;
   1609                         continue;
   1610                     }
   1611                     sub_str++;
   1612 
   1613                     if (*sub_str != 'i') {
   1614                         LOG_CLI((BSL_META_U(unit,
   1615                                             "Port %d: Bad config string \"%s\"\n"),
   1616                                  port, config_str));
   1617                         rv = SOC_E_FAIL;
   1618                         continue;
   1619                     }
   1620                     option2 = *sub_str;
   1621                     sub_str++;
   1622                 }
   1623             }
   1624         }
   1625 
   1626         /* Check trailing string */
   1627         if (*sub_str != '\0') {
   1628             LOG_CLI((BSL_META_U(unit,
   1629                                 "Port %d: Bad config string \"%s\"\n"),
   1630                      port, config_str));
   1631             rv = SOC_E_FAIL;
   1632             continue;
   1633         }
   1634 
   1635         /* Update soc_info */
   1636         si->port_l2p_mapping[port] = phy_port;
   1637         si->port_p2l_mapping[phy_port] = port;
   1638         if (phy_port == 129) { /* management port 0 */
   1639             pipe = 1;
   1640             si->port_l2i_mapping[port] = 32;
   1641             si->port_p2m_mapping[phy_port] = 96;
   1642             si->port_serdes[port] = 32;
   1643             SOC_PBMP_PORT_ADD(si->management_pbm, port);
   1644         } else if (phy_port == 131) { /* management port 1 */
   1645             pipe = 2;
   1646             si->port_l2i_mapping[port] = 32;
   1647             si->port_p2m_mapping[phy_port] = 160;
   1648             si->port_serdes[port] = 32;
   1649             SOC_PBMP_PORT_ADD(si->management_pbm, port);
   1650         } else {
   1651             idb_port = (phy_port - 1) % _TH_PORTS_PER_PIPE;
   1652             pipe = (phy_port - 1) / _TH_PORTS_PER_PIPE;
   1653             si->port_l2i_mapping[port] = idb_port;
   1654             si->port_p2m_mapping[phy_port] =
   1655                 (pipe << 6) | ((idb_port & 0x1) << 4) | (idb_port >> 1);
   1656             si->port_serdes[port] = (phy_port - 1) / _TH_PORTS_PER_PBLK;
   1657         }
   1658         si->port_pipe[port] = pipe;
   1659         SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port);
   1660         si->port_speed_max[port] = port_bandwidth;
   1661         if (option1 == 'i') {
   1662             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port);
   1663         } else {
   1664             switch (option1) {
   1665             case '1': si->port_num_lanes[port] = 1; break;
   1666             case '2': si->port_num_lanes[port] = 2; break;
   1667             case '4': si->port_num_lanes[port] = 4; break;
   1668             default: break;
   1669             }
   1670         }
   1671         if (option2 == 'i') {
   1672             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port);
   1673         }
   1674         if (oversub_mode) {
   1675             SOC_PBMP_PORT_ADD(si->oversub_pbm, port);
   1676         }
   1677     }
   1678     /* Flex config detected, disabled ports in config */
   1679     if (SOC_PBMP_NOT_NULL(SOC_PORT_DISABLED_BITMAP(unit, all))) {
   1680         si->flex_eligible = TRUE;
   1681     }
   1682 
   1683     for (index = 1; index < COUNTOF(fixed_ports); index++) {
   1684         pipe = fixed_ports[index].pipe;
   1685         port = fixed_ports[index].port;
   1686         phy_port = fixed_ports[index].phy_port;
   1687         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   1688             /* Remove loopback port if the entire pipe is not in use */
   1689             si->port_l2p_mapping[port] = -1;
   1690             si->port_l2i_mapping[port] = -1;
   1691             si->port_p2l_mapping[phy_port] = -1;
   1692             si->port_p2m_mapping[phy_port] = -1;
   1693             si->port_pipe[port] = -1;
   1694         } else {
   1695             SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port);
   1696         }
   1697     }
   1698 
   1699     /* Since in tomahawk, CPU port's Queues and Scheduling nodes are bound to
   1700        pipeline 0, add CPU Port to PIPE_PBM of PIPE 0 */
   1701     SOC_PBMP_PORT_ADD(si->pipe_pbm[0], CMIC_PORT(unit));
   1702 
   1703     if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
   1704         LOG_CLI((BSL_META_U(unit,
   1705                             "physical to logical mapping:")));
   1706         for (index = 0; index < num_phy_port; index++) {
   1707             if (index % 16 == 0) {
   1708                 LOG_CLI((BSL_META_U(unit,
   1709                                     "\n    ")));
   1710             }
   1711             LOG_CLI((BSL_META_U(unit,
   1712                                 " %3d"), si->port_p2l_mapping[index]));
   1713         }
   1714         LOG_CLI((BSL_META_U(unit,
   1715                             "\n")));
   1716         LOG_CLI((BSL_META_U(unit,
   1717                             "physical port bandwidth:")));
   1718         for (index = 0; index < num_phy_port; index++) {
   1719             if (index % 16 == 0) {
   1720                 LOG_CLI((BSL_META_U(unit,
   1721                                     "\n    ")));
   1722             }
   1723             port = si->port_p2l_mapping[index];
   1724             if (port == -1) {
   1725                 LOG_CLI((BSL_META_U(unit,
   1726                                     "  -1")));
   1727             } else if (si->port_speed_max[port] == 2500) {
   1728                 LOG_CLI((BSL_META_U(unit,
   1729                                     " 2.5")));
   1730             } else {
   1731                 LOG_CLI((BSL_META_U(unit,
   1732                                     " %3d"), si->port_speed_max[port] / 1000));
   1733             }
   1734         }
   1735         LOG_CLI((BSL_META_U(unit,
   1736                             "\n")));
   1737 
   1738         LOG_CLI((BSL_META_U(unit,
   1739                             "physical to mmu mapping:")));
   1740         for (index = 0; index < num_phy_port; index++) {
   1741             if (index % 16 == 0) {
   1742                 LOG_CLI((BSL_META_U(unit,
   1743                                     "\n    ")));
   1744             }
   1745             LOG_CLI((BSL_META_U(unit,
   1746                                 " %3d"), si->port_p2m_mapping[index]));
   1747         }
   1748         LOG_CLI((BSL_META_U(unit,
   1749                             "\n")));
   1750     }
   1751 
   1752     
   1753 
   1754     /* Setup port_num_lanes */
   1755     for (port = 0; port < num_port; port++) {
   1756         if (si->port_speed_max[port] > 53000) {
   1757             si->port_num_lanes[port] = 4;
   1758         } else if (si->port_speed_max[port] == 40000 ||
   1759                    si->port_speed_max[port] == 42000) {
   1760             /* Note: 40G, HG[42] can operate either in dual or quad lane mode
   1761                      Check if adjacent ports exist to set dual lane mode */
   1762             phy_port = si->port_l2p_mapping[port];
   1763             if (phy_port >= 1 && phy_port <= 127 && phy_port != -1) {
   1764                 int sis_port;
   1765 
   1766                 if (phy_port % 4 == 1) {
   1767                     sis_port = si->port_p2l_mapping[phy_port+2];
   1768                     if ((si->port_speed_max[sis_port] > 0) &&
   1769                         !SOC_PBMP_MEMBER(si->all.disabled_bitmap, sis_port)) {
   1770                         si->port_num_lanes[port] = 2;
   1771                     }
   1772                 } else if (phy_port % 4 == 3) {
   1773                     sis_port = si->port_p2l_mapping[phy_port-2];
   1774                     if ((si->port_speed_max[sis_port] > 0) &&
   1775                         !SOC_PBMP_MEMBER(si->all.disabled_bitmap, sis_port)) {
   1776                         si->port_num_lanes[port] = 2;
   1777                     }
   1778                 }
   1779             }
   1780             /* Else set to quad lane mode by default if the user did not
   1781                specify anything and no sister ports existed */
   1782             if (si->port_num_lanes[port] == -1) {
   1783                 si->port_num_lanes[port] = 4;
   1784             }
   1785         } else if ((si->port_speed_max[port] >= 20000) &&
   1786                     !(si->port_speed_max[port] == 25000 ||
   1787                       si->port_speed_max[port] == 27000)) {
   1788             /* 50G, HG[53], 20G MLD, HG[21] use 2 lanes */
   1789             si->port_num_lanes[port] = 2;
   1790         } else if (si->port_speed_max[port] > 0) {
   1791             /* 10G XFI, HG[11], 25G XFI and HG[27] use 1 lane */
   1792             if (si->port_num_lanes[port] == -1) {
   1793                 /* But RXAUI and XAUI on mgmt ports use 2 and 4 lanes, which
   1794                  * can be provided via the portmap interface.
   1795                  */
   1796                 si->port_num_lanes[port] = 1;
   1797             }
   1798         }
   1799     }
   1800 
   1801     /* Setup high speed port (HSP) pbm */
   1802     for (port = 0; port < num_port; port++) {
   1803         phy_port = si->port_l2p_mapping[port];
   1804         if (phy_port == -1) {
   1805             continue;
   1806         }
   1807         if (si->port_speed_max[port] >= 40000) {
   1808             SOC_PBMP_PORT_ADD(si->eq_pbm, port);
   1809         }
   1810     }
   1811 
   1812     /* Setup pipe/xpe mapping
   1813      * XPE0 (SC_R/XPE_A): IP 0/3 EP 0/1
   1814      * XPE1 (SC_S/XPE_A): IP 0/3 EP 2/3
   1815      * XPE2 (SC_R/XPE_B): IP 1/2 EP 0/1
   1816      * XPE3 (SC_S/XPE_B): IP 1/2 EP 2/3
   1817      */
   1818     pipe_map = 0;
   1819     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   1820         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   1821             continue;
   1822         }
   1823         pipe_map |= 1 << pipe;
   1824     }
   1825     xpe_map = 0;
   1826     for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   1827         ipipe_map = (xpe < 2 ? 0x9 : 0x6) & pipe_map;
   1828         epipe_map = (xpe & 1 ? 0xc : 0x3) & pipe_map;
   1829         if (ipipe_map == 0 || epipe_map == 0) {
   1830             continue;
   1831         }
   1832         xpe_map |= 1 << xpe;
   1833         si->xpe_ipipe_map[xpe] = ipipe_map;
   1834         si->xpe_epipe_map[xpe] = epipe_map;
   1835     }
   1836     sc_map = 0;
   1837     for (sc = 0; sc < NUM_SLICE(unit); sc++) {
   1838         ipipe_map = pipe_map;
   1839         epipe_map = (sc & 1 ? 0xc : 0x3) & pipe_map;
   1840         if (ipipe_map == 0 || epipe_map == 0) {
   1841             continue;
   1842         }
   1843         sc_map |= 1 << sc;
   1844         si->sc_ipipe_map[sc] = ipipe_map;
   1845         si->sc_epipe_map[sc] = epipe_map;
   1846     }
   1847     for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) {
   1848         /* Number of pipes is 4 in Tomahawk */
   1849         /* coverity[overrun-local : FALSE] */
   1850         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   1851             continue;
   1852         }
   1853         /* coverity[overrun-local : FALSE] */
   1854         si->ipipe_xpe_map[pipe] = (pipe == 0 || pipe == 3 ? 0x3 : 0xc) &
   1855             xpe_map;
   1856         /* coverity[overrun-local : FALSE] */
   1857         si->epipe_xpe_map[pipe] = (pipe < 2 ? 0x5 : 0xa) & xpe_map;
   1858         /* coverity[overrun-local : FALSE] */
   1859         si->ipipe_sc_map[pipe] = sc_map;
   1860         /* coverity[overrun-local : FALSE] */
   1861         si->epipe_sc_map[pipe] = (pipe < 2 ? 0x1 : 0x2) & sc_map;
   1862     }
   1863 
   1864     return rv;
   1865 #else
   1866     return SOC_E_UNAVAIL;
   1867 #endif
   1868 }
   1869 
   1870 #if defined(BCM_TOMAHAWK2_SUPPORT)
   1871 /*
   1872  * Function:
   1873  *      soc_th2_port_max_oversub_ratio_get
   1874  * Purpose:
   1875  *      Get the max OVS ratio among all half pipes in the device.
   1876  * Parameters:
   1877  *      unit - (IN) Unit number.
   1878  *      ratio - (OUT) Max OVS ratio among all half pipes in the device
   1879  * Returns:
   1880  *      SOC_E_xxx
   1881  * Notes:
   1882  */
   1883 STATIC int
   1884 soc_th2_port_max_oversub_ratio_get(
   1885     int              unit,
   1886     OUT int* const   ratio)
   1887 {
   1888     soc_info_t           *si;
   1889     _soc_tomahawk2_tdm_t *tdm;
   1890     int                  pipe, hpipe, max_ovs_ratio;
   1891 
   1892     if (!ratio) {
   1893         return SOC_E_PARAM;
   1894     }
   1895 
   1896     if (SAL_BOOT_XGSSIM) {
   1897         *ratio = 0;
   1898         return SOC_E_NONE;
   1899     }
   1900 
   1901     si = &SOC_INFO(unit);
   1902     tdm = SOC_CONTROL(unit)->tdm_info;
   1903 
   1904     if (!si || !tdm) {
   1905         return SOC_E_INTERNAL;
   1906     }
   1907 
   1908     max_ovs_ratio = 0;
   1909     for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe++) {
   1910         for (hpipe = 0; hpipe < _TH2_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) {
   1911             if (max_ovs_ratio < tdm->ovs_ratio_x1000[pipe][hpipe]) {
   1912                 max_ovs_ratio = tdm->ovs_ratio_x1000[pipe][hpipe];
   1913             }
   1914         }
   1915     }
   1916     *ratio = max_ovs_ratio;
   1917 
   1918     return SOC_E_NONE;
   1919 }
   1920 #endif
   1921 soc_error_t
   1922 soc_th_subsidiary_ports_get(int unit, soc_port_t port, soc_pbmp_t *pbmp)
   1923 {
   1924     soc_info_t *si = &SOC_INFO(unit);
   1925     soc_port_t phy_port_base, phy_port;
   1926     soc_pbmp_t pbm;
   1927     int max_subport;
   1928 
   1929     if (!SOC_PORT_VALID(unit, port) || IS_CPU_PORT(unit, port) ||
   1930         IS_LB_PORT(unit, port) ||
   1931         SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
   1932          /* CPU, LB and Management ports do not support flexport */
   1933         return SOC_E_PORT;
   1934     }
   1935 
   1936     phy_port = si->port_l2p_mapping[port];
   1937     if (-1 == phy_port) {
   1938         return SOC_E_PORT;
   1939     }
   1940     phy_port_base = PORT_BLOCK_BASE_PORT(port);
   1941 
   1942     /* Only lane 0 and lane 2 of a PM can be controlling ports */
   1943     if ((phy_port_base != phy_port) && ((phy_port_base + 2) != phy_port)) {
   1944         /* Not a controlling port */
   1945         return SOC_E_PORT;
   1946     }
   1947 
   1948 #ifdef BCM_TOMAHAWK3_SUPPORT
   1949     /* Tomahawk 3 has 8 lanes per PM instead of 4 */
   1950     if (SOC_IS_TOMAHAWK3(unit)) {
   1951         max_subport = phy_port + (8 - ((phy_port - 1) % 8));
   1952     } else
   1953 #endif
   1954     {
   1955         max_subport = phy_port + (4 - ((phy_port - 1) % 4));
   1956     }
   1957     SOC_PBMP_CLEAR(pbm);
   1958     for (; phy_port < max_subport; phy_port++) {
   1959         if (si->port_p2l_mapping[phy_port] == -1) {
   1960             continue;
   1961         }
   1962         SOC_PBMP_PORT_ADD(pbm, si->port_p2l_mapping[phy_port]);
   1963     }
   1964     SOC_PBMP_ASSIGN(*pbmp, pbm);
   1965 
   1966     return SOC_E_NONE;
   1967 }
   1968 
   1969 int
   1970 soc_th_port_oversub_ratio_get(
   1971     int              unit,
   1972     soc_port_t       port,
   1973     OUT int* const   ratio)
   1974 {
   1975     soc_info_t          *si;
   1976     _soc_tomahawk_tdm_t *tdm;
   1977     int                  pipe;
   1978 
   1979     if (!ratio) {
   1980         return SOC_E_PARAM;
   1981     }
   1982 
   1983 #if defined(BCM_TOMAHAWK2_SUPPORT)
   1984     if (SOC_IS_TOMAHAWK2(unit)) {
   1985         return soc_th2_port_max_oversub_ratio_get(unit, ratio);
   1986     }
   1987 #endif
   1988 
   1989     si = &SOC_INFO(unit);
   1990     tdm = SOC_CONTROL(unit)->tdm_info;
   1991 
   1992     if (!si || !tdm) {
   1993         return SOC_E_INTERNAL;
   1994     }
   1995 
   1996     pipe = si->port_pipe[port];
   1997     *ratio = tdm->ovs_ratio_x1000[pipe];
   1998 
   1999     return SOC_E_NONE;
   2000 }
   2001 
   2002 uint32 _soc_th_temp_mon_mask[SOC_MAX_NUM_DEVICES];
   2003 
   2004 static int
   2005 _soc_th_freq_val_sel(int frequency)
   2006 {
   2007     switch (frequency) {
   2008     case 850:
   2009         return 1;
   2010     case 765:
   2011         return 2;
   2012     case 672:
   2013         return 3;
   2014     case 645:
   2015         return 4;
   2016     case 545:
   2017         return 5;
   2018     default:
   2019         return 1;
   2020     }
   2021 }
   2022 
   2023 STATIC int _soc_tomahawk_clear_all_memory(int unit, int mmu_init);
   2024 STATIC int _soc_tomahawk_tdm_calculation_free_memory(int unit);
   2025 
   2026 int
   2027 soc_tomahawk_chip_reset(int unit)
   2028 {
   2029 #define _SOC_TH_LCPLL_COUNT    4
   2030 #define _SOC_TH_PLL_CFG_FIELDS 4
   2031 #define _SOC_TH_DEF_TEMP_MAX   125
   2032 #define _SOC_TH_NUM_PORTS      136
   2033 #define _SOC_TH_LINK_DELAY_REG_BASE   0x20000700   /* EGR_1588_LINK_DELAY_64 */
   2034 #define _SOC_TH_LINK_DELAY_REG_BLK    2            /* EPIPE BLOCKNUM */
   2035 
   2036     soc_info_t *si;
   2037     uint16 dev_id;
   2038     uint8 rev_id;
   2039     uint32 to_usec, temp_mask;
   2040     uint32 rval, temp_thr;
   2041     soc_reg_t reg;
   2042     int freq_sel, freq_list_len, max_frequency;
   2043     int num_banks, index, shared_bank, shared_bank_offset = 0;
   2044     int num_shared_l2_banks, num_shared_l3_banks, num_shared_fpem_banks;
   2045     uint32 config = 0, map = 0, fpmap = 0;
   2046     soc_field_t fields[_SOC_TH_PLL_CFG_FIELDS];
   2047     uint32 values[_SOC_TH_PLL_CFG_FIELDS];
   2048     static soc_field_t l2_fields[] = {
   2049         L2_ENTRY_BANK_2f, L2_ENTRY_BANK_3f, L2_ENTRY_BANK_4f,
   2050         L2_ENTRY_BANK_5f
   2051     };
   2052     static soc_field_t l3_fields[] = {
   2053         L3_ENTRY_BANK_4f, L3_ENTRY_BANK_5f, L3_ENTRY_BANK_6f,
   2054         L3_ENTRY_BANK_7f
   2055     };
   2056     static soc_field_t fpem_fields[] = {
   2057         FPEM_ENTRY_BANK_0f, FPEM_ENTRY_BANK_1f, FPEM_ENTRY_BANK_2f,
   2058         FPEM_ENTRY_BANK_3f
   2059     };
   2060     static const soc_reg_t lcpll_ctrl0_reg[] = {
   2061         TOP_XG_PLL0_CTRL_0r, TOP_XG_PLL1_CTRL_0r,
   2062         TOP_XG_PLL2_CTRL_0r, TOP_XG_PLL3_CTRL_0r
   2063     };
   2064     static const soc_reg_t lcpll_ctrl4_reg[] = {
   2065         TOP_XG_PLL0_CTRL_4r, TOP_XG_PLL1_CTRL_4r,
   2066         TOP_XG_PLL2_CTRL_4r, TOP_XG_PLL3_CTRL_4r
   2067     };
   2068     static const soc_reg_t lcpll_status_reg[] = {
   2069         TOP_XG_PLL0_STATUSr, TOP_XG_PLL1_STATUSr,
   2070         TOP_XG_PLL2_STATUSr, TOP_XG_PLL3_STATUSr
   2071     };
   2072     static const soc_reg_t temp_thr_reg[] = {
   2073         TOP_PVTMON_0_INTR_THRESHOLDr, TOP_PVTMON_1_INTR_THRESHOLDr,
   2074         TOP_PVTMON_2_INTR_THRESHOLDr, TOP_PVTMON_3_INTR_THRESHOLDr,
   2075         TOP_PVTMON_4_INTR_THRESHOLDr, TOP_PVTMON_5_INTR_THRESHOLDr,
   2076         TOP_PVTMON_6_INTR_THRESHOLDr, TOP_PVTMON_7_INTR_THRESHOLDr
   2077     };
   2078     static const char *temp_thr_prop[] = {
   2079         "temp0_threshold", "temp1_threshold", "temp2_threshold",
   2080         "temp3_threshold", "temp4_threshold", "temp5_threshold",
   2081         "temp6_threshold", "temp7_threshold"
   2082     };
   2083     static const int freq_list[] = { 850, 765, 672, 645, 545 };
   2084 
   2085     int port, acc;
   2086     uint64 rval64;
   2087 
   2088     /* Settings for 500 MHz TSPLL output clock. */
   2089     unsigned ts_ref_freq = 0;
   2090     unsigned ts_idx = 0;
   2091 
   2092     static const soc_pll_param_t ts_pll[] = {
   2093     /*     Fref, Ndiv_int, Ndiv_frac,  Pdiv, Mdiv, Ka, Ki, Kp, VCO_div2 */
   2094       {12800000,      195,   0x50000,     1,    5,  0,  2,  3,        1},
   2095       {20000000,      125,         0,     1,    5,  0,  2,  3,        1},
   2096       {25000000,      100,         0,     1,    5,  0,  2,  3,        1},
   2097       {32000000,       78,   0x20000,     1,    5,  0,  2,  3,        1},
   2098       {50000000,      100,         0,     2,    5,  0,  2,  3,        1},
   2099       {       0,      100,         0,     2,    5,  0,  2,  3,        1} /* 50 MHz internal reference. */
   2100     };
   2101 
   2102     /* Settings for 20 MHz BSPLL output clock. */
   2103     unsigned bs_ref_freq = 0;
   2104     unsigned bs_idx = 0;
   2105 
   2106     static const soc_pll_param_t bs_pll[] = {
   2107     /*     Fref, Ndiv_int, Ndiv_frac,  Pdiv, Mdiv, Ka, Ki, Kp, VCO_div2 */
   2108       {12800000,      195,   0x50000,     1,  125,  0,  2,  3,        1},
   2109       {20000000,      125,         0,     1,  125,  0,  2,  3,        1},
   2110       {25000000,      100,         0,     1,  125,  0,  2,  3,        1},
   2111       {32000000,       78,   0x20000,     1,  125,  0,  2,  3,        1},
   2112       {50000000,      100,         0,     2,  125,  0,  2,  3,        1},
   2113       {       0,      100,         0,     2,  125,  0,  2,  3,        1} /* 50 MHz internal reference. */
   2114     };
   2115 
   2116     si = &SOC_INFO(unit);
   2117     soc_cm_get_id(unit, &dev_id, &rev_id);
   2118     to_usec = SAL_BOOT_QUICKTURN ? (250 * MILLISECOND_USEC) :
   2119                                    (10 * MILLISECOND_USEC);
   2120 
   2121     /*
   2122      * SBUS ring and block number:
   2123      * ring 0: IP(1), LBPORT0(54), LBPORT1(51), LBPORT2(52), LBPORT3(53)
   2124      * ring 1: EP(2)
   2125      * ring 2: MMU_XPE(3), MMU_SC(4), MMU_GLB(5)
   2126      * ring 3: PM7(22), PM6(21), PM5(20), PM4(19), PM3(18), PM2(17), PM1(16),
   2127      *         PM0(15), PM31(46), PM30(45), PM29(44), PM28(43), PM27(42),
   2128      *         PM26(41), PM25(40), PM24(39), CLPORT32(55)
   2129      * ring 4: PM32(11), PM8(23), PM9(24), PM10(25), PM11(26), PM12(27),
   2130      *         PM13(28), PM14(29), PM15(30), PM16(31), PM17(32), PM18(33),
   2131      *         PM19(34), PM20(35), PM21(36), PM22(37), PM23(38)
   2132      * ring 5: OTPC(6), AVS(59), TOP(7), SER(8)
   2133      */
   2134 #ifdef BCM_CMICM_SUPPORT
   2135     if (soc_feature(unit, soc_feature_cmicm)) {
   2136         WRITE_CMIC_SBUS_RING_MAP_0_7r(unit, 0x55222100);
   2137         WRITE_CMIC_SBUS_RING_MAP_8_15r(unit, 0x30004005);
   2138         WRITE_CMIC_SBUS_RING_MAP_16_23r(unit, 0x43333333);
   2139         WRITE_CMIC_SBUS_RING_MAP_24_31r(unit, 0x44444444);
   2140         WRITE_CMIC_SBUS_RING_MAP_32_39r(unit, 0x34444444);
   2141         WRITE_CMIC_SBUS_RING_MAP_40_47r(unit, 0x03333333);
   2142         WRITE_CMIC_SBUS_RING_MAP_48_55r(unit, 0x30000000);
   2143         WRITE_CMIC_SBUS_RING_MAP_56_63r(unit, 0x00005000);
   2144         WRITE_CMIC_SBUS_TIMEOUTr(unit, 0x7d0);
   2145     }
   2146 #endif
   2147 
   2148 #ifdef BCM_CMICX_SUPPORT
   2149     if (soc_feature(unit, soc_feature_cmicx)) {
   2150         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_0_7_OFFSET,0x55222100);
   2151         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_8_15_OFFSET,0x30004005);
   2152         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_16_23_OFFSET,0x43333333);
   2153         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_24_31_OFFSET,0x44444444);
   2154         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_32_39_OFFSET,0x34444444);
   2155         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_40_47_OFFSET,0x03333333);
   2156         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_48_55_OFFSET,0x30000000);
   2157         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_56_63_OFFSET,0x00005000);
   2158         soc_pci_write(unit, CMIC_TOP_SBUS_TIMEOUT_OFFSET,0x7d0);
   2159     }
   2160 #endif
   2161     sal_usleep(to_usec);
   2162 
   2163 
   2164     SOC_IF_ERROR_RETURN
   2165         (soc_tomahawk_max_frequency_get(unit, dev_id, rev_id, -1,
   2166                                         &max_frequency));
   2167     if ((si->frequency != max_frequency)
   2168         || (si->frequency != freq_list[0])) {
   2169         if (si->frequency > max_frequency) {
   2170             si->frequency = max_frequency;
   2171         }
   2172         freq_list_len = COUNTOF(freq_list);
   2173         for (freq_sel = 1; freq_sel < freq_list_len; freq_sel++) { /* skip index 0 */
   2174             if (si->frequency == freq_list[freq_sel]) {
   2175                 break;
   2176             }
   2177         }
   2178         if (freq_sel < freq_list_len) {
   2179             LOG_CLI((BSL_META_U(unit,
   2180                                 "*** change core clock frequency to %dMHz\n"),
   2181                                 si->frequency));
   2182 
   2183             freq_sel = _soc_th_freq_val_sel(si->frequency);
   2184             fields[0] = CORE_CLK_0_FREQ_SELf;
   2185             values[0] = freq_sel;
   2186             fields[1] = SW_CORE_CLK_0_SEL_ENf;
   2187             values[1] = 1;
   2188             SOC_IF_ERROR_RETURN
   2189                 (soc_reg_fields32_modify(unit, TOP_CORE_CLK_FREQ_SELr,
   2190                                          REG_PORT_ANY, 2, fields, values));
   2191             sal_usleep(to_usec);
   2192         }
   2193     }
   2194     else {
   2195         /* Set correct frequency in non OTP'd SKUs */
   2196         SOC_IF_ERROR_RETURN(READ_TOP_DEV_REV_IDr(unit, &rval));
   2197         if (!(soc_reg_field_get(unit, TOP_DEV_REV_IDr, rval, DEVICE_SKEWf) & 0x8)) {
   2198             SOC_IF_ERROR_RETURN
   2199                 (soc_tomahawk_max_frequency_get(unit, dev_id, rev_id, -1,
   2200                                                 &max_frequency));
   2201             LOG_CLI((BSL_META_U(unit,
   2202                                 "*** change core clock frequency to %dMHz\n"),
   2203                                 max_frequency));
   2204             freq_sel = _soc_th_freq_val_sel(max_frequency);
   2205             fields[0] = CORE_CLK_0_FREQ_SELf;
   2206             values[0] = freq_sel;
   2207             fields[1] = SW_CORE_CLK_0_SEL_ENf;
   2208             values[1] = 1;
   2209             SOC_IF_ERROR_RETURN
   2210                 (soc_reg_fields32_modify(unit, TOP_CORE_CLK_FREQ_SELr,
   2211                                          REG_PORT_ANY, 2, fields, values));
   2212             sal_usleep(to_usec);
   2213         }
   2214     }
   2215 
   2216     /* Power on core pll1 */
   2217     SOC_IF_ERROR_RETURN
   2218         (soc_reg_field32_modify(unit, TOP_CORE_PLL1_CTRL_1r,
   2219                                 REG_PORT_ANY, PWRONf, 0));
   2220     /* Program LCPLL frequency */
   2221     for (index = 0; index < COUNTOF(lcpll_ctrl0_reg); index++) {
   2222         SOC_IF_ERROR_RETURN
   2223             (soc_reg_field32_modify(unit, lcpll_ctrl4_reg[index],
   2224                                     REG_PORT_ANY, POST_RST_SELf, 3));
   2225         SOC_IF_ERROR_RETURN
   2226             (soc_reg_field32_modify(unit, lcpll_ctrl0_reg[index],
   2227                                     REG_PORT_ANY, PDIVf, 1));
   2228         SOC_IF_ERROR_RETURN
   2229             (soc_reg_field32_modify(unit, lcpll_ctrl0_reg[index],
   2230                                     REG_PORT_ANY, NDIV_INTf, 20));
   2231     }
   2232 
   2233     /* Configure TS PLL */
   2234     ts_ref_freq = soc_property_get(unit, spn_PTP_TS_PLL_FREF, 0);  /* 0->internal reference */
   2235 
   2236     for (ts_idx = 0; ts_idx < sizeof(ts_pll)/sizeof(ts_pll[0]); ++ts_idx) {
   2237         if (ts_pll[ts_idx].ref_freq == ts_ref_freq) {
   2238             break;
   2239         }
   2240     }
   2241 
   2242     if (ts_idx == sizeof(ts_pll)/sizeof(ts_pll[0])) {
   2243         /* Valid configuration lookup failed. Use internal reference. */
   2244         ts_idx = 5;
   2245         ts_ref_freq = 0;
   2246     }
   2247 
   2248     SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_0r(unit, &rval));
   2249     soc_reg_field_set(unit, TOP_TS_PLL_CTRL_0r, &rval, POST_RESETB_SELECTf, 3);
   2250     SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_0r(unit, rval));
   2251 
   2252     SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_1r(unit, &rval));
   2253     soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, & rval, FREF_SELf, (ts_ref_freq != 0));
   2254     SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_1r(unit, rval));
   2255 
   2256     SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_2r(unit,&rval));
   2257     soc_reg_field_set(unit, TOP_TS_PLL_CTRL_2r, &rval, PDIVf,
   2258                       soc_property_get(unit, spn_PTP_TS_PLL_PDIV, ts_pll[ts_idx].pdiv));
   2259     soc_reg_field_set(unit, TOP_TS_PLL_CTRL_2r, &rval, CH0_MDIVf,
   2260                       soc_property_get(unit, spn_PTP_TS_PLL_MNDIV, ts_pll[ts_idx].mdiv));
   2261     SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_2r(unit, rval));
   2262 
   2263     SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_3r(unit,&rval));
   2264     soc_reg_field_set(unit, TOP_TS_PLL_CTRL_3r, &rval, NDIV_INTf,
   2265                       soc_property_get(unit, spn_PTP_TS_PLL_N, ts_pll[ts_idx].ndiv_int));
   2266     soc_reg_field_set(unit, TOP_TS_PLL_CTRL_3r, &rval, NDIV_FRACf, ts_pll[ts_idx].ndiv_frac);
   2267     SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_3r(unit, rval));
   2268 
   2269     SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_4r(unit,&rval));
   2270     soc_reg_field_set(unit, TOP_TS_PLL_CTRL_4r, &rval, KAf,
   2271                       soc_property_get(unit, spn_PTP_TS_KA, ts_pll[ts_idx].ka));
   2272     soc_reg_field_set(unit, TOP_TS_PLL_CTRL_4r, &rval, KIf,
   2273                       soc_property_get(unit, spn_PTP_TS_KI, ts_pll[ts_idx].ki));
   2274     soc_reg_field_set(unit, TOP_TS_PLL_CTRL_4r, &rval, KPf,
   2275                       soc_property_get(unit, spn_PTP_TS_KP, ts_pll[ts_idx].kp));
   2276     SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_4r(unit, rval));
   2277 
   2278     /* Set 250Mhz (implies 4ns resolution) default timesync clock to
   2279        calculate assymentric delays */
   2280     SOC_TIMESYNC_PLL_CLOCK_NS(unit) = (1/250 * 1000); /* clock period in nanoseconds */
   2281 
   2282 
   2283     /* Configure BroadSync PLLs. */
   2284     bs_ref_freq = soc_property_get(unit, spn_PTP_BS_FREF, 0);  /* 0->internal reference */
   2285 
   2286     for (bs_idx = 0; bs_idx < sizeof(bs_pll)/sizeof(bs_pll[0]); ++bs_idx) {
   2287         if (bs_pll[bs_idx].ref_freq == bs_ref_freq) {
   2288             break;
   2289         }
   2290     }
   2291 
   2292     if (bs_idx == sizeof(bs_pll)/sizeof(bs_pll[0])) {
   2293         /* Valid configuration lookup failed. Use internal reference. */
   2294         bs_idx = 5;
   2295         bs_ref_freq = 0;
   2296     }
   2297 
   2298     /* Configure BS PLL0 */
   2299     SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_0r(unit, &rval));
   2300     soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_0r, &rval, POST_RESETB_SELECTf, 3);
   2301     SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_0r(unit, rval));
   2302 
   2303     SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_1r(unit, &rval));
   2304     soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, & rval, FREF_SELf, (bs_ref_freq != 0));
   2305     SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_1r(unit, rval));
   2306 
   2307     SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_2r(unit, &rval));
   2308     soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_2r, &rval, PDIVf,
   2309                       soc_property_get(unit, spn_PTP_BS_PDIV, bs_pll[bs_idx].pdiv));
   2310     soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_2r, &rval, CH0_MDIVf,
   2311                       soc_property_get(unit, spn_PTP_BS_MNDIV, bs_pll[bs_idx].mdiv));
   2312     SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_2r(unit, rval));
   2313 
   2314     SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_3r(unit, &rval));
   2315     soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_3r, &rval, NDIV_INTf,
   2316                       soc_property_get(unit, spn_PTP_BS_NDIV_INT, bs_pll[bs_idx].ndiv_int));
   2317     soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_3r, &rval, NDIV_FRACf,
   2318                       soc_property_get(unit, spn_PTP_BS_NDIV_FRAC, bs_pll[bs_idx].ndiv_frac));
   2319     SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_3r(unit, rval));
   2320 
   2321     SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_4r(unit, &rval));
   2322     soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_4r, &rval, KAf,
   2323                       soc_property_get(unit, spn_PTP_BS_KA, bs_pll[bs_idx].ka));
   2324     soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_4r, &rval, KIf,
   2325                       soc_property_get(unit, spn_PTP_BS_KI, bs_pll[bs_idx].ki));
   2326     soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_4r, &rval, KPf,
   2327                       soc_property_get(unit, spn_PTP_BS_KP, bs_pll[bs_idx].kp));
   2328     SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_4r(unit, rval));
   2329 
   2330     /* Configure BS PLL1 */
   2331     SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_0r(unit, &rval));
   2332     soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_0r, &rval, POST_RESETB_SELECTf, 3);
   2333     SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_0r(unit, rval));
   2334 
   2335     SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_1r(unit, &rval));
   2336     soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, & rval, FREF_SELf, (bs_ref_freq != 0));
   2337     SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_1r(unit, rval));
   2338 
   2339     SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_2r(unit, &rval));
   2340     soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_2r, &rval, PDIVf,
   2341                       soc_property_get(unit, spn_PTP_BS_PDIV, bs_pll[bs_idx].pdiv));
   2342     soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_2r, &rval, CH0_MDIVf,
   2343                       soc_property_get(unit, spn_PTP_BS_MNDIV, bs_pll[bs_idx].mdiv));
   2344     SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_2r(unit, rval));
   2345 
   2346     SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_3r(unit, &rval));
   2347     soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_3r, &rval, NDIV_INTf,
   2348                       soc_property_get(unit, spn_PTP_BS_NDIV_INT, bs_pll[bs_idx].ndiv_int));
   2349     soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_3r, &rval, NDIV_FRACf,
   2350                       soc_property_get(unit, spn_PTP_BS_NDIV_FRAC, bs_pll[bs_idx].ndiv_frac));
   2351     SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_3r(unit, rval));
   2352 
   2353     SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_4r(unit, &rval));
   2354     soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_4r, &rval, KAf,
   2355                       soc_property_get(unit, spn_PTP_BS_KA, bs_pll[bs_idx].ka));
   2356     soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_4r, &rval, KIf,
   2357                       soc_property_get(unit, spn_PTP_BS_KI, bs_pll[bs_idx].ki));
   2358     soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_4r, &rval, KPf,
   2359                       soc_property_get(unit, spn_PTP_BS_KP, bs_pll[bs_idx].kp));
   2360     SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_4r(unit, rval));
   2361 
   2362     /* Bring LCPLL, time sync PLL, BroadSync PLL, AVS out of reset */
   2363     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   2364     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL0_RST_Lf,
   2365                       1);
   2366     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL1_RST_Lf,
   2367                       1);
   2368     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL2_RST_Lf,
   2369                       1);
   2370     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL3_RST_Lf,
   2371                       1);
   2372     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_TS_PLL_RST_Lf, 1);
   2373     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL0_RST_Lf,
   2374                       1);
   2375     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL1_RST_Lf,
   2376                       1);
   2377     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf, 1);
   2378     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   2379 
   2380     sal_usleep(to_usec);
   2381 
   2382     if (!SAL_BOOT_SIMULATION) {
   2383         /* Check LCPLL lock status */
   2384         for (index = 0; index < _SOC_TH_LCPLL_COUNT; index++) {
   2385             reg = lcpll_status_reg[index];
   2386             SOC_IF_ERROR_RETURN
   2387                 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2388             if (!soc_reg_field_get(unit, reg, rval, TOP_XGPLL_LOCKf)) {
   2389                 LOG_ERROR(BSL_LS_SOC_COMMON,
   2390                           (BSL_META_U(unit,
   2391                                       "LCPLL %d not locked on unit %d "
   2392                                       "status = 0x%08x\n"), index, unit, rval));
   2393             }
   2394         }
   2395         /* Check time sync lock status */
   2396         reg = TOP_TS_PLL_STATUSr;
   2397         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2398         if (!soc_reg_field_get(unit, reg, rval, PLL_LOCKf)) {
   2399             LOG_ERROR(BSL_LS_SOC_COMMON,
   2400                       (BSL_META_U(unit,
   2401                                   "TS_PLL not locked on unit %d "
   2402                                   "status = 0x%08x\n"), unit, rval));
   2403         }
   2404         /* Check BroadSync lock status */
   2405         reg = TOP_BS_PLL0_STATUSr;
   2406         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2407         if (!soc_reg_field_get(unit, reg, rval, PLL_LOCKf)) {
   2408             LOG_ERROR(BSL_LS_SOC_COMMON,
   2409                       (BSL_META_U(unit,
   2410                                   "BS_PLL0 not locked on unit %d "
   2411                                   "status = 0x%08x\n"), unit, rval));
   2412         }
   2413     }
   2414 
   2415     /* De-assert LCPLL's post reset */
   2416     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   2417     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2418                       TOP_XG_PLL0_POST_RST_Lf, 1);
   2419     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2420                       TOP_XG_PLL1_POST_RST_Lf, 1);
   2421     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2422                       TOP_XG_PLL2_POST_RST_Lf, 1);
   2423     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2424                       TOP_XG_PLL3_POST_RST_Lf, 1);
   2425     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2426                       TOP_TS_PLL_POST_RST_Lf, 1);
   2427     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2428                       TOP_BS_PLL0_POST_RST_Lf, 1);
   2429     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2430                       TOP_BS_PLL1_POST_RST_Lf, 1);
   2431     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   2432 
   2433     sal_usleep(to_usec);
   2434 
   2435     /* Set correct value for BG_ADJ */
   2436     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_0r(unit, &rval));
   2437     soc_reg_field_set(unit, TOP_PVTMON_CTRL_0r, &rval, BG_ADJf, 0);
   2438     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_0r(unit, rval));
   2439 
   2440     /* Enable high temperature interrupt monitoring.
   2441      * Default on: pvtmon6 (close to core_plls at center of die).
   2442      */
   2443     temp_mask = soc_property_get(unit, "temp_monitor_select", 1<<6);
   2444     /* The above is a 9 bit mask to indicate which temp sensor to hook up to
   2445      * the interrupt.
   2446      */
   2447     rval = 0;
   2448     for (index = 0; index <COUNTOF(temp_thr_reg); index++) {
   2449         uint32 trval;
   2450 
   2451         /* data = 410.04-(temp/0.48705) = (410040-(temp*1000))/487
   2452          * Note: Since this is a high temp value we can safely assume it to
   2453          * always be a +ive number. This is in degrees celcius.
   2454          */
   2455         temp_thr = soc_property_get(unit, temp_thr_prop[index], _SOC_TH_DEF_TEMP_MAX);
   2456         if (temp_thr > 410) {
   2457             LOG_ERROR(BSL_LS_SOC_COMMON,
   2458                       (BSL_META_U(unit,
   2459                                   "Unsupported temp value %d !! Max 410. Using %d.\n"),
   2460                        temp_thr, _SOC_TH_DEF_TEMP_MAX));
   2461             temp_thr = _SOC_TH_DEF_TEMP_MAX;
   2462         }
   2463         /* Convert temperature to config data */
   2464         temp_thr = (410040-(temp_thr*1000))/487;
   2465         SOC_IF_ERROR_RETURN
   2466             (soc_reg32_get(unit, temp_thr_reg[index], REG_PORT_ANY, 0, &trval));
   2467         soc_reg_field_set(unit, temp_thr_reg[index], &trval, MIN_THRESHOLDf,
   2468                           temp_thr);
   2469         SOC_IF_ERROR_RETURN
   2470             (soc_reg32_set(unit, temp_thr_reg[index], REG_PORT_ANY, 0, trval));
   2471         if (temp_mask & (1 << index)) {
   2472             rval |= (1 << ((index * 2) + 1)); /* 2 bits per pvtmon, using min */
   2473         }
   2474     }
   2475     _soc_th_temp_mon_mask[unit] = temp_mask;
   2476 
   2477     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_INTR_MASKr(unit, rval));
   2478     /* Enable temp mon interrupt */
   2479 #ifdef BCM_CMICM_SUPPORT
   2480     if (soc_feature(unit, soc_feature_cmicm)) {
   2481         (void)soc_cmicm_intr3_enable(unit, 0x4); /* PVTMON_INTR bit 2 */
   2482     }
   2483 #endif
   2484 
   2485     /* Bring port blocks out of reset */
   2486     rval = 0;
   2487     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_PM32_RST_Lf, 1);
   2488     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_TS_RST_Lf, 1);
   2489     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval));
   2490     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_3r(unit, 0xffffffff));
   2491     sal_usleep(to_usec);
   2492 
   2493     /* Bring IP, EP, and MMU blocks out of reset */
   2494     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REGr(unit, &rval));
   2495     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_IP_RST_Lf, 1);
   2496     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_EP_RST_Lf, 1);
   2497     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_MMU_RST_Lf, 1);
   2498     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval));
   2499     sal_usleep(to_usec);
   2500 
   2501     if (!SAL_BOOT_PLISIM) {
   2502         COMPILER_64_ZERO(rval64);
   2503 
   2504         for (port = 0; port < _SOC_TH_NUM_PORTS; port++) {
   2505             for (acc = 0; acc < _TH_PIPES_PER_DEV; acc++) {
   2506                 SOC_IF_ERROR_RETURN(
   2507                     _soc_reg64_set(unit, _SOC_TH_LINK_DELAY_REG_BLK, acc,
   2508                                    (_SOC_TH_LINK_DELAY_REG_BASE + port),
   2509                                    rval64));
   2510             }
   2511         }
   2512     }
   2513 
   2514     /* Must do this before setting low-latency mode */
   2515     SOC_IF_ERROR_RETURN(_soc_tomahawk_clear_all_memory(unit, 0));
   2516 
   2517     /* Configure Switch Latency Bypass Mode */
   2518     SOC_IF_ERROR_RETURN(soc_th_latency_init(unit));
   2519 
   2520     SOC_IF_ERROR_RETURN
   2521         (soc_tomahawk_hash_bank_count_get(unit, L2Xm, &num_banks));
   2522     num_shared_l2_banks = num_banks - 2; /* minus 2 dedicated L2 banks */
   2523     SOC_IF_ERROR_RETURN
   2524         (soc_tomahawk_hash_bank_count_get(unit, L3_ENTRY_ONLYm, &num_banks));
   2525     num_shared_l3_banks = num_banks - 4; /* minus 4 dedicated L3 banks */
   2526     SOC_IF_ERROR_RETURN
   2527         (soc_tomahawk_hash_bank_count_get(unit, EXACT_MATCH_2m,
   2528                                           &num_shared_fpem_banks));
   2529 
   2530     if (soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) {
   2531         int non_alpm = num_shared_fpem_banks + num_shared_l3_banks +
   2532             num_shared_l2_banks;
   2533         if ((non_alpm) && (non_alpm <= 2)) {
   2534             /* If Shared banks are used between ALPM and non-ALPM memories,
   2535              * then ALPM uses Shared Bank B2, B3 and non-ALPM uses B4, B5 banks
   2536              */
   2537             soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   2538                               ALPM_ENTRY_BANK_CONFIGf, 0x3);
   2539             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   2540                               ALPM_BANK_MODEf, 1);
   2541             SOC_IF_ERROR_RETURN
   2542                 (soc_reg_field32_modify(unit, ISS_LOG_TO_PHY_BANK_MAP_2r,
   2543                                         REG_PORT_ANY, ALPM_BANK_MODEf, 1));
   2544             SOC_IF_ERROR_RETURN
   2545                 (soc_reg_field32_modify(unit, ISS_MEMORY_CONTROL_84r,
   2546                                         REG_PORT_ANY, BYPASS_ISS_MEMORY_LPf, 0x3));
   2547             soc_th_set_alpm_banks(unit, 2);
   2548             shared_bank_offset = 2;
   2549         } else {
   2550             soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   2551                               ALPM_ENTRY_BANK_CONFIGf, 0xf);
   2552             soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   2553                               ALPM_BANK_MODEf, 0);
   2554             SOC_IF_ERROR_RETURN
   2555                 (soc_reg_field32_modify(unit, ISS_LOG_TO_PHY_BANK_MAP_2r,
   2556                                         REG_PORT_ANY, ALPM_BANK_MODEf, 0));
   2557             SOC_IF_ERROR_RETURN
   2558                 (soc_reg_field32_modify(unit, ISS_MEMORY_CONTROL_84r,
   2559                                         REG_PORT_ANY, BYPASS_ISS_MEMORY_LPf, 0xf));
   2560             soc_th_set_alpm_banks(unit, 4);
   2561         }
   2562     }
   2563 
   2564     soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config, L2_ENTRY_BANK_CONFIGf,
   2565                       ((1 << num_shared_l2_banks) - 1) << shared_bank_offset);
   2566     for (index = 0; index < num_shared_l2_banks; index++) {
   2567         shared_bank = index + shared_bank_offset;
   2568         soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   2569                           l2_fields[index], shared_bank);
   2570     }
   2571     shared_bank_offset += num_shared_l2_banks;
   2572 
   2573     soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config, L3_ENTRY_BANK_CONFIGf,
   2574                       ((1 << num_shared_l3_banks) - 1) << shared_bank_offset);
   2575     for (index = 0; index < num_shared_l3_banks; index++) {
   2576         shared_bank = index + shared_bank_offset;;
   2577         soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   2578                           l3_fields[index], shared_bank);
   2579     }
   2580     shared_bank_offset += num_shared_l3_banks;
   2581 
   2582     soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config,
   2583                       FPEM_ENTRY_BANK_CONFIGf,
   2584                       ((1 << num_shared_fpem_banks) - 1) << shared_bank_offset);
   2585     for (index = 0; index < num_shared_fpem_banks; index++) {
   2586         shared_bank = index + shared_bank_offset;
   2587         soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map,
   2588                           fpem_fields[index], shared_bank);
   2589         soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAP_3r, &fpmap,
   2590                           fpem_fields[index], shared_bank);
   2591     }
   2592 
   2593     SOC_IF_ERROR_RETURN
   2594         (soc_reg32_set(unit, ISS_BANK_CONFIGr, REG_PORT_ANY, 0, config));
   2595     SOC_IF_ERROR_RETURN
   2596         (soc_reg32_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, REG_PORT_ANY, 0, map));
   2597     SOC_IF_ERROR_RETURN
   2598         (soc_th_iss_log_to_phy_bank_map_shadow_set(unit, map));
   2599     SOC_IF_ERROR_RETURN
   2600         (soc_reg32_set(unit, ISS_LOG_TO_PHY_BANK_MAP_3r, REG_PORT_ANY, 0, fpmap));
   2601 
   2602     /* Bypass unused Port Blocks */
   2603     if (soc_property_get(unit, "disable_unused_port_blocks", TRUE)) {
   2604         SOC_IF_ERROR_RETURN(soc_th_bypass_unused_pm(unit));
   2605     }
   2606 
   2607     if (!(SOC_CONTROL(unit)->soc_flags & SOC_F_ALL_MODULES_INITED) &&
   2608         soc_feature(unit, soc_feature_turbo_boot)) {
   2609         SOC_HW_RESET_START(unit);
   2610     }
   2611 
   2612 #ifdef BCM_IPROC_SUPPORT
   2613     /* Reset all mHost processors */
   2614     SOC_IF_ERROR_RETURN(WRITE_MHOST_0_CR5_RST_CTRLr(unit, 0));
   2615     SOC_IF_ERROR_RETURN(WRITE_MHOST_1_CR5_RST_CTRLr(unit, 0));
   2616     /*Reset the common UARTs */
   2617     SOC_IF_ERROR_RETURN(WRITE_CHIPCOMMONG_UART0_UART_SRRr(unit, 1));
   2618     SOC_IF_ERROR_RETURN(WRITE_CHIPCOMMONG_UART1_UART_SRRr(unit, 1));
   2619 #endif
   2620 
   2621     return SOC_E_NONE;
   2622 }
   2623 
   2624 #ifdef BCM_WARM_BOOT_SUPPORT
   2625 /*
   2626  * Function:
   2627  *      soc_tomahawk_chip_warmboot_reset
   2628  * Purpose:
   2629  *      Special re-init sequencing for BCM56960 during warmboot
   2630  */
   2631 int
   2632 soc_tomahawk_chip_warmboot_reset(int unit)
   2633 {
   2634     uint32 map = 0;
   2635 
   2636     SOC_IF_ERROR_RETURN
   2637         (soc_reg32_get(unit, ISS_LOG_TO_PHY_BANK_MAPr, REG_PORT_ANY, 0, &map));
   2638     SOC_IF_ERROR_RETURN
   2639         (soc_th_iss_log_to_phy_bank_map_shadow_set(unit, map));
   2640 
   2641     return SOC_E_NONE;
   2642 }
   2643 #endif
   2644 
   2645 int
   2646 soc_tomahawk_port_reset(int unit)
   2647 {
   2648     uint32 rval;
   2649     int blk, port;
   2650     int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100;
   2651 
   2652 #ifdef BCM_TOMAHAWK2_SUPPORT
   2653     if (soc_feature(unit, soc_feature_pm_refclk_master)) {
   2654         soc_info_t *si = &SOC_INFO(unit);
   2655         if (!SHR_BITNULL_RANGE(si->pm_ref_master_bitmap, 0,
   2656                                  SOC_MAX_NUM_BLKS)) {
   2657             soc_xgxs_reset_master_tsc(unit);
   2658         }
   2659     }
   2660 #endif
   2661 
   2662     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
   2663         port = SOC_BLOCK_PORT(unit, blk);
   2664 
   2665         SOC_IF_ERROR_RETURN(READ_CLPORT_MAC_CONTROLr(unit, port, &rval));
   2666         soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1);
   2667         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, port, rval));
   2668         sal_udelay(10);
   2669         soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0);
   2670         /* PM interface is 16B in TH2 */
   2671         if (soc_feature(unit, soc_feature_clmac_16byte_interface_mode)) {
   2672             soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval,
   2673                                 SYS_16B_INTF_MODEf, 1);
   2674         }
   2675         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, port, rval));
   2676     }
   2677 
   2678     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   2679         port = SOC_BLOCK_PORT(unit, blk);
   2680 
   2681         SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_CONTROLr(unit, port, &rval));
   2682         soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1);
   2683         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval));
   2684         sal_udelay(10);
   2685         soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0);
   2686         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval));
   2687     }
   2688 
   2689     /* Power off CLPORT blocks */
   2690     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
   2691         port = SOC_BLOCK_PORT(unit, blk);
   2692         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 1));
   2693     }
   2694     sal_usleep(sleep_usec + 10000);
   2695     /* Power on CLPORT blocks */
   2696     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
   2697         port = SOC_BLOCK_PORT(unit, blk);
   2698         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 0));
   2699     }
   2700 
   2701     /* Power off XLPORT blocks */
   2702     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   2703         port = SOC_BLOCK_PORT(unit, blk);
   2704         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 1));
   2705     }
   2706     sal_usleep(sleep_usec + 10000);
   2707     /* Power off XLPORT blocks */
   2708     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   2709         port = SOC_BLOCK_PORT(unit, blk);
   2710         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 0));
   2711     }
   2712 
   2713     return SOC_E_NONE;
   2714 }
   2715 
   2716 int
   2717 soc_tomahawkplus_port_reset(int unit)
   2718 {
   2719     uint32 rval;
   2720     int blk, port;
   2721     int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100;
   2722 
   2723     /* Power off CLPORT blocks */
   2724     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
   2725         port = SOC_BLOCK_PORT(unit, blk);
   2726         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 1));
   2727     }
   2728     sal_usleep(sleep_usec + 10000);
   2729     /* Power on CLPORT blocks */
   2730     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
   2731         port = SOC_BLOCK_PORT(unit, blk);
   2732         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 0));
   2733     }
   2734 
   2735     /* Power off XLPORT blocks */
   2736     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   2737         port = SOC_BLOCK_PORT(unit, blk);
   2738         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 1));
   2739     }
   2740     sal_usleep(sleep_usec + 10000);
   2741     /* Power off XLPORT blocks */
   2742     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   2743         port = SOC_BLOCK_PORT(unit, blk);
   2744         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 0));
   2745     }
   2746 
   2747     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
   2748         port = SOC_BLOCK_PORT(unit, blk);
   2749 
   2750         SOC_IF_ERROR_RETURN(READ_CLPORT_MAC_CONTROLr(unit, port, &rval));
   2751         soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1);
   2752         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, port, rval));
   2753         sal_udelay(10);
   2754         soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0);
   2755         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, port, rval));
   2756     }
   2757 
   2758     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   2759         port = SOC_BLOCK_PORT(unit, blk);
   2760 
   2761         SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_CONTROLr(unit, port, &rval));
   2762         soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1);
   2763         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval));
   2764         sal_udelay(10);
   2765         soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0);
   2766         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval));
   2767     }
   2768     return SOC_E_NONE;
   2769 }
   2770 
   2771 
   2772 /* Configure HSP port multicast T2OQ setting.
   2773  * Note: Caller must check if the Port is part of HSP port bitmap
   2774  *       HSP Port check:  SOC_PBMP_MEMBER(si->eq_pbm, port)
   2775  */
   2776 
   2777 STATIC int
   2778 _soc_tomahawk_mc_toq_cfg(int unit, int port, int enable)
   2779 {
   2780     static soc_field_t t2oq_fields[] = {
   2781         IS_MC_T2OQ_PORT0f, IS_MC_T2OQ_PORT1f
   2782     };
   2783     soc_field_t field;
   2784     uint32 rval, fval;
   2785     int inst, pipe, mmu_port;
   2786     soc_reg_t reg = MMU_SCFG_TOQ_MC_CFG1r;
   2787     soc_info_t *si = &SOC_INFO(unit);;
   2788 
   2789     pipe = si->port_pipe[port];
   2790     field = t2oq_fields[pipe & 0x01];
   2791     inst = (pipe >> 1) | SOC_REG_ADDR_INSTANCE_MASK;
   2792     mmu_port = si->port_p2m_mapping[si->port_l2p_mapping[port]];
   2793 
   2794     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval));
   2795     fval = soc_reg_field_get(unit, reg, rval, field);
   2796     if (enable) {
   2797         fval |= 1 << (mmu_port & 0x0f);
   2798     } else {
   2799         fval &= ~(1 << (mmu_port & 0x0f));
   2800     }
   2801     soc_reg_field_set(unit, reg, &rval, field, fval);
   2802     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   2803 
   2804     return SOC_E_NONE;
   2805 }
   2806 
   2807 /*
   2808  * Utility function to update multicast initial copy count
   2809  * Invoked during speed set and flexport operations.
   2810  */
   2811 STATIC soc_error_t
   2812 soc_tomahawk_update_icc(int unit, soc_port_t port, int port_speed)
   2813 {
   2814     soc_info_t *si = &SOC_INFO(unit);
   2815     int phy_port, count_width;
   2816     uint32 regval = 0;
   2817 
   2818     phy_port = si->port_l2p_mapping[port];
   2819     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
   2820         phy_port == 129 || phy_port == 131) {
   2821         /* For CPU, loopback, and management ports,
   2822          * the copy count width is fixed at 3 bits (encoded value of 1).
   2823          * Pysical ports 129 and 131 are management ports.
   2824          */
   2825         count_width = 1;
   2826     } else {
   2827         /* For ports with speed 40G and above the copy count width
   2828          * is 3 bits (encoded value of 1) for lower speeds its
   2829          * 2 bits (encoded value of 0).
   2830          */
   2831         count_width = (port_speed >= 40000) ? 1 : 0;
   2832     }
   2833     soc_reg_field_set(unit, PORT_INITIAL_COPY_COUNT_WIDTHr, &regval,
   2834                       BIT_WIDTHf, count_width);
   2835     SOC_IF_ERROR_RETURN(WRITE_PORT_INITIAL_COPY_COUNT_WIDTHr
   2836                            (unit, port, regval));
   2837 
   2838     return SOC_E_NONE;
   2839 }
   2840 
   2841 /*
   2842  * Function to update Port PG's Headroom allocation.
   2843  * Port PG needs to be updated during
   2844  *  1. Flex (bcmPortControlLanes) operation
   2845  *  2. Port Speed update (bcm_port_speed_set api)
   2846  * Note: This function will update the Port's PG Headroom to the
   2847  * updated port speed (soc_info.port_init_speed).
   2848  */
   2849 STATIC
   2850 int soc_tomahawk_port_pg_headroom_update(int unit, soc_port_t port)
   2851 {
   2852 #define DEFAULT_PG_NUM 7  /* Default Priority Group Num */
   2853     int headroom, lossless, pipe, midx;
   2854     soc_mem_t mem;
   2855     thdi_port_pg_config_entry_t pg_config_mem_entry;
   2856 
   2857     lossless = SOC_INFO(unit).mmu_lossless;
   2858     headroom = _soc_th_default_pg_headroom(unit, port, lossless);
   2859     pipe = SOC_INFO(unit).port_pipe[port];
   2860     mem = SOC_MEM_UNIQUE_ACC(unit, THDI_PORT_PG_CONFIGm)[pipe];
   2861     midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, THDI_PORT_PG_CONFIGm,
   2862                                       DEFAULT_PG_NUM);
   2863     SOC_IF_ERROR_RETURN
   2864         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, midx, &pg_config_mem_entry));
   2865     soc_mem_field32_set(unit, mem, &pg_config_mem_entry,
   2866                         PG_HDRM_LIMITf, headroom);
   2867     SOC_IF_ERROR_RETURN
   2868         (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, &pg_config_mem_entry));
   2869     return SOC_E_NONE;
   2870 }
   2871 
   2872 STATIC int
   2873 _soc_tomahawk_port_mixed_speed_check(int unit, soc_th_port_lanes_t *lanes_ctrl)
   2874 {
   2875     soc_info_t *si = &SOC_INFO(unit);
   2876     soc_port_t phy_port_base, phy_port;
   2877     soc_port_t port_sub, port_sis;
   2878     int port_sub_speed, port_sis_speed;
   2879     soc_port_t port_base = lanes_ctrl->port_base;
   2880 
   2881     phy_port = si->port_l2p_mapping[port_base];
   2882     if (-1 == phy_port) {
   2883         return SOC_E_PORT;
   2884     }
   2885     phy_port_base = PORT_BLOCK_BASE_PORT(port_base);
   2886     if ((phy_port_base != phy_port) && ((phy_port_base + 2) != phy_port)) {
   2887         /* Not a controlling port, skip the checking */
   2888         return SOC_E_NONE;
   2889     }
   2890 
   2891     /* check mixed sister port mode */
   2892     port_sub = si->port_p2l_mapping[phy_port_base];
   2893     port_sis = si->port_p2l_mapping[phy_port_base + 2];
   2894     if (phy_port_base == phy_port) {
   2895         port_sub_speed = lanes_ctrl->speed;
   2896     } else {
   2897         port_sub_speed = si->port_init_speed[port_sub];
   2898     }
   2899     if ((phy_port_base + 2) == phy_port) {
   2900         port_sis_speed = lanes_ctrl->speed;
   2901     } else {
   2902         port_sis_speed = si->port_init_speed[port_sis];
   2903     }
   2904 
   2905     if (!SOC_PBMP_MEMBER(si->all.disabled_bitmap, si->port_p2l_mapping[phy_port_base + 1]) ||
   2906         !SOC_PBMP_MEMBER(si->all.disabled_bitmap, si->port_p2l_mapping[phy_port_base + 3])) {
   2907         return SOC_E_PORT;
   2908     }
   2909 
   2910     if (((port_sub_speed == 50000) && (port_sis_speed == 50000)) ||
   2911         ((port_sub_speed == 53000) && (port_sis_speed == 53000))) {
   2912         lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_50_0_50_0;
   2913     } else if (((port_sub_speed == 50000) && (port_sis_speed == 25000)) ||
   2914                ((port_sub_speed == 53000) && (port_sis_speed == 27000))) {
   2915                lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_50_0_25_0;
   2916     } else if (((port_sub_speed == 25000) && (port_sis_speed == 50000)) ||
   2917                ((port_sub_speed == 27000) && (port_sis_speed == 53000))) {
   2918                lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_25_0_50_0;
   2919     } else if (((port_sub_speed == 25000) && (port_sis_speed == 25000)) ||
   2920                ((port_sub_speed == 27000) && (port_sis_speed == 27000))) {
   2921                lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_25_0_25_0;
   2922     } else if (((port_sub_speed == 40000) && (port_sis_speed == 40000)) ||
   2923                ((port_sub_speed == 43000) && (port_sis_speed == 43000))) {
   2924                lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_40_0_40_0;
   2925     } else if (((port_sub_speed == 20000) && (port_sis_speed == 20000)) ||
   2926                ((port_sub_speed == 21000) && (port_sis_speed == 21000))) {
   2927                lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_20_0_20_0;
   2928     } else {
   2929         lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_0;
   2930     }
   2931     if (lanes_ctrl->mixed_port_mode == MIXED_DUAL_MODE_0) {
   2932         return SOC_E_PORT;
   2933     }
   2934 
   2935     return SOC_E_NONE;
   2936 }
   2937 
   2938 int
   2939 soc_tomahawk_port_speed_update(int unit, soc_port_t port, int speed)
   2940 {
   2941     uint32 rval, fval;
   2942     uint32 entry[SOC_MAX_MEM_WORDS];
   2943     soc_info_t *si = &SOC_INFO(unit);
   2944     soc_port_t it_port;
   2945     int port_rename = 0;
   2946     int rv;
   2947     soc_th_port_lanes_t lanes_ctrl;
   2948 
   2949     sal_memset(&lanes_ctrl, 0, sizeof(lanes_ctrl));
   2950     lanes_ctrl.port_base = port;
   2951     lanes_ctrl.lanes = TH_FLEXPORT_SPEED_SET_NUM_LANES;
   2952     lanes_ctrl.cur_lanes = TH_FLEXPORT_SPEED_SET_NUM_LANES;
   2953     lanes_ctrl.speed = speed;
   2954     lanes_ctrl.os_mixed_sister = si->os_mixed_sister_25_50_enable;
   2955 
   2956     SOC_IF_ERROR_RETURN(READ_CLPORT_MODE_REGr(unit, port, &rval));
   2957     lanes_ctrl.cur_mode = soc_reg_field_get(unit, CLPORT_MODE_REGr, rval,
   2958             XPORT0_CORE_PORT_MODEf);
   2959 
   2960     /* Validate the port config under Mixed Speed */
   2961     if ((lanes_ctrl.os_mixed_sister) &&
   2962         (lanes_ctrl.cur_mode == SOC_TH_PORT_MODE_DUAL)) {
   2963         if (!SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
   2964             SOC_IF_ERROR_RETURN(_soc_tomahawk_port_mixed_speed_check(unit, &lanes_ctrl));
   2965         }
   2966     }
   2967 
   2968     /*
   2969      * Update bitmaps and port names of Management Port
   2970      * when shift b/w XE <=> GE <=> FE
   2971     */
   2972     if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
   2973         if (IS_XE_PORT(unit, port) && (speed < 10000) && (speed > 100)) {
   2974             SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port);
   2975             SOC_PBMP_PORT_ADD(si->ge.bitmap, port);
   2976             port_rename = 1;
   2977         } else if (IS_XE_PORT(unit, port) && (speed <= 100)) {
   2978             SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port);
   2979             SOC_PBMP_PORT_ADD(si->fe.bitmap, port);
   2980             port_rename = 1;
   2981         } else if (IS_GE_PORT(unit, port) && (speed == 10000)) {
   2982             SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port);
   2983             SOC_PBMP_PORT_ADD(si->xe.bitmap, port);
   2984             port_rename = 1;
   2985         } else if (IS_GE_PORT(unit, port) && (speed <= 100)) {
   2986             SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port);
   2987             SOC_PBMP_PORT_ADD(si->fe.bitmap, port);
   2988             port_rename = 1;
   2989         } else if (IS_FE_PORT(unit, port) && (speed == 10000)) {
   2990             SOC_PBMP_PORT_REMOVE(si->fe.bitmap, port);
   2991             SOC_PBMP_PORT_ADD(si->xe.bitmap, port);
   2992             port_rename = 1;
   2993         } else if (IS_FE_PORT(unit, port) && (speed < 10000) && (speed > 100)) {
   2994             SOC_PBMP_PORT_REMOVE(si->fe.bitmap, port);
   2995             SOC_PBMP_PORT_ADD(si->ge.bitmap, port);
   2996             port_rename = 1;
   2997         }
   2998     }
   2999     if (port_rename) {
   3000         _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(xe);
   3001         _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ge);
   3002         _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(fe);
   3003         soc_dport_map_update(unit);
   3004     }
   3005 
   3006     /*
   3007      * No reconfiguration is needed if new speed
   3008      * matches current speed
   3009      */
   3010     if (speed == si->port_init_speed[port]) {
   3011         return SOC_E_NONE;
   3012     }
   3013 
   3014     /* Update HSP port multicast T2OQ setting */
   3015     if (SOC_PBMP_MEMBER(si->eq_pbm, port) && (!SOC_IS_TOMAHAWK2(unit))) {
   3016         SOC_IF_ERROR_RETURN
   3017             (_soc_tomahawk_mc_toq_cfg(unit, port,
   3018                                       (speed >= 40000) ? TRUE : FALSE));
   3019     }
   3020 
   3021     rv = soc_th_port_asf_mode_set(unit, port, speed,
   3022                                   _SOC_TH_ASF_MODE_CFG_UPDATE);
   3023     if ((SOC_E_NONE != rv) && (SOC_E_UNAVAIL != rv) && (SOC_E_PARAM != rv)) {
   3024         return rv;
   3025     }
   3026 
   3027     /* OS related updates */
   3028     if (SOC_PBMP_NOT_NULL(SOC_INFO(unit).oversub_pbm)) {
   3029         int factor = SOC_IS_TOMAHAWK2(unit) ? 178125 : 118750;
   3030         sal_memset(entry, 0, sizeof(egr_xmit_start_count_entry_t));
   3031         fval = ((speed / 10) * factor) / 100000;
   3032         soc_mem_field32_set(unit, EDB_1DBG_Bm, &entry, FIELD_Bf, fval);
   3033         SOC_IF_ERROR_RETURN
   3034             (soc_mem_write(unit, EDB_1DBG_Bm, MEM_BLOCK_ALL,
   3035                            SOC_INFO(unit).port_l2p_mapping[port], entry));
   3036 
   3037         rval = 0;
   3038         if (speed >= 100000) {
   3039             fval = 140;
   3040         } else if (speed >= 40000) {
   3041             fval = 60;
   3042         } else if (speed >= 25000) {
   3043             fval = 40;
   3044         } else if (speed >= 20000) {
   3045             fval = 30;
   3046         } else {
   3047             fval = 15;
   3048         }
   3049         soc_reg_field_set(unit, MMU_3DBG_Cr, &rval, FIELD_Af,
   3050                           fval + sal_rand() % 20);
   3051         SOC_IF_ERROR_RETURN
   3052             (soc_tomahawk_sc_reg32_set(unit, MMU_3DBG_Cr, -1, port, 0, rval));
   3053     }
   3054 
   3055     if (!SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
   3056         SOC_IF_ERROR_RETURN(soc_th_speed_set_init_ctrl(unit, &lanes_ctrl));
   3057         SOC_IF_ERROR_RETURN
   3058             (soc_tomahawk_port_lanes_set(unit, &lanes_ctrl));
   3059     }
   3060 
   3061     return SOC_E_NONE;
   3062 }
   3063 
   3064 /*
   3065  * Utility routine called when converting an HiGig2 encapped port
   3066  * to IEEE encap. This routine returns the IEEE speed corresponding
   3067  * to the current HG speed of the port
   3068  */
   3069 int
   3070 soc_th_port_ie_speed_get(int unit, soc_port_t port, int *speed)
   3071 {
   3072     soc_info_t *si;
   3073     si = &SOC_INFO(unit);
   3074 
   3075     switch (si->port_init_speed[port]) {
   3076         case 11000:
   3077             *speed = 10000;
   3078             break;
   3079         case 21000:
   3080             *speed = 20000;
   3081             break;
   3082         case 27000:
   3083             *speed = 25000;
   3084             break;
   3085         case 42000:
   3086             *speed = 40000;
   3087             break;
   3088         case 53000:
   3089             *speed = 50000;
   3090             break;
   3091         case 106000:
   3092             *speed = 100000;
   3093             break;
   3094         default:
   3095             /* port_init_speed is already IEEE speed */
   3096             *speed = si->port_init_speed[port];
   3097             break;
   3098     }
   3099 
   3100     return SOC_E_NONE;
   3101 }
   3102 
   3103 /*
   3104  * Utility routine called when converting an IEEE encapped port
   3105  * to HiGig2 encap. This routine returns the HG speed corresponding
   3106  * to the current ethernet speed of the port
   3107  */
   3108 int
   3109 soc_th_port_hg_speed_get(int unit, soc_port_t port, int *speed)
   3110 {
   3111     soc_info_t *si;
   3112     si = &SOC_INFO(unit);
   3113 
   3114     switch (si->port_init_speed[port]) {
   3115         case 10000:
   3116             *speed = 11000;
   3117             break;
   3118         case 20000:
   3119             *speed = 21000;
   3120             break;
   3121         case 25000:
   3122             *speed = 27000;
   3123             break;
   3124         case 40000:
   3125             *speed = 42000;
   3126             break;
   3127         case 50000:
   3128             *speed = 53000;
   3129             break;
   3130         case 100000:
   3131             *speed = 106000;
   3132             break;
   3133         default:
   3134             /* port_init_speed is already HG speed */
   3135             *speed = si->port_init_speed[port];
   3136             break;
   3137     }
   3138 
   3139     return SOC_E_NONE;
   3140 }
   3141 
   3142 int
   3143 soc_tomahawk_xpe_base_index_check(int unit, int base_type, int xpe,
   3144                                   int base_index, char *msg)
   3145 {
   3146     soc_info_t *si;
   3147     int pipe;
   3148     uint32 map;
   3149     char *base_name;
   3150 
   3151     si = &SOC_INFO(unit);
   3152 
   3153     if (xpe == -1 || base_index == -1) {
   3154         return SOC_E_NONE;
   3155     }
   3156 
   3157     if (xpe < NUM_XPE(unit) && si->xpe_ipipe_map[xpe] == 0) {
   3158         if (msg) {
   3159             LOG_CLI((BSL_META_U(unit,
   3160                                 "%s: XPE%d is not in config\n"),
   3161                      msg, xpe));
   3162         }
   3163         return SOC_E_PARAM;
   3164     }
   3165 
   3166     switch (base_type) {
   3167     case 0: /* IPORT */
   3168     case 1: /* EPORT */
   3169         base_name = base_type == 0 ? "IPORT" : "EPORT";
   3170         pipe = si->port_pipe[base_index];
   3171         if (pipe == -1) {
   3172             if (msg) {
   3173                 LOG_CLI((BSL_META_U(unit,
   3174                                     "%s: %s%d is not in config\n"),
   3175                          msg, base_name, base_index));
   3176             }
   3177         } else if (xpe < NUM_XPE(unit)) { /* Unique access type */
   3178             map = base_type == 0 ?
   3179                 si->ipipe_xpe_map[pipe] : si->epipe_xpe_map[pipe];
   3180             if (map & (1 << xpe)) {
   3181                 break;
   3182             }
   3183             if (msg != NULL) {
   3184                 LOG_CLI((BSL_META_U(unit,
   3185                                     "%s: %s%d is not in XPE%d\n"),
   3186                          msg, base_name, base_index, xpe));
   3187             }
   3188         } else {
   3189             break;
   3190         }
   3191         return SOC_E_PARAM;
   3192     case 2: /* IPIPE */
   3193     case 3: /* EPIPE */
   3194         if (base_type == 2) {
   3195             base_name = "IPIPE";
   3196             map = si->ipipe_xpe_map[base_index];
   3197         } else {
   3198             base_name = "EPIPE";
   3199             map = si->epipe_xpe_map[base_index];
   3200         }
   3201         if (map == 0) {
   3202             if (msg) {
   3203                 LOG_CLI((BSL_META_U(unit,
   3204                                     "%s: %s%d is not in config\n"),
   3205                          msg, base_name, base_index));
   3206             }
   3207         } else if (xpe < NUM_XPE(unit)) { /* Unique access type */
   3208             if (map & (1 << xpe)) {
   3209                 break;
   3210             }
   3211             if (msg != NULL) {
   3212                 LOG_CLI((BSL_META_U(unit,
   3213                                     "%s: %s%d is not in XPE%d\n"),
   3214                          msg, base_name, base_index, xpe));
   3215             }
   3216         } else {
   3217             break;
   3218         }
   3219         return SOC_E_PARAM;
   3220     case 4: /* CHIP */
   3221         break;
   3222     case 5: /* XPE */
   3223         if (si->xpe_ipipe_map[base_index] != 0) {
   3224             break;
   3225         }
   3226         if (msg != NULL) {
   3227             LOG_CLI((BSL_META_U(unit,
   3228                                 "%s: XPE%d is not in config\n"),
   3229                      msg, base_index));
   3230         }
   3231         return SOC_E_PARAM;
   3232     case 6: /* SLICE */
   3233         if (si->sc_ipipe_map[base_index] == 0) {
   3234             if (msg != NULL) {
   3235                 LOG_CLI((BSL_META_U(unit,
   3236                                     "%s: SLICE%d is not in config\n"),
   3237                          msg, base_index));
   3238             }
   3239         } else if (xpe < NUM_XPE(unit)) { /* Unique access type */
   3240             if (xpe & 1) { /* XPE 1 and 3 are in slice 1 */
   3241                 if (base_index == 1) {
   3242                     break;
   3243                 }
   3244             } else { /* XPE 0 and 2 are in slice 0 */
   3245                 if (base_index == 0) {
   3246                     break;
   3247                 }
   3248             }
   3249             if (msg != NULL) {
   3250                 LOG_CLI((BSL_META_U(unit,
   3251                                     "%s: XPE%d is not in SLICE%d\n"),
   3252                          msg, xpe, base_index));
   3253             }
   3254         } else {
   3255             break;
   3256         }
   3257         return SOC_E_PARAM;
   3258     case 7: /* LAYER */
   3259         if (xpe & 2) { /* XPE 2 and 3 are in layer 1 */
   3260             if (base_index == 1) {
   3261                 break;
   3262             }
   3263         } else { /* XPE 0 and 1 are in layer 0 */
   3264             if (base_index == 0) {
   3265                 break;
   3266             }
   3267         }
   3268         if (msg) {
   3269             LOG_CLI((BSL_META_U(unit,
   3270                                 "%s: XPE%d is not in LAYER%d\n"),
   3271                      msg, xpe, base_index));
   3272         }
   3273         return SOC_E_PARAM;
   3274     }
   3275 
   3276     return SOC_E_NONE;
   3277 }
   3278 
   3279 void soc_th_set_alpm_banks(int unit, int alpm_banks)
   3280 {
   3281     num_shared_alpm_banks[unit] = alpm_banks;
   3282     return;
   3283 }
   3284 
   3285 int soc_th_get_alpm_banks(int unit)
   3286 {
   3287     int rv = SOC_E_NONE;
   3288     uint32 bank_config = 0xf;
   3289     uint32 config = 0;
   3290 
   3291     if (num_shared_alpm_banks[unit] == 0) {
   3292         rv = soc_reg32_get(unit, ISS_BANK_CONFIGr, REG_PORT_ANY, 0, &config);
   3293         if (SOC_FAILURE(rv)) {
   3294             num_shared_alpm_banks[unit] = 4;
   3295         } else {
   3296             bank_config = soc_reg_field_get(unit, ISS_BANK_CONFIGr, config,
   3297                                             ALPM_ENTRY_BANK_CONFIGf);
   3298             if (bank_config == 0x3) {
   3299                 num_shared_alpm_banks[unit] = 2;
   3300             } else {
   3301                 num_shared_alpm_banks[unit] = 4;
   3302             }
   3303         }
   3304     }
   3305 
   3306     return num_shared_alpm_banks[unit];
   3307 }
   3308 
   3309 int
   3310 soc_tomahawk_alpm_mode_get(int unit)
   3311 {
   3312     return _soc_alpm_mode[unit];
   3313 }
   3314 
   3315 void
   3316 _soc_tomahawk_alpm_bkt_view_set(int unit, int index, soc_mem_t view)
   3317 {
   3318     int bkt = (index >> (soc_th_get_alpm_banks(unit) + 1) / 2) & SOC_TH_ALPM_BKT_MASK(unit);
   3319 
   3320     if (view != INVALIDm) {
   3321         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3322                     (BSL_META_U(unit,
   3323                                 "Unit:%d ALPM bkt set index:%d bkt:%d view:%s\n"),
   3324                                 unit, index, bkt, SOC_MEM_NAME(unit, view)));
   3325     }
   3326     _soc_th_alpm_bkt_view_map[unit][bkt] = view;
   3327 }
   3328 
   3329 soc_mem_t
   3330 _soc_tomahawk_alpm_bkt_view_get(int unit, int index)
   3331 {
   3332     soc_mem_t view;
   3333     int bkt = (index >> (soc_th_get_alpm_banks(unit) + 1) / 2) & SOC_TH_ALPM_BKT_MASK(unit);
   3334     
   3335     view = _soc_th_alpm_bkt_view_map[unit][bkt];
   3336     if (view != INVALIDm) {
   3337         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3338                     (BSL_META_U(unit,
   3339                                 "Unit:%d ALPM bkt get index:%d bkt:%d view:%s\n"),
   3340                                 unit, index, bkt, SOC_MEM_NAME(unit, view)));
   3341     }
   3342     return view;
   3343 }
   3344 
   3345 int soc_tomahawk_mem_basetype_get(int unit, soc_mem_t mem)
   3346 {
   3347     int base_type;
   3348 
   3349     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   3350     return base_type;
   3351 }
   3352 
   3353 int soc_tomahawk_mem_is_xpe(int unit, soc_mem_t mem)
   3354 {
   3355     int block_info_index;
   3356 
   3357     if (!SOC_MEM_IS_VALID(unit, mem)) {
   3358         return 0;
   3359     }
   3360 
   3361     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
   3362     if (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_XPE) {
   3363         return 1;
   3364     } else {
   3365         return 0;
   3366     }
   3367 }
   3368 
   3369 /* Function to check if given XPE/PIPE combo matches for the given mem's base
   3370  * type definition.
   3371  */
   3372 int
   3373 soc_tomahawk_mem_xpe_pipe_check(int unit, soc_mem_t mem, int xpe, int pipe)
   3374 {
   3375     int rv = SOC_E_NONE;
   3376     int block_info_index, base_type;
   3377 
   3378     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
   3379     if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_XPE) {
   3380         return SOC_E_PARAM;
   3381     }
   3382 
   3383     base_type = soc_tomahawk_mem_basetype_get(unit, mem);
   3384     rv = soc_tomahawk_xpe_base_index_check(unit, base_type, xpe, pipe, NULL);
   3385 
   3386     if (rv == SOC_E_PARAM) {
   3387         rv = SOC_E_UNAVAIL;
   3388     }
   3389 
   3390     return rv;
   3391 }
   3392 
   3393 STATIC int
   3394 _soc_tomahawk_xpe_reg_check(int unit, soc_reg_t reg, int xpe, int base_index)
   3395 {
   3396     int acc_type, base_type;
   3397 
   3398     if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_XPE)) {
   3399         LOG_CLI((BSL_META_U(unit,
   3400                             "%s is not XPE register\n"), SOC_REG_NAME(unit, reg)));
   3401         return SOC_E_PARAM;
   3402     }
   3403 
   3404     if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */
   3405         if (xpe == -1 || xpe >= NUM_XPE(unit)) {
   3406             LOG_CLI((BSL_META_U(unit,
   3407                                 "%s bad XPE value %d\n"),
   3408                      SOC_REG_NAME(unit, reg), xpe));
   3409             return SOC_E_PARAM;
   3410         }
   3411     } else {
   3412         acc_type = SOC_REG_ACC_TYPE(unit, reg);
   3413         if (acc_type < NUM_XPE(unit)) { /* UNIQUE per XPE register */
   3414             if (xpe != acc_type) {
   3415                 LOG_CLI((BSL_META_U(unit,
   3416                                     "Ovveride XPE value %d with ACC_TYPE of %s\n"),
   3417                          xpe, SOC_REG_NAME(unit, reg)));
   3418             }
   3419             xpe = acc_type;
   3420         } else { /* non-UNIQUE register */
   3421             return SOC_E_NONE;
   3422         }
   3423     }
   3424     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   3425 
   3426     return soc_tomahawk_xpe_base_index_check(unit, base_type, xpe, base_index,
   3427                                              SOC_REG_NAME(unit, reg));
   3428 }
   3429 
   3430 STATIC int
   3431 _soc_tomahawk_xpe_mem_check(int unit, soc_mem_t mem, int xpe, int base_index)
   3432 {
   3433     int block_info_index, acc_type, base_type;
   3434 
   3435     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
   3436     if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_XPE) {
   3437         LOG_CLI((BSL_META_U(unit,
   3438                             "%s is not XPE register\n"), SOC_MEM_NAME(unit, mem)));
   3439         return SOC_E_PARAM;
   3440     }
   3441 
   3442     if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { /* UNIQUE base memory */
   3443         if (xpe == -1 || xpe >= NUM_XPE(unit)) {
   3444             LOG_CLI((BSL_META_U(unit,
   3445                                 "%s bad XPE value %d\n"),
   3446                      SOC_MEM_NAME(unit, mem), xpe));
   3447             return SOC_E_PARAM;
   3448         }
   3449     } else {
   3450         acc_type = SOC_MEM_ACC_TYPE(unit, mem);
   3451         if (acc_type < NUM_XPE(unit)) { /* UNIQUE per XPE memory */
   3452             if (xpe != acc_type) {
   3453                 LOG_CLI((BSL_META_U(unit,
   3454                                     "Ovveride XPE value %d with ACC_TYPE of %s\n"),
   3455                          xpe, SOC_MEM_NAME(unit, mem)));
   3456                 xpe = acc_type;
   3457             }
   3458         } else { /* non-UNIQUE memory */
   3459             return SOC_E_NONE;
   3460         }
   3461     }
   3462     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   3463 
   3464     return soc_tomahawk_xpe_base_index_check(unit, base_type, xpe, base_index,
   3465                                              SOC_MEM_NAME(unit, mem));
   3466 }
   3467 
   3468 /*
   3469  * Parameters for soc_tomahawk_xpe_reg_access and soc_tomahawk_xpe_mem_access:
   3470  *
   3471  *    base unique  reg/  xpe   write action          read action
   3472  *   index  type   mem
   3473  *    ==== ====== ===== ===   ================      =================
   3474  * #1   -1  no     -     -    all XPEs/pipes        first pipe in the first XPE
   3475  * #2   -1  yes   base   -1   (same as #1)
   3476  * #3   -1  yes   base  0-3   all pipes in the XPE  first pipe in the XPE
   3477  * #4   -1  yes  xpe0-3  -    (same as #3)
   3478  * #5  0-3  no     -     -    applicable XPEs       first XPE has the pipe
   3479  * #6  0-3  yes   base   -1   (same as #5)
   3480  * #7  0-3  yes   base  0-3   the XPE/pipe          the XPE/pipe
   3481  * #8  0-3  yes  xpe0-3  -    (same as #7)
   3482  *
   3483  * - S/W will loop through base types (i.e. pipes) if base_index==-1
   3484  * - S/W will loop through applicable XPEs if xpe==-1 on unique access type
   3485  *   base view (H/W will do the loop for other access types)
   3486  * - base_index will be ignored if the table does not have multiple sections
   3487  *   for example ACC_TYPE==UNIQUE BASE_TYPE==XPE
   3488  */
   3489 STATIC int
   3490 _soc_tomahawk_xpe_reg_access(int unit, soc_reg_t reg, int xpe, int base_index,
   3491                              int index, uint64 *data, int write)
   3492 {
   3493     soc_info_t *si;
   3494     soc_reg_t orig_reg;
   3495     int port;
   3496     int base_type, break_after_first, unique, accessed;
   3497     int base_index_count;
   3498     uint32 base_index_map, xpe_map=0, orig_xpe_map;
   3499     soc_pbmp_t base_index_pbmp;
   3500     uint32 inst;
   3501 
   3502     si = &SOC_INFO(unit);
   3503     orig_reg = reg;
   3504     base_type = SOC_REG_BASE_TYPE(unit, reg);
   3505     break_after_first = TRUE;
   3506 
   3507     if (xpe >= 0 && base_index >= 0) {
   3508         SOC_IF_ERROR_RETURN
   3509             (_soc_tomahawk_xpe_reg_check(unit, reg, xpe, base_index));
   3510     }
   3511 
   3512     switch (base_type) {
   3513     case 0: /* IPORT */
   3514     case 1: /* EPORT */
   3515         if (xpe >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
   3516             reg = SOC_REG_UNIQUE_ACC(unit, reg)[xpe];
   3517         }
   3518 
   3519         if (base_index == -1) {
   3520             SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit));
   3521         } else {
   3522             /* This argument is logical port, same as soc_reg_get/set */
   3523             SOC_PBMP_PORT_SET(base_index_pbmp, base_index);
   3524         }
   3525 
   3526         SOC_PBMP_ITER(base_index_pbmp, port) {
   3527             /* Loop through XPE(s) only on UNIQUE type base register */
   3528             if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   3529                 if (base_index < -1) {
   3530                     return SOC_E_PARAM;
   3531                 } else if (base_index == -1) {
   3532                     xpe_map = 0xf;
   3533                 } else {
   3534                     xpe_map = base_type == 0 ?
   3535                         si->ipipe_xpe_map[base_index] :
   3536                         si->epipe_xpe_map[base_index];
   3537                 }
   3538                 if (write) {
   3539                     break_after_first = FALSE;
   3540                 }
   3541             }
   3542             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   3543                 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   3544                     if (!(xpe_map & (1 << xpe))) {
   3545                         continue;
   3546                     }
   3547                     reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe];
   3548                 }
   3549                 if (write) {
   3550                     SOC_IF_ERROR_RETURN
   3551                         (soc_reg_set(unit, reg, port, index, *data));
   3552                 } else {
   3553                     SOC_IF_ERROR_RETURN
   3554                         (soc_reg_get(unit, reg, port, index, data));
   3555                 }
   3556                 if (break_after_first) {
   3557                     break;
   3558                 }
   3559             }
   3560         }
   3561         break;
   3562     case 2: /* IPIPE */
   3563     case 3: /* EPIPE */
   3564         if (xpe >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
   3565             reg = SOC_REG_UNIQUE_ACC(unit, reg)[xpe];
   3566         }
   3567 
   3568         soc_tomahawk_pipe_map_get(unit, &base_index_map);
   3569         if (base_index != -1) {
   3570             base_index_map &= 1 << base_index;
   3571             if (base_index_map == 0) {
   3572                 return SOC_E_PARAM;
   3573             }
   3574         }
   3575 
   3576         for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) {
   3577             if (!(base_index_map & (1 << base_index))) {
   3578                 continue;
   3579             }
   3580             /* Loop through XPE(s) only on UNIQUE type base register */
   3581             if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   3582                 xpe_map = base_type == 2 ?
   3583                     si->ipipe_xpe_map[base_index] :
   3584                     si->epipe_xpe_map[base_index];
   3585                 if (write) {
   3586                     break_after_first = FALSE;
   3587                 }
   3588             }
   3589             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   3590                 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   3591                     if (!(xpe_map & (1 << xpe))) {
   3592                         continue;
   3593                     }
   3594                     reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe];
   3595                 }
   3596                 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   3597                 if (write) {
   3598                     SOC_IF_ERROR_RETURN
   3599                         (soc_reg_set(unit, reg, inst, index, *data));
   3600                 } else {
   3601                     SOC_IF_ERROR_RETURN
   3602                         (soc_reg_get(unit, reg, inst, index, data));
   3603                 }
   3604                 if (break_after_first) {
   3605                     break;
   3606                 }
   3607             }
   3608         }
   3609         break;
   3610     case 4: /* CHIP */
   3611         if (xpe == -1) {
   3612             xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   3613         } else {
   3614             xpe_map = (1 << xpe) & (si->ipipe_xpe_map[0]|si->ipipe_xpe_map[1]);
   3615         }
   3616         unique = (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL);
   3617         
   3618         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   3619             if (!(xpe_map & (1 << xpe))) {
   3620                 continue;
   3621             }
   3622 
   3623             if (unique) {
   3624                 reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe];
   3625             }
   3626             if (write) {
   3627                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data));
   3628             } else {
   3629                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data));
   3630             }
   3631             /* only unique writing need access all xpe */
   3632             if (!(write && unique)) {
   3633                 break;
   3634             }
   3635         }
   3636         break;
   3637     case 5: /* XPE */
   3638         if (xpe >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) {
   3639             reg = SOC_REG_UNIQUE_ACC(unit, reg)[xpe];
   3640         }
   3641 
   3642         if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL ||
   3643             SOC_REG_ACC_TYPE(unit, reg) < NUM_XPE(unit)) {
   3644             base_index_map = 1;
   3645         } else if (base_index == -1) {
   3646             base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   3647         } else {
   3648             base_index_map = 1 << base_index;
   3649         }
   3650 
   3651         /* Loop through XPE(s) only on UNIQUE type base register */
   3652         if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   3653             xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   3654             break_after_first = FALSE;
   3655         }
   3656 
   3657         for (base_index = 0; base_index < NUM_XPE(unit); base_index++) {
   3658             if (!(base_index_map & (1 << base_index))) {
   3659                 continue;
   3660             }
   3661             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   3662                 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) {
   3663                     if (!(xpe_map & (1 << xpe))) {
   3664                         continue;
   3665                     }
   3666                     reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe];
   3667                 }
   3668                 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   3669                 if (write) {
   3670                     SOC_IF_ERROR_RETURN
   3671                         (soc_reg_set(unit, reg, inst, index, *data));
   3672                 } else {
   3673                     SOC_IF_ERROR_RETURN
   3674                         (soc_reg_get(unit, reg, inst, index, data));
   3675                 }
   3676                 if (break_after_first) {
   3677                     break;
   3678                 }
   3679             }
   3680         }
   3681         break;
   3682     case 6: /* SLICE */
   3683     case 7: /* LAYER */
   3684         if (base_index == -1) {
   3685             base_index_map = base_type == 6 ? si->ipipe_sc_map[0] : 0x3;
   3686         } else {
   3687             base_index_map = 1 << base_index;
   3688         }
   3689         if (xpe == -1) {
   3690             orig_xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   3691         } else {
   3692             orig_xpe_map = (1 << xpe);
   3693         }
   3694         unique = (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL);
   3695         accessed = 0;
   3696 
   3697         base_index_count = base_type == 6 ? NUM_SLICE(unit) : NUM_LAYER(unit);
   3698         for (base_index = 0; base_index < base_index_count; base_index++) {
   3699             if (!(base_index_map & (1 << base_index))) {
   3700                 continue;
   3701             }
   3702             
   3703             /* Loop through XPE(s) only on UNIQUE type base register */
   3704             if (base_type == 6) {
   3705                 /* epipe 0 on sc 0, epipe 2 on sc 1 */
   3706                 xpe_map = si->epipe_xpe_map[base_index * 2];
   3707             } else {
   3708                 /* ipipe 0 on layer 0, ipipe 1 on layer 1 */
   3709                 xpe_map = si->ipipe_xpe_map[base_index];
   3710             }
   3711             xpe_map &= orig_xpe_map;
   3712 
   3713             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   3714                 if (!(xpe_map & (1 << xpe))) {
   3715                     continue;
   3716                 }
   3717                 
   3718                 if (unique) {
   3719                     reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe];
   3720                 }
   3721                 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   3722                 if (write) {
   3723                     SOC_IF_ERROR_RETURN
   3724                         (soc_reg_set(unit, reg, inst, index, *data));
   3725                 } else {
   3726                     SOC_IF_ERROR_RETURN
   3727                         (soc_reg_get(unit, reg, inst, index, data));
   3728                 }
   3729                 accessed = 1;
   3730                 /* only unique writing need access all xpe */
   3731                 if (!(write && unique)) {
   3732                     break;
   3733                 }
   3734             }
   3735             /* reading operation breaks if accessed */
   3736             if ((!write) && (accessed)) {
   3737                 break;
   3738             }
   3739         }
   3740         break;
   3741     /* No default case as base_type can have value only between 0-7 */
   3742     }
   3743 
   3744     return SOC_E_NONE;
   3745 }
   3746 
   3747 STATIC int
   3748 _soc_tomahawk_xpe_mem_access(int unit, soc_mem_t mem, int xpe, int base_index,
   3749                              int copyno, int offset_in_section,
   3750                              void *entry_data, int write)
   3751 {
   3752     soc_info_t *si;
   3753     soc_mem_t mem_list[8] = {INVALIDm};
   3754     int mem_index, mem_cnt;
   3755     int index;
   3756     int base_type;
   3757     uint32 base_index_map, xpe_map=0, orig_xpe_map;
   3758 
   3759     si = &SOC_INFO(unit);
   3760     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   3761     mem_index = 0;
   3762     
   3763     if (xpe >= 0 && base_index >= 0) {
   3764         SOC_IF_ERROR_RETURN
   3765             (_soc_tomahawk_xpe_mem_check(unit, mem, xpe, base_index));
   3766     }
   3767 
   3768     switch (base_type) {
   3769     case 2: /* IPIPE */
   3770     case 3: /* EPIPE */
   3771         /* no _PIPEx */
   3772         if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) {
   3773             mem_list[mem_index++] = mem;
   3774             break;
   3775         }
   3776         
   3777         soc_tomahawk_pipe_map_get(unit, &base_index_map);
   3778         if (base_index != -1) {
   3779             base_index_map &= (1 << base_index);
   3780             if (base_index_map == 0) {
   3781                 return SOC_E_PARAM;
   3782             }
   3783         }
   3784 
   3785         orig_xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   3786         if (xpe != -1) {
   3787             orig_xpe_map &= (1 << xpe);
   3788             if (orig_xpe_map == 0) {
   3789                 return SOC_E_PARAM;
   3790             }
   3791         }
   3792         
   3793         for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) {
   3794             if (!(base_index_map & (1 << base_index))) {
   3795                 continue;
   3796             }
   3797 
   3798             /* no need to check each pipe, 0 is enough */
   3799             if (SOC_MEM_ACC_TYPE(unit, SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, 0)) 
   3800                 == _TH_SUBS_ACC_TYPE_DUPLICATE) {
   3801                 /* _PIPEx */
   3802                 mem_list[mem_index++] = 
   3803                     SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, base_index);
   3804             } else {
   3805                 /* _XPEy_PIPEx */
   3806                 xpe_map = base_type == 2 ?
   3807                     si->ipipe_xpe_map[base_index] : 
   3808                     si->epipe_xpe_map[base_index];
   3809                 xpe_map &= orig_xpe_map;
   3810                 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   3811                     if (!(xpe_map & (1 << xpe))) {
   3812                         continue;
   3813                     }
   3814                     mem_list[mem_index++] = 
   3815                         SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, mem, xpe, base_index);
   3816                 }
   3817             }
   3818         }
   3819         break;
   3820     case 4: /* CHIP */
   3821         /* no _XPEx */
   3822         if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) {
   3823             mem_list[mem_index++] = mem;
   3824             break;
   3825         }
   3826         
   3827         xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   3828         if (xpe != -1) {
   3829             xpe_map &= (1 << xpe);
   3830             if (xpe_map == 0) {
   3831                 return SOC_E_PARAM;
   3832             }
   3833         }
   3834 
   3835         /* _XPEx */
   3836         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   3837             if (!(xpe_map & (1 << xpe))) {
   3838                 continue;
   3839             }
   3840             mem_list[mem_index++] = 
   3841                 SOC_MEM_UNIQUE_ACC_XPE(unit, mem, xpe);
   3842         }
   3843         break;
   3844     case 5: /* XPE */
   3845         /* no _XPEx */
   3846         if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) {
   3847             mem_list[mem_index++] = mem;
   3848             break;
   3849         }
   3850         
   3851         xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   3852         if (xpe != -1) {
   3853             xpe_map &= (1 << xpe);
   3854             if (xpe_map == 0) {
   3855                 return SOC_E_PARAM;
   3856             }
   3857         }
   3858 
   3859         /* _XPEx */
   3860         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   3861             if (!(xpe_map & (1 << xpe))) {
   3862                 continue;
   3863             }
   3864             mem_list[mem_index++] = 
   3865                 SOC_MEM_UNIQUE_ACC_XPE(unit, mem, xpe);
   3866         }
   3867         break;
   3868     case 6: /* SLICE */
   3869         /* no _SCx */
   3870         if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) {
   3871             mem_list[mem_index++] = mem;
   3872             break;
   3873         }
   3874         
   3875         base_index_map = si->ipipe_sc_map[0];
   3876         if (base_index != -1) {
   3877             base_index_map &= (1 << base_index);
   3878             if (base_index_map == 0) {
   3879                 return SOC_E_PARAM;
   3880             }
   3881         }
   3882 
   3883         for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) {
   3884             if (!(base_index_map & (1 << base_index))) {
   3885                 continue;
   3886             }
   3887 
   3888             /* no need to check each sc, 0 is enough */
   3889             if (SOC_MEM_ACC_TYPE(unit, SOC_MEM_UNIQUE_ACC_SC(unit, mem, 0))
   3890                 == _TH_SUBS_ACC_TYPE_DUPLICATE) {
   3891                 /* _PIPEx */
   3892                 mem_list[mem_index++] = 
   3893                     SOC_MEM_UNIQUE_ACC_SC(unit, mem, base_index);
   3894             } else {
   3895                 /* No unique access type for such base_type till now */
   3896             }
   3897         }
   3898         break;
   3899     case 0: /* IPORT */
   3900     case 1: /* EPORT */
   3901     case 7: /* LAYER */
   3902     default:
   3903         return SOC_E_INTERNAL;
   3904     }
   3905 
   3906     mem_cnt = write ? mem_index : 1;
   3907     index = offset_in_section;
   3908     for (mem_index = 0; mem_index < mem_cnt; mem_index ++) {
   3909         if (write) {
   3910             SOC_IF_ERROR_RETURN(soc_mem_write
   3911                 (unit, mem_list[mem_index], copyno, index, entry_data));
   3912         } else {
   3913             SOC_IF_ERROR_RETURN(soc_mem_read
   3914                 (unit, mem_list[mem_index], copyno, index, entry_data));
   3915         }
   3916     }
   3917 
   3918     return SOC_E_NONE;
   3919 }
   3920 
   3921 int
   3922 soc_tomahawk_sc_base_index_check(int unit, int base_type, int sc,
   3923                                  int base_index, char *msg)
   3924 {
   3925     soc_info_t *si;
   3926     int pipe;
   3927     uint32 map;
   3928     char *base_name;
   3929 
   3930     si = &SOC_INFO(unit);
   3931 
   3932     if (sc == -1 || base_index == -1) {
   3933         return SOC_E_NONE;
   3934     }
   3935 
   3936     if (sc < NUM_SLICE(unit) && si->sc_ipipe_map[sc] == 0) {
   3937         if (msg) {
   3938             LOG_CLI((BSL_META_U(unit,
   3939                                 "%s: SC%d is not in config\n"),
   3940                      msg, sc));
   3941         }
   3942         return SOC_E_PARAM;
   3943     }
   3944 
   3945     switch (base_type) {
   3946     case 0: /* IPORT */
   3947     case 1: /* EPORT */
   3948         base_name = base_type == 0 ? "IPORT" : "EPORT";
   3949         pipe = si->port_pipe[base_index];
   3950         if (pipe == -1) {
   3951             if (msg) {
   3952                 LOG_CLI((BSL_META_U(unit,
   3953                                     "%s: %s%d is not in config\n"),
   3954                          msg, base_name, base_index));
   3955             }
   3956         } else if (sc < NUM_SLICE(unit)) { /* Unique access type */
   3957             map = base_type == 0 ?
   3958                 si->ipipe_sc_map[pipe] : si->epipe_sc_map[pipe];
   3959             if (map & (1 << sc)) {
   3960                 break;
   3961             }
   3962             if (msg != NULL) {
   3963                 LOG_CLI((BSL_META_U(unit,
   3964                                     "%s: %s%d is not in SC%d\n"),
   3965                          msg, base_name, base_index, sc));
   3966             }
   3967         } else {
   3968             break;
   3969         }
   3970         return SOC_E_PARAM;
   3971     case 2: /* IPIPE */
   3972     case 3: /* EPIPE */
   3973         if (base_type == 2) {
   3974             base_name = "IPIPE";
   3975             map = si->ipipe_sc_map[base_index];
   3976         } else {
   3977             base_name = "EPIPE";
   3978             map = si->epipe_sc_map[base_index];
   3979         }
   3980         if (map == 0) {
   3981             if (msg) {
   3982                 LOG_CLI((BSL_META_U(unit,
   3983                                     "%s: %s%d is not in config\n"),
   3984                          msg, base_name, base_index));
   3985             }
   3986         } else if (sc < NUM_SLICE(unit)) { /* Unique access type */
   3987             if (map & (1 << sc)) {
   3988                 break;
   3989             }
   3990             if (msg != NULL) {
   3991                 LOG_CLI((BSL_META_U(unit,
   3992                                     "%s: %s%d is not in SC%d\n"),
   3993                          msg, base_name, base_index, sc));
   3994             }
   3995         } else {
   3996             break;
   3997         }
   3998         return SOC_E_PARAM;
   3999     case 4: /* CHIP */
   4000         break;
   4001     case 5: /* XPE */
   4002         if (si->xpe_ipipe_map[base_index] == 0) {
   4003             if (msg != NULL) {
   4004                 LOG_CLI((BSL_META_U(unit,
   4005                                     "%s: XPE%d is not in config\n"),
   4006                          msg, base_index));
   4007             }
   4008         } else if (sc < NUM_SLICE(unit)) { /* Unique access type */
   4009             if (sc == 0) { /* XPE 0 and 2 are in slice 0 */
   4010                 if (base_index == 0 || base_index == 2) {
   4011                     break;
   4012                 }
   4013             } else { /* XPE 1 and 3 are in slice 1 */
   4014                 if (base_index == 1 || base_index == 3) {
   4015                     break;
   4016                 }
   4017             }
   4018             if (msg != NULL) {
   4019                 LOG_CLI((BSL_META_U(unit,
   4020                                     "%s: XPE%d is not in SLICE%d\n"),
   4021                          msg, base_index, sc));
   4022             }
   4023         } else {
   4024             break;
   4025         }
   4026         return SOC_E_PARAM;
   4027     case 6: /* SLICE */
   4028     case 7: /* LAYER, not used */
   4029         break;
   4030     }
   4031 
   4032     return SOC_E_NONE;
   4033 }
   4034 
   4035 STATIC int
   4036 _soc_tomahawk_sc_reg_check(int unit, soc_reg_t reg, int sc, int base_index)
   4037 {
   4038     int acc_type, base_type;
   4039 
   4040     if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_SC)) {
   4041         LOG_CLI((BSL_META_U(unit,
   4042                             "%s is not SC register\n"), SOC_REG_NAME(unit, reg)));
   4043         return SOC_E_PARAM;
   4044     }
   4045 
   4046     if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */
   4047         if (sc == -1 || sc >= NUM_SLICE(unit)) {
   4048             LOG_CLI((BSL_META_U(unit,
   4049                                 "%s bad SC value %d\n"),
   4050                      SOC_REG_NAME(unit, reg), sc));
   4051             return SOC_E_PARAM;
   4052         }
   4053     } else {
   4054         acc_type = SOC_REG_ACC_TYPE(unit, reg);
   4055         if (acc_type < NUM_SLICE(unit)) { /* UNIQUE per SC register */
   4056             if (sc != acc_type) {
   4057                 LOG_CLI((BSL_META_U(unit,
   4058                                     "Ovveride SC value %d with ACC_TYPE of %s\n"),
   4059                          sc, SOC_REG_NAME(unit, reg)));
   4060             }
   4061             sc = acc_type;
   4062         } else { /* non-UNIQUE register */
   4063             return SOC_E_NONE;
   4064         }
   4065     }
   4066     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   4067 
   4068     return soc_tomahawk_sc_base_index_check(unit, base_type, sc, base_index,
   4069                                             SOC_REG_NAME(unit, reg));
   4070 }
   4071 
   4072 #if 0
   4073 STATIC int
   4074 _soc_tomahawk_sc_mem_check(int unit, soc_mem_t mem, int sc, int base_index)
   4075 {
   4076     int block_info_index, acc_type, base_type;
   4077 
   4078     block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
   4079     if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_SC) {
   4080         LOG_CLI((BSL_META_U(unit,
   4081                             "%s is not SC register\n"), SOC_MEM_NAME(unit, mem)));
   4082         return SOC_E_PARAM;
   4083     }
   4084 
   4085     if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { /* UNIQUE base memory */
   4086         if (sc == -1 || sc >= NUM_SLICE(unit)) {
   4087             LOG_CLI((BSL_META_U(unit,
   4088                                 "%s bad SC value %d\n"),
   4089                      SOC_MEM_NAME(unit, mem), sc));
   4090             return SOC_E_PARAM;
   4091         }
   4092     } else {
   4093         acc_type = SOC_MEM_ACC_TYPE(unit, mem);
   4094         if (acc_type < NUM_SLICE(unit)) { /* UNIQUE per SC memory */
   4095             if (sc != acc_type) {
   4096                 LOG_CLI((BSL_META_U(unit,
   4097                                     "Ovveride SC value %d with ACC_TYPE of %s\n"),
   4098                          sc, SOC_MEM_NAME(unit, mem)));
   4099                 sc = acc_type;
   4100             }
   4101         } else { /* non-UNIQUE memory */
   4102             return SOC_E_NONE;
   4103         }
   4104     }
   4105     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   4106 
   4107     return soc_tomahawk_sc_base_index_check(unit, base_type, sc, base_index,
   4108                                             SOC_MEM_NAME(unit, mem));
   4109 }
   4110 #endif
   4111 
   4112 STATIC int
   4113 _soc_tomahawk_sc_reg_access(int unit, soc_reg_t reg, int sc, int base_index,
   4114                             int index, uint64 *data, int write)
   4115 {
   4116     soc_info_t *si;
   4117     int port;
   4118     int base_type;
   4119     uint32 base_index_map;
   4120     soc_pbmp_t base_index_pbmp;
   4121     uint32 inst;
   4122 
   4123     si = &SOC_INFO(unit);
   4124     base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7;
   4125 
   4126     if (sc >= 0 && base_index >= 0) {
   4127         SOC_IF_ERROR_RETURN
   4128             (_soc_tomahawk_sc_reg_check(unit, reg, sc, base_index));
   4129     }
   4130 
   4131     switch (base_type) {
   4132     case 0: /* IPORT */
   4133     case 1: /* EPORT */
   4134         /* No unique access type for such base_type */
   4135         if (base_index == -1) {
   4136             SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit));
   4137         } else {
   4138             /* This argument is logical port, same as soc_reg_get/set */
   4139             SOC_PBMP_PORT_SET(base_index_pbmp, base_index);
   4140         }
   4141 
   4142         SOC_PBMP_ITER(base_index_pbmp, port) {
   4143             if (write) {
   4144                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, index, *data));
   4145             } else {
   4146                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, index, data));
   4147             }
   4148         }
   4149         break;
   4150     case 2: /* IPIPE */
   4151     case 3: /* EPIPE */
   4152         /* No unique access type for such base_type */
   4153         soc_tomahawk_pipe_map_get(unit, &base_index_map);
   4154         if (base_index != -1) {
   4155             base_index_map &= 1 << base_index;
   4156             if (base_index_map == 0) {
   4157                 return SOC_E_PARAM;
   4158             }
   4159         }
   4160 
   4161         for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) {
   4162             if (!(base_index_map & (1 << base_index))) {
   4163                 continue;
   4164             }
   4165             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   4166             if (write) {
   4167                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   4168             } else {
   4169                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   4170             }
   4171         }
   4172         break;
   4173     case 4: /* CHIP */
   4174         if (write) {
   4175             SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data));
   4176         } else {
   4177             SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data));
   4178         }
   4179         break;
   4180     case 5: /* XPE */
   4181         /* No unique access type for such base_type */
   4182         if (base_index == -1) {
   4183             base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   4184         } else {
   4185             base_index_map = 1 << base_index;
   4186         }
   4187 
   4188         for (base_index = 0; base_index < NUM_XPE(unit); base_index++) {
   4189             if (!(base_index_map & (1 << base_index))) {
   4190                 continue;
   4191             }
   4192             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   4193             if (write) {
   4194                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   4195             } else {
   4196                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   4197             }
   4198         }
   4199         break;
   4200     case 6: /* SLICE */
   4201         /* No unique access type for such base_type */
   4202         if (base_index == -1) {
   4203             base_index_map = si->ipipe_sc_map[0];;
   4204         } else {
   4205             base_index_map = 1 << base_index;
   4206         }
   4207         for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) {
   4208             if (!(base_index_map & (1 << base_index))) {
   4209                 continue;
   4210             }
   4211             inst = base_index | SOC_REG_ADDR_INSTANCE_MASK;
   4212             if (write) {
   4213                 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data));
   4214             } else {
   4215                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data));
   4216             }
   4217         }
   4218         break;
   4219     case 7: /* LAYER */
   4220     default:
   4221         return SOC_E_INTERNAL;
   4222     }
   4223 
   4224     return SOC_E_NONE;
   4225 }
   4226 #if 0
   4227 STATIC int
   4228 _soc_tomahawk_sc_mem_access(int unit, soc_mem_t mem, int sc, int base_index,
   4229                             int copyno, int offset_in_section, void *entry_data,
   4230                             int write)
   4231 {
   4232     soc_info_t *si;
   4233     soc_mem_t orig_mem;
   4234     int index, section_size;
   4235     int base_type, break_after_first;
   4236     uint32 base_index_map, sc_map=0;
   4237 
   4238     si = &SOC_INFO(unit);
   4239     orig_mem = mem;
   4240     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   4241     section_size = SOC_MEM_INFO(unit, mem).section_size;
   4242     break_after_first = TRUE;
   4243 
   4244     if (sc >= 0 && base_index >= 0) {
   4245         SOC_IF_ERROR_RETURN
   4246             (_soc_tomahawk_sc_mem_check(unit, mem, sc, base_index));
   4247     }
   4248 
   4249     switch (base_type) {
   4250     case 2: /* IPIPE */
   4251     case 3: /* EPIPE */
   4252         if (sc >= 0 && SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) {
   4253             mem = SOC_MEM_UNIQUE_ACC(unit, mem)[sc];
   4254         }
   4255 
   4256         /* All tables with such base_type should have multiple sections */
   4257         soc_tomahawk_pipe_map_get(unit, &base_index_map);
   4258         if (base_index != -1) {
   4259             base_index_map &= 1 << base_index;
   4260             if (base_index_map == 0) {
   4261                 return SOC_E_PARAM;
   4262             }
   4263         }
   4264 
   4265         for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) {
   4266             if (!(base_index_map & (1 << base_index))) {
   4267                 continue;
   4268             }
   4269             /* Loop through SC(s) only on UNIQUE type base memory */
   4270             if (SOC_MEM_UNIQUE_ACC(unit, orig_mem) != NULL) {
   4271                 sc_map = base_type == 2 ?
   4272                     si->ipipe_sc_map[base_index] :
   4273                     si->epipe_sc_map[base_index];
   4274                 if (write) {
   4275                     break_after_first = FALSE;
   4276                 }
   4277             }
   4278             for (sc = 0; sc < NUM_SLICE(unit); sc++) {
   4279                 if (SOC_MEM_UNIQUE_ACC(unit, orig_mem) != NULL) {
   4280                     if (!(sc_map & (1 << sc))) {
   4281                         continue;
   4282                     }
   4283                     mem = SOC_MEM_UNIQUE_ACC(unit, orig_mem)[sc];
   4284                 }
   4285                 index = base_index * section_size + offset_in_section;
   4286                 if (write) {
   4287                     SOC_IF_ERROR_RETURN
   4288                         (soc_mem_write(unit, mem, copyno, index, entry_data));
   4289                 } else {
   4290                     SOC_IF_ERROR_RETURN
   4291                         (soc_mem_read(unit, mem, copyno, index, entry_data));
   4292                 }
   4293                 if (break_after_first) {
   4294                     break;
   4295                 }
   4296             }
   4297         }
   4298         break;
   4299     case 5: /* XPE */
   4300         /* No unique access type for such base_type */
   4301         if (base_index == -1) {
   4302             base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
   4303         } else {
   4304             base_index_map = 1 << base_index;
   4305         }
   4306 
   4307         for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) {
   4308             if (!(base_index_map & (1 << base_index))) {
   4309                 continue;
   4310             }
   4311             index = base_index * section_size + offset_in_section;
   4312             if (write) {
   4313                 SOC_IF_ERROR_RETURN
   4314                     (soc_mem_write(unit, mem, copyno, index, entry_data));
   4315             } else {
   4316                 SOC_IF_ERROR_RETURN
   4317                     (soc_mem_read(unit, mem, copyno, index, entry_data));
   4318             }
   4319         }
   4320         break;
   4321     case 6: /* SLICE */
   4322         /* No unique access type for such base_type */
   4323         if (base_index == -1) {
   4324             base_index_map = si->ipipe_sc_map[0];
   4325         } else {
   4326             base_index_map = 1 << base_index;
   4327         }
   4328         for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) {
   4329             if (!(base_index_map & (1 << base_index))) {
   4330                 continue;
   4331             }
   4332             index = base_index * section_size + offset_in_section;
   4333             if (write) {
   4334                 SOC_IF_ERROR_RETURN
   4335                     (soc_mem_write(unit, mem, copyno, index, entry_data));
   4336             } else {
   4337                 SOC_IF_ERROR_RETURN
   4338                     (soc_mem_read(unit, mem, copyno, index, entry_data));
   4339             }
   4340         }
   4341         break;
   4342     case 0: /* IPORT */
   4343     case 1: /* EPORT */
   4344     case 4: /* CHIP */
   4345     case 7: /* LAYER */
   4346     default:
   4347         return SOC_E_INTERNAL;
   4348     }
   4349 
   4350     return SOC_E_NONE;
   4351 }
   4352 #endif
   4353 
   4354 /*About layer concept, you can refer to 1.3.3 chapter in MMUuA_overview.pdf*/
   4355 int
   4356 soc_tomahawk_mmu_layer_get(int unit, int pipe, int *layer)
   4357 {
   4358     if( layer == NULL ) {
   4359         return SOC_E_PARAM;
   4360     }
   4361     if ( pipe >= 0 && pipe < NUM_PIPE(unit)) {
   4362         if ( pipe == 0 || pipe == 3 ) { /* pipe 0 and 3 are in layer 0 */
   4363             *layer = 0;
   4364         } else { /* pipe 1 and 2 are in layer 1 */
   4365             *layer = 1;
   4366         }
   4367         return SOC_E_NONE;
   4368     }
   4369     return SOC_E_PARAM;
   4370 }
   4371 
   4372 int
   4373 soc_tomahawk_xpe_reg32_set(int unit, soc_reg_t reg, int xpe, int base_index,
   4374                            int index, uint32 data)
   4375 {
   4376     uint64 data64;
   4377 
   4378     COMPILER_64_SET(data64, 0, data);
   4379     SOC_IF_ERROR_RETURN(_soc_tomahawk_xpe_reg_access(unit, reg, xpe, base_index,
   4380                                                      index, &data64, TRUE));
   4381 
   4382     return SOC_E_NONE;
   4383 }
   4384 
   4385 int
   4386 soc_tomahawk_xpe_reg32_get(int unit, soc_reg_t reg, int xpe, int base_index,
   4387                            int index, uint32 *data)
   4388 {
   4389     uint64 data64;
   4390 
   4391     COMPILER_64_SET(data64, 0, *data);
   4392     SOC_IF_ERROR_RETURN(_soc_tomahawk_xpe_reg_access(unit, reg, xpe, base_index,
   4393                                                      index, &data64, FALSE));
   4394     *data = COMPILER_64_LO(data64);
   4395 
   4396     return SOC_E_NONE;
   4397 }
   4398 
   4399 int
   4400 soc_tomahawk_xpe_reg_set(int unit, soc_reg_t reg, int xpe, int base_index,
   4401                          int index, uint64 data)
   4402 {
   4403     return _soc_tomahawk_xpe_reg_access(unit, reg, xpe, base_index,
   4404                                         index, &data, TRUE);
   4405 }
   4406 
   4407 int
   4408 soc_tomahawk_xpe_reg_get(int unit, soc_reg_t reg, int xpe, int base_index,
   4409                          int index, uint64 *data)
   4410 {
   4411     return _soc_tomahawk_xpe_reg_access(unit, reg, xpe, base_index,
   4412                                         index, data, FALSE);
   4413 }
   4414 
   4415 int
   4416 soc_tomahawk_xpe_mem_write(int unit, soc_mem_t mem, int xpe, int base_index,
   4417                            int copyno, int offset_in_section, void *entry_data)
   4418 {
   4419     return _soc_tomahawk_xpe_mem_access(unit, mem, xpe, base_index, copyno,
   4420                                         offset_in_section, entry_data, TRUE);
   4421 }
   4422 
   4423 int
   4424 soc_tomahawk_xpe_mem_read(int unit, soc_mem_t mem, int xpe, int base_index,
   4425                           int copyno, int offset_in_section, void *entry_data)
   4426 {
   4427     return _soc_tomahawk_xpe_mem_access(unit, mem, xpe, base_index, copyno,
   4428                                         offset_in_section, entry_data, FALSE);
   4429 }
   4430 
   4431 int
   4432 soc_tomahawk_sc_reg32_set(int unit, soc_reg_t reg, int sc, int base_index,
   4433                           int index, uint32 data)
   4434 {
   4435     uint64 data64;
   4436 
   4437     COMPILER_64_SET(data64, 0, data);
   4438     SOC_IF_ERROR_RETURN(_soc_tomahawk_sc_reg_access(unit, reg, sc, base_index,
   4439                                                     index, &data64, TRUE));
   4440 
   4441     return SOC_E_NONE;
   4442 }
   4443 
   4444 int
   4445 soc_tomahawk_sc_reg32_get(int unit, soc_reg_t reg, int sc, int base_index,
   4446                           int index, uint32 *data)
   4447 {
   4448     uint64 data64;
   4449 
   4450     COMPILER_64_SET(data64, 0, *data);
   4451     SOC_IF_ERROR_RETURN(_soc_tomahawk_sc_reg_access(unit, reg, sc, base_index,
   4452                                                     index, &data64, FALSE));
   4453     *data = COMPILER_64_LO(data64);
   4454 
   4455     return SOC_E_NONE;
   4456 }
   4457 
   4458 int
   4459 soc_tomahawk_sc_reg_set(int unit, soc_reg_t reg, int sc, int base_index,
   4460                         int index, uint64 data)
   4461 {
   4462     return _soc_tomahawk_sc_reg_access(unit, reg, sc, base_index,
   4463                                        index, &data, TRUE);
   4464 }
   4465 
   4466 int
   4467 soc_tomahawk_sc_reg_get(int unit, soc_reg_t reg, int sc, int base_index,
   4468                         int index, uint64 *data)
   4469 {
   4470     return _soc_tomahawk_sc_reg_access(unit, reg, sc, base_index,
   4471                                        index, data, FALSE);
   4472 }
   4473 
   4474 int
   4475 soc_tomahawk_port_traffic_egr_enable_set(int unit, soc_port_t port,
   4476                         int enable)
   4477 {
   4478     uint64 rval64;
   4479     int mmu_port, phy_port, i;
   4480     soc_info_t *si = &SOC_INFO(unit);
   4481     soc_reg_t reg[3] = {
   4482         THDU_OUTPUT_PORT_RX_ENABLE_64r,
   4483         MMU_THDM_DB_PORT_RX_ENABLE_64r,
   4484         MMU_THDM_MCQE_PORT_RX_ENABLE_64r
   4485     };
   4486     int pipe;
   4487     uint32 mmu_inst_map;
   4488     int xpe;
   4489 
   4490     phy_port = si->port_l2p_mapping[port];
   4491     mmu_port = si->port_p2m_mapping[phy_port];
   4492     mmu_port %= SOC_TH_MMU_PORT_STRIDE;
   4493     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, port, &pipe));
   4494     mmu_inst_map = si->epipe_xpe_map[pipe];
   4495     for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   4496         if (!(mmu_inst_map & (1 << xpe))) {
   4497             continue;
   4498         }
   4499 
   4500         for (i = 0; i < 3; i++) {
   4501             COMPILER_64_ZERO(rval64);
   4502             SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg_get(unit, reg[i],
   4503                 xpe, pipe, 0, &rval64));
   4504             if (enable) {
   4505                 COMPILER_64_BITSET(rval64, mmu_port);
   4506             } else {
   4507                 COMPILER_64_BITCLR(rval64, mmu_port);
   4508             }
   4509             SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg_set(unit, reg[i],
   4510                 xpe, pipe, 0, rval64));
   4511         }
   4512     }
   4513 
   4514     return SOC_E_NONE;
   4515 }
   4516 
   4517 #if 0
   4518 int
   4519 soc_tomahawk_sc_mem_write(int unit, soc_mem_t mem, int sc, int base_index,
   4520                           int copyno, int offset_in_section, void *entry_data)
   4521 {
   4522     return _soc_tomahawk_sc_mem_access(unit, mem, sc, base_index, copyno,
   4523                                        offset_in_section, entry_data, TRUE);
   4524 }
   4525 
   4526 int
   4527 soc_tomahawk_sc_mem_read(int unit, soc_mem_t mem, int sc, int base_index,
   4528                          int copyno, int offset_in_section, void *entry_data)
   4529 {
   4530     return _soc_tomahawk_sc_mem_access(unit, mem, sc, base_index, copyno,
   4531                                        offset_in_section, entry_data, FALSE);
   4532 }
   4533 #endif
   4534 
   4535 int
   4536 soc_tomahawk_clear_mmu_memory(int unit)
   4537 {
   4538 #define SOC_MMU_BASE_TYPE_IPORT 0
   4539 #define SOC_MMU_BASE_TYPE_EPORT 1
   4540 #define SOC_MMU_BASE_TYPE_IPIPE 2
   4541 #define SOC_MMU_BASE_TYPE_EPIPE 3
   4542 #define SOC_MMU_BASE_TYPE_CHIP 4
   4543 #define SOC_MMU_BASE_TYPE_XPE 5
   4544 #define SOC_MMU_BASE_TYPE_SC 6
   4545 #define SOC_MMU_BASE_TYPE_LAYER 7
   4546     int i, j, use_base_type_views, base_type, index, num_views;
   4547     uint32 entry[SOC_MAX_MEM_WORDS];
   4548     soc_mem_t mem;
   4549     static struct {
   4550         soc_mem_t mem; /* base view */
   4551         int use_base_type_views; /* 1 means use xpe/sc/etc views */
   4552         int index; /* -1 means clear entire mem */
   4553     } mem_list[] = {
   4554         { MMU_CBPDATA0m, 1, 0 },
   4555         { MMU_CBPDATA15m, 1, 0 },
   4556         { MMU_CBPDATA30m, 1, 0 },
   4557         { MMU_CBPDATA45m, 1, 0 },
   4558         { INVALIDm, 0, -1 }
   4559     };
   4560 
   4561 #ifdef  BCM_TOMAHAWKPLUS_SUPPORT
   4562     /* adjust CBPDATA for resetting on TH+ */
   4563     if (SOC_IS_TOMAHAWKPLUS(unit)) {
   4564         mem_list[0].mem = MMU_CBPDATA0m;
   4565         mem_list[1].mem = MMU_CBPDATA19m;
   4566         mem_list[2].mem = MMU_CBPDATA38m;
   4567         mem_list[3].mem = MMU_CBPDATA57m;
   4568     }
   4569 #endif
   4570 
   4571     for (i = 0; mem_list[i].mem != INVALIDm; i++) {
   4572         mem = mem_list[i].mem;
   4573         index = mem_list[i].index;
   4574         use_base_type_views = mem_list[i].use_base_type_views;
   4575         if (use_base_type_views) {
   4576             base_type = soc_tomahawk_mem_basetype_get(unit, mem);
   4577             switch (base_type) {
   4578             case SOC_MMU_BASE_TYPE_XPE:
   4579                 num_views = NUM_XPE(unit);
   4580                 break;
   4581             case SOC_MMU_BASE_TYPE_SC:
   4582                 num_views = NUM_SLICE(unit);
   4583                 break;
   4584             case SOC_MMU_BASE_TYPE_LAYER:
   4585                 num_views = NUM_LAYER(unit);
   4586                 break;
   4587             case SOC_MMU_BASE_TYPE_IPIPE:
   4588             case SOC_MMU_BASE_TYPE_EPIPE:
   4589                 num_views = NUM_PIPE(unit);
   4590                 break;
   4591             default:
   4592                 num_views = -1; /* not supported */
   4593                 break;
   4594             }
   4595             if (num_views < 0) {
   4596                 LOG_ERROR(BSL_LS_SOC_COMMON,
   4597                           (BSL_META_U(unit,
   4598                                       "mmu_mem %s, base_type %d will not be"
   4599                                       "cleared \n"),
   4600                            SOC_MEM_NAME(unit,mem), base_type));
   4601                 continue;
   4602             }
   4603         } else {
   4604             num_views = 0; /* dont_care */
   4605         }
   4606 
   4607         sal_memset(entry, 0x0,
   4608                    soc_mem_entry_words(unit, mem) * sizeof(uint32));
   4609         if (use_base_type_views) {
   4610             for (j = 0; j < num_views; j++) {
   4611                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   4612                             (BSL_META_U(unit,
   4613                                         "mmu_mem %s, index %d will be "
   4614                                         "cleared \n"),
   4615                             SOC_MEM_NAME(unit, SOC_MEM_UNIQUE_ACC(unit, mem)[j]),
   4616                             index));
   4617                 if (index >= 0) {
   4618                     SOC_IF_ERROR_RETURN
   4619                         (soc_mem_write(unit,
   4620                                        SOC_MEM_UNIQUE_ACC(unit, mem)[j],
   4621                                        MEM_BLOCK_ALL, index, entry));
   4622                 } else {
   4623                     SOC_IF_ERROR_RETURN
   4624                         (soc_mem_clear(unit,
   4625                                        SOC_MEM_UNIQUE_ACC(unit, mem)[j],
   4626                                        COPYNO_ALL, TRUE));
   4627                 }
   4628             }
   4629         } else {
   4630             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   4631                         (BSL_META_U(unit,
   4632                                     "mmu_mem %s, index %d will be "
   4633                                     "cleared \n"),
   4634                         SOC_MEM_NAME(unit, mem), index));
   4635             if (index >= 0) {
   4636                 SOC_IF_ERROR_RETURN
   4637                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index,
   4638                                    entry));
   4639             } else {
   4640                 SOC_IF_ERROR_RETURN
   4641                     (soc_mem_clear(unit, mem, COPYNO_ALL, TRUE));
   4642             }
   4643         }
   4644     }
   4645     return SOC_E_NONE;
   4646 }
   4647 
   4648 /* Function to Clear all Memories.
   4649  * Param
   4650  *   mmu_init - bool val to indicate whether to initialize mmu or not.
   4651  */
   4652 STATIC int
   4653 _soc_tomahawk_clear_all_memory(int unit, int mmu_init)
   4654 {
   4655     uint32 pipe_map;
   4656     soc_reg_t reg;
   4657     int pipe, count;
   4658     uint32 rval, in_progress;
   4659     int pipe_init_usec;
   4660     soc_timeout_t to;
   4661 
   4662     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   4663 
   4664     /* Initial IPIPE memory */
   4665     rval = 0;
   4666     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_1r(unit, rval));
   4667     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1);
   4668     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1);
   4669     /* Set count to # entries of largest IPIPE table */
   4670     count = soc_mem_index_count(unit, ING_L3_NEXT_HOPm);
   4671     if (count < soc_mem_index_count(unit, L2Xm)) {
   4672         count = soc_mem_index_count(unit, L2Xm);
   4673     }
   4674     if (count < soc_mem_index_count(unit, L3_ENTRY_ONLYm)) {
   4675         count = soc_mem_index_count(unit, L3_ENTRY_ONLYm);
   4676     }
   4677     if (count < soc_mem_index_count(unit, FPEM_ECCm)) {
   4678         count = soc_mem_index_count(unit, FPEM_ECCm);
   4679     }
   4680     if (count < soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) {
   4681         count = soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m);
   4682     }
   4683     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, count);
   4684     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   4685 
   4686     /* Initial L2_MGT memories */
   4687     rval = 0;
   4688     SOC_IF_ERROR_RETURN(WRITE_L2_MGMT_HW_RESET_CONTROL_0r(unit, rval));
   4689     soc_reg_field_set(unit, L2_MGMT_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1);
   4690     soc_reg_field_set(unit, L2_MGMT_HW_RESET_CONTROL_1r, &rval, VALIDf, 1);
   4691     count = soc_mem_index_count(unit, L2_MOD_FIFOm);
   4692     if (count < soc_mem_index_count(unit, L2_MGMT_SER_FIFOm)) {
   4693         count = soc_mem_index_count(unit, L2_MGMT_SER_FIFOm);
   4694     }
   4695     soc_reg_field_set(unit, L2_MGMT_HW_RESET_CONTROL_1r, &rval, COUNTf, count);
   4696     SOC_IF_ERROR_RETURN(WRITE_L2_MGMT_HW_RESET_CONTROL_1r(unit, rval));
   4697 
   4698     /* Initial EPIPE memory */
   4699     rval = 0;
   4700     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_0r(unit, rval));
   4701     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1);
   4702     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, VALIDf, 1);
   4703     /* Set count to # entries in largest EPIPE table (EGR_L3_NEXT_HOP) */
   4704     count = SOC_MEM_INFO(unit, EGR_L3_NEXT_HOPm).index_max + 1;
   4705     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, COUNTf, count);
   4706     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval));
   4707 
   4708     /* For simulation, set timeout to 10 sec.  Otherwise, timeout = 50 ms */
   4709     if (SAL_BOOT_SIMULATION) {
   4710         pipe_init_usec = 10000000;
   4711     } else {
   4712         pipe_init_usec = 50000;
   4713     }
   4714     soc_timeout_init(&to, pipe_init_usec, 0);
   4715 
   4716     /* Wait for IPIPE memory initialization done */
   4717     in_progress = pipe_map;
   4718     do {
   4719         sal_usleep(1000);
   4720         for (pipe = 0; pipe < _TH_PIPES_PER_DEV && in_progress; pipe++) {
   4721             if (in_progress & (1 << pipe)) { /* not done yet */
   4722                 reg = SOC_REG_UNIQUE_ACC(unit, ING_HW_RESET_CONTROL_2r)[pipe];
   4723                 SOC_IF_ERROR_RETURN
   4724                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4725                     if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   4726                         in_progress ^= 1 << pipe;
   4727                     }
   4728             }
   4729         }
   4730         if (soc_timeout_check(&to)) {
   4731             LOG_WARN(BSL_LS_SOC_COMMON,
   4732                      (BSL_META_U(unit,
   4733                                  "unit %d : ING_HW_RESET timeout\n"), unit));
   4734             break;
   4735         }
   4736     } while (in_progress != 0);
   4737 
   4738     /* Wait for EPIPE memory initialization done */
   4739     in_progress = pipe_map;
   4740     do {
   4741         for (pipe = 0; pipe < _TH_PIPES_PER_DEV && in_progress; pipe++) {
   4742             if (in_progress & (1 << pipe)) { /* not done yet */
   4743                 reg = SOC_REG_UNIQUE_ACC(unit, EGR_HW_RESET_CONTROL_1r)[pipe];
   4744                 SOC_IF_ERROR_RETURN
   4745                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4746                     if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   4747                         in_progress ^= 1 << pipe;
   4748                     }
   4749             }
   4750         }
   4751         if (in_progress != 0) {
   4752             sal_usleep(1000);
   4753         }
   4754         if (soc_timeout_check(&to)) {
   4755             LOG_WARN(BSL_LS_SOC_COMMON,
   4756                      (BSL_META_U(unit,
   4757                                  "unit %d : EGR_HW_RESET timeout\n"), unit));
   4758             break;
   4759         }
   4760     } while (in_progress != 0);
   4761 
   4762     /* Make sure L2_MGMT memories are all clean */
   4763     reg = L2_MGMT_HW_RESET_CONTROL_1r;
   4764     SOC_IF_ERROR_RETURN
   4765         (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4766     if (!soc_reg_field_get(unit, reg, rval, DONEf)) {
   4767         LOG_WARN(BSL_LS_SOC_COMMON, (BSL_META_U(unit,
   4768             "unit %d : L2_MGMT_HW_RESET not done (reg val: 0x%x) !! \n"),
   4769             unit, rval));
   4770     } else {
   4771         SOC_IF_ERROR_RETURN(WRITE_L2_MGMT_HW_RESET_CONTROL_1r(unit, 0));
   4772     }
   4773 
   4774     rval = 0;
   4775     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   4776     rval = SOC_REG_INFO(unit, EGR_HW_RESET_CONTROL_1r).rst_val_lo;
   4777     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval));
   4778 
   4779     /* Initialize IDB memory */
   4780     SOC_IF_ERROR_RETURN(WRITE_IDB_HW_CONTROLr(unit, 0));
   4781     rval = 0;
   4782     soc_reg_field_set(unit, IDB_HW_CONTROLr, &rval, IS_MEM_INITf, 1);
   4783     SOC_IF_ERROR_RETURN(WRITE_IDB_HW_CONTROLr(unit, rval));
   4784     SOC_IF_ERROR_RETURN(WRITE_IDB_HW_CONTROLr(unit, 0));
   4785 
   4786     if (mmu_init) {
   4787         /* Initialize MMU memory */
   4788         SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, 0));
   4789         rval = 0;
   4790         soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, INIT_MEMf, 1);
   4791         SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   4792         SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, 0));
   4793     }
   4794 
   4795     return SOC_E_NONE;
   4796 }
   4797 
   4798 STATIC int
   4799 _soc_tomahawk_port_mapping_init(int unit)
   4800 {
   4801     soc_info_t *si;
   4802     int port, phy_port, idb_port;
   4803     int num_port, num_phy_port;
   4804     soc_reg_t reg;
   4805     soc_mem_t mem;
   4806     uint32 rval;
   4807     uint32 entry[SOC_MAX_MEM_WORDS];
   4808     int pipe;
   4809     int i;
   4810     uint16 dev_id = 0;
   4811     uint8 rev_id = 0;
   4812 
   4813     /*
   4814      * 96 entries MMU_CHFC_SYSPORT_MAPPINGm.SYS_PORT
   4815      * 256 entries SYS_PORTMAPm.DEVICE_PORT_NUMBER
   4816      */
   4817 
   4818     si = &SOC_INFO(unit);
   4819     soc_cm_get_id(unit, &dev_id, &rev_id);
   4820 
   4821     num_port = soc_mem_index_count(unit, PORT_TABm) - 1;
   4822     num_phy_port = 136;
   4823 
   4824     /* Ingress physical to device port mapping */
   4825     sal_memset(&entry, 0,
   4826                sizeof(ing_idb_to_device_port_number_mapping_table_entry_t));
   4827     for (phy_port = 0; phy_port < num_phy_port; phy_port++) {
   4828         port = si->port_p2l_mapping[phy_port];
   4829         if (port != -1) {
   4830             pipe = si->port_pipe[port];
   4831             idb_port = si->port_l2i_mapping[port];
   4832         } else if (phy_port >= 132) { /* loopback port */
   4833             pipe = phy_port - 132;
   4834             idb_port = 33;
   4835         } else if (phy_port == 129) { /* management port 0 (if not in use) */
   4836             pipe = 1;
   4837             idb_port = 32;
   4838         } else if (phy_port == 130) { /* undefined physical port */
   4839             pipe = 3;
   4840             idb_port = 32;
   4841         } else if (phy_port == 131) { /* management port 1 (if not in use) */
   4842             pipe = 2;
   4843             idb_port = 32;
   4844         } else {
   4845             pipe = (phy_port - 1) / _TH_PORTS_PER_PIPE;
   4846             idb_port = (phy_port -1 ) % _TH_PORTS_PER_PIPE;
   4847         }
   4848         mem = SOC_MEM_UNIQUE_ACC
   4849             (unit, ING_IDB_TO_DEVICE_PORT_NUMBER_MAPPING_TABLEm)[pipe];
   4850         soc_mem_field32_set(unit, mem, &entry, DEVICE_PORT_NUMBERf,
   4851                             port == -1 ? 0xff : port);
   4852         SOC_IF_ERROR_RETURN
   4853             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, idb_port, &entry));
   4854     }
   4855 
   4856     /* Ingress GPP port to device port mapping */
   4857     mem = SYS_PORTMAPm;
   4858     sal_memset(&entry, 0, sizeof(sys_portmap_entry_t));
   4859     for (port = 0; port < num_port; port++) {
   4860         soc_mem_field32_set(unit, mem, &entry, DEVICE_PORT_NUMBERf, port);
   4861         SOC_IF_ERROR_RETURN
   4862             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, port, &entry));
   4863     }
   4864 
   4865     /* Ingress device port to GPP port mapping
   4866      * PORT_TAB.SRC_SYS_PORT_ID is programmed in the general port config
   4867      * init routine _bcm_fb_port_cfg_init()
   4868      */
   4869 
   4870     /* Egress device port to physical port mapping */
   4871     rval = 0;
   4872     reg = EGR_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGr;
   4873     PBMP_ALL_ITER(unit, port) {
   4874         soc_reg_field_set(unit, reg, &rval, PHYSICAL_PORT_NUMBERf,
   4875                           si->port_l2p_mapping[port]);
   4876         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   4877     }
   4878 
   4879     /* MMU port to device port mapping */
   4880     rval = 0;
   4881     reg = MMU_PORT_TO_DEVICE_PORT_MAPPINGr;
   4882     PBMP_ALL_ITER(unit, port) {
   4883         soc_reg_field_set(unit, reg, &rval, DEVICE_PORTf, port);
   4884         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   4885     }
   4886 
   4887     /* MMU port to physical port mapping */
   4888     rval = 0;
   4889     reg = MMU_PORT_TO_PHY_PORT_MAPPINGr;
   4890     PBMP_ALL_ITER(unit, port) {
   4891         soc_reg_field_set(unit, reg, &rval, PHY_PORTf,
   4892                           si->port_l2p_mapping[port]);
   4893         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   4894     }
   4895 
   4896     /* MMU port to system port mapping */
   4897     rval = 0;
   4898     reg = MMU_PORT_TO_SYSTEM_PORT_MAPPINGr;
   4899     PBMP_ALL_ITER(unit, port) {
   4900         soc_reg_field_set(unit, reg, &rval, SYSTEM_PORTf, port);
   4901         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   4902     }
   4903     
   4904     if ((BCM56963_DEVICE_ID == dev_id) || (BCM56967_DEVICE_ID == dev_id)) {
   4905         const int phy_pbmp_lb_disable[] = {
   4906             13,14,15,16,17,18,19,20,25,26,27,28,29,30,31,32,45,46,47,48,
   4907             57,58,59,60,61,62,63,64,73,74,75,76,77,78,79,80,89,90,91,92,
   4908             93,94,95,96,113,114,115,116,121,122,123,124,125,126,127,128};
   4909         for (i = 0; i < COUNTOF(phy_pbmp_lb_disable); i++) {
   4910             phy_port = phy_pbmp_lb_disable[i];
   4911             port = si->port_p2l_mapping[phy_port];
   4912             if (port != -1) {
   4913                 SOC_PBMP_PORT_ADD(loopback_disable[unit],port);
   4914             }
   4915         }
   4916     }
   4917     return SOC_E_NONE;
   4918 }
   4919 
   4920 STATIC int
   4921 _soc_tomahawk_tdm_idb_calendar_set(int unit,  int calendar_id, int in_pipe)
   4922 {
   4923     soc_info_t *si;
   4924     _soc_tomahawk_tdm_t *tdm;
   4925     uint32 pipe_map;
   4926     soc_mem_t mem;
   4927     soc_reg_t reg;
   4928     soc_field_t field;
   4929     int pipe, slot, id, length;
   4930     int port, phy_port, idb_port;
   4931     uint32 rval = 0;
   4932     uint32 entry[SOC_MAX_MEM_WORDS];
   4933     static const soc_mem_t calendar_mems[] = {
   4934         IS_TDM_CALENDAR0m, IS_TDM_CALENDAR1m
   4935     };
   4936     static const soc_field_t calendar_end_fields[] = {
   4937         CAL0_ENDf, CAL1_ENDf
   4938     };
   4939 
   4940     si = &SOC_INFO(unit);
   4941     tdm = SOC_CONTROL(unit)->tdm_info;
   4942 
   4943     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   4944 
   4945     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   4946         if (!(pipe_map & (1 << pipe)) ||
   4947             ((UPDATE_ALL_PIPES != in_pipe) && (pipe != in_pipe))) {
   4948             continue;
   4949         }
   4950 
   4951         for (length = _TDM_LENGTH; length > 0; length--) {
   4952             if (tdm->idb_tdm[pipe][length - 1] != TH_NUM_EXT_PORTS) {
   4953                 break;
   4954             }
   4955         }
   4956 
   4957         reg = SOC_REG_UNIQUE_ACC(unit, IS_TDM_CONFIGr)[pipe];
   4958         if (calendar_id == -1) { /* choose "the other one" */
   4959             SOC_IF_ERROR_RETURN
   4960                 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   4961             calendar_id = soc_reg_field_get(unit, reg, rval, CURR_CALf) ^ 1;
   4962         }
   4963         mem = SOC_MEM_UNIQUE_ACC(unit, calendar_mems[calendar_id])[pipe];
   4964         field = calendar_end_fields[calendar_id];
   4965         sal_memset(entry, 0, soc_mem_entry_words(unit, mem) * sizeof(uint32));
   4966         for (slot = 0; slot < length; slot += 2) {
   4967             phy_port = tdm->idb_tdm[pipe][slot];
   4968             id = -1;
   4969             if (phy_port == TH_OVSB_TOKEN) {
   4970                 idb_port = _SOC_TH_TDM_OVERSUB_TOKEN;
   4971             } else if (phy_port == TH_IDL1_TOKEN) {
   4972                 idb_port = _SOC_TH_TDM_IDL1_TOKEN;
   4973             } else if (phy_port == TH_IDL2_TOKEN) {
   4974                 idb_port = _SOC_TH_TDM_IDL2_TOKEN;
   4975             } else if (phy_port == NULL_TOKEN) {
   4976                 idb_port = _SOC_TH_TDM_NULL_TOKEN;
   4977             } else if (phy_port >= TH_NUM_EXT_PORTS) {
   4978                 idb_port = _SOC_TH_TDM_UNUSED_TOKEN;
   4979             } else {
   4980                 /* TDM code  always allocates slots for management ports.
   4981                  * If mgmgt ports are omitted from config, this mapping
   4982                  * is not set up.
   4983                  */
   4984                 if ((phy_port == 129) || (phy_port == 131)){
   4985                     idb_port = 32;
   4986                     id = 0xf;
   4987                 }
   4988                 else {
   4989                     port = si->port_p2l_mapping[phy_port];
   4990                     idb_port = si->port_l2i_mapping[port];
   4991                     id = si->port_serdes[port];
   4992                 }
   4993             }
   4994             soc_mem_field32_set(unit, mem, entry, PORT_NUM_EVENf, idb_port);
   4995             soc_mem_field32_set(unit, mem, entry, PHY_PORT_ID_EVENf, id & 0xf);
   4996             phy_port = tdm->idb_tdm[pipe][slot + 1];
   4997             id = -1;
   4998             if (phy_port == TH_OVSB_TOKEN) {
   4999                 idb_port = _SOC_TH_TDM_OVERSUB_TOKEN;
   5000             } else if (phy_port == TH_IDL1_TOKEN) {
   5001                 idb_port = _SOC_TH_TDM_IDL1_TOKEN;
   5002             } else if (phy_port == TH_IDL2_TOKEN) {
   5003                 idb_port = _SOC_TH_TDM_IDL2_TOKEN;
   5004             } else if (phy_port == NULL_TOKEN) {
   5005                 idb_port = _SOC_TH_TDM_NULL_TOKEN;
   5006             } else if (phy_port >= TH_NUM_EXT_PORTS) {
   5007                 idb_port = _SOC_TH_TDM_UNUSED_TOKEN;
   5008             } else {
   5009                 /* TDM code  always allocates slots for management ports.
   5010                  * If mgmgt ports are omitted from config, this mapping
   5011                  * is not set up.
   5012                  */
   5013                 if ((phy_port == 129) || (phy_port == 131)){
   5014                     idb_port = 32;
   5015                     id = 0xf;
   5016                 }
   5017                 else {
   5018                     port = si->port_p2l_mapping[phy_port];
   5019                     idb_port = si->port_l2i_mapping[port];
   5020                     id = si->port_serdes[port];
   5021                 }
   5022             }
   5023             soc_mem_field32_set(unit, mem, entry, PORT_NUM_ODDf, idb_port);
   5024             soc_mem_field32_set(unit, mem, entry, PHY_PORT_ID_ODDf, id & 0xf);
   5025             SOC_IF_ERROR_RETURN
   5026                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot / 2, entry));
   5027             if (tdm->idb_tdm[pipe][slot + 2] == TH_NUM_EXT_PORTS) {
   5028                 soc_reg_field_set(unit, reg, &rval, field,
   5029                                   phy_port == TH_NUM_EXT_PORTS ? slot : slot + 1);
   5030                 break;
   5031             }
   5032         }
   5033         soc_reg_field_set(unit, reg, &rval, CURR_CALf, calendar_id);
   5034         soc_reg_field_set(unit, reg, &rval, ENABLEf, 1);
   5035         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   5036     }
   5037 
   5038     return SOC_E_NONE;
   5039 }
   5040 
   5041 STATIC int
   5042 _soc_tomahawk_tdm_idb_oversub_group_set(int unit)
   5043 {
   5044     soc_info_t *si;
   5045     _soc_tomahawk_tdm_t *tdm;
   5046     uint32 pipe_map;
   5047     int block_info_idx;
   5048     soc_reg_t reg, reg1;
   5049     int pipe, clport, group, lane, slot, id, mode, ovs_class;
   5050     int port, phy_port, phy_port_base, idb_port;
   5051     int speed_max;
   5052     uint32 rval;
   5053     static const soc_reg_t grp_tbl_regs[] = {
   5054         IS_OVR_SUB_GRP0_TBLr, IS_OVR_SUB_GRP1_TBLr,
   5055         IS_OVR_SUB_GRP2_TBLr, IS_OVR_SUB_GRP3_TBLr,
   5056         IS_OVR_SUB_GRP4_TBLr, IS_OVR_SUB_GRP5_TBLr
   5057     };
   5058     static const soc_reg_t pblk_calendar_regs[] ={
   5059         IS_PBLK0_CALENDARr, IS_PBLK1_CALENDARr,
   5060         IS_PBLK2_CALENDARr, IS_PBLK3_CALENDARr,
   5061         IS_PBLK4_CALENDARr, IS_PBLK5_CALENDARr,
   5062         IS_PBLK6_CALENDARr, IS_PBLK7_CALENDARr
   5063     };
   5064     static int pblk_slots[SOC_TH_PORT_RATIO_COUNT][7] = {
   5065         { 0, -1,  0,  0, -1,  0, -1 }, /* SOC_TH_PORT_RATIO_SINGLE */
   5066         { 0, -1,  2,  0, -1,  2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_1 */
   5067         { 0,  0,  2,  0,  0,  2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_2_1 */
   5068         { 0,  2,  2,  0,  2,  2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_2 */
   5069         { 0, -1,  2,  0, -1,  3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_2_1_1 */
   5070         { 0,  0,  2,  0,  0,  3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_4_1_1 */
   5071         { 0, -1,  2,  1, -1,  2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_2 */
   5072         { 0,  2,  2,  1,  2,  2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_4 */
   5073         { 0, -1,  2,  1, -1,  3, -1 }  /* SOC_TH_PORT_RATIO_QUAD */
   5074     };
   5075 
   5076     si = &SOC_INFO(unit);
   5077     tdm = SOC_CONTROL(unit)->tdm_info;
   5078 
   5079     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   5080 
   5081     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5082         if (!(pipe_map & (1 << pipe))) {
   5083             continue;
   5084         }
   5085 
   5086         reg1 = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe];
   5087         for (group = 0; group < _OVS_GROUP_COUNT; group++) {
   5088             reg = SOC_REG_UNIQUE_ACC(unit, grp_tbl_regs[group])[pipe];
   5089             rval = 0;
   5090             for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
   5091                 phy_port = tdm->idb_ovs_tdm[pipe][group][slot];
   5092                 if (phy_port >= TH_NUM_EXT_PORTS) {
   5093                     idb_port = 0x3f;
   5094                     id = 0;
   5095                 } else {
   5096                     port = si->port_p2l_mapping[phy_port];
   5097                     idb_port = si->port_l2i_mapping[port];
   5098                     id = si->port_serdes[port];
   5099                 }
   5100                 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id & 0x7);
   5101                 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port);
   5102                 SOC_IF_ERROR_RETURN
   5103                     (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
   5104             }
   5105             /* Handle the case where the first element in the group
   5106              * is invalid but other valid ports exist in the group.
   5107              */
   5108             for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
   5109                 phy_port = tdm->idb_ovs_tdm[pipe][group][slot];
   5110                 if (phy_port < TH_NUM_EXT_PORTS) {
   5111                     break;
   5112                 }
   5113             }
   5114             /* No valid ports found, skip group */
   5115             if (_OVS_GROUP_TDM_LENGTH == slot) {
   5116                 continue;
   5117             }
   5118             if (si->os_mixed_sister_25_50_enable == 0) {
   5119                 port = si->port_p2l_mapping[phy_port];
   5120                 speed_max = 25000 * si->port_num_lanes[port];
   5121                 if (speed_max > si->port_speed_max[port]) {
   5122                     speed_max = si->port_speed_max[port];
   5123                 }
   5124             } else {
   5125                 speed_max = tdm->speed[phy_port];
   5126             }
   5127             _soc_tomahawk_speed_to_ovs_class_mapping(unit, speed_max,
   5128                                                      &ovs_class);
   5129             rval = 0;
   5130             soc_reg_field_set(unit, reg1, &rval, SAME_SPACINGf, 4);
   5131             soc_reg_field_set(unit, reg1, &rval, SISTER_SPACINGf, 4);
   5132             soc_reg_field_set(unit, reg1, &rval, SPEEDf, ovs_class);
   5133             SOC_IF_ERROR_RETURN
   5134                 (soc_reg32_set(unit, reg1, REG_PORT_ANY, group, rval));
   5135         }
   5136     }
   5137 
   5138     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   5139         port = SOC_BLOCK_PORT(unit, block_info_idx);
   5140         phy_port_base = PORT_BLOCK_BASE_PORT(port);
   5141         pipe = si->port_pipe[port];
   5142         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   5143 
   5144         mode = tdm->port_ratio[clport];
   5145         reg = SOC_REG_UNIQUE_ACC(unit, pblk_calendar_regs[clport & 0x7])[pipe];
   5146         rval = 0;
   5147         soc_reg_field_set(unit, reg, &rval, VALIDf, 1);
   5148         soc_reg_field_set(unit, reg, &rval, SPACINGf, 4);
   5149         for (slot = 0; slot < 7; slot++) {
   5150             lane = pblk_slots[mode][slot];
   5151             if (lane == -1) {
   5152                 SOC_IF_ERROR_RETURN
   5153                     (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, 0));
   5154                 continue;
   5155             }
   5156             port = si->port_p2l_mapping[phy_port_base + lane];
   5157             idb_port = si->port_l2i_mapping[port];
   5158             soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port);
   5159             SOC_IF_ERROR_RETURN
   5160                 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
   5161         }
   5162     }
   5163 
   5164     return SOC_E_NONE;
   5165 }
   5166 
   5167 int
   5168 _soc_tomahawk_tdm_idb_opportunistic_set(int unit, int enable)
   5169 {
   5170     soc_reg_t reg;
   5171     uint32 pipe_map;
   5172     int pipe;
   5173     uint32 rval;
   5174 
   5175     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   5176 
   5177     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5178         if (!(pipe_map & (1 << pipe))) {
   5179             continue;
   5180         }
   5181 
   5182         reg = SOC_REG_UNIQUE_ACC(unit, IS_CPU_LB_OPP_CFGr)[pipe];
   5183         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   5184         soc_reg_field_set(unit, reg, &rval, CPU_OPP_ENf, enable ? 1 : 0);
   5185         soc_reg_field_set(unit, reg, &rval, LB_OPP_ENf, enable ? 1 : 0);
   5186         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   5187 
   5188         reg = SOC_REG_UNIQUE_ACC(unit, IS_OPP_SCHED_CFGr)[pipe];
   5189         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   5190         soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, enable ? 1 : 0);
   5191         soc_reg_field_set(unit, reg, &rval, OPP2_PORT_ENf, enable ? 1 : 0);
   5192         soc_reg_field_set(unit, reg, &rval, OPP_OVR_SUB_ENf, enable ? 1 : 0);
   5193         soc_reg_field_set(unit, reg, &rval, DISABLE_PORT_NUMf, 35);
   5194         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   5195     }
   5196 
   5197     return SOC_E_NONE;
   5198 }
   5199 
   5200 int
   5201 _soc_tomahawk_tdm_idb_hsp_set(int unit, int all_pipes)
   5202 {
   5203     soc_info_t *si;
   5204     soc_reg_t reg;
   5205     uint32 pipe_map;
   5206     int pipe;
   5207     int port, idb_port;
   5208     uint32 port_map[_TH_PIPES_PER_DEV];
   5209     uint32 rval = 0x0;
   5210 
   5211     si = &SOC_INFO(unit);
   5212 
   5213     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   5214 
   5215     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5216         port_map[pipe] = 0;
   5217     }
   5218     SOC_PBMP_ITER(si->eq_pbm, port) {
   5219         pipe = si->port_pipe[port];
   5220         idb_port = si->port_l2i_mapping[port];
   5221         port_map[pipe] |= 1 << idb_port;
   5222     }
   5223 
   5224     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5225         if (!(pipe_map & (1 << pipe))) {
   5226             continue;
   5227         }
   5228         if ((UPDATE_ALL_PIPES == all_pipes) || (pipe == all_pipes)) {
   5229             reg = SOC_REG_UNIQUE_ACC(unit, IS_TDM_HSPr)[pipe];
   5230             soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[pipe]);
   5231             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   5232         }
   5233     }
   5234 
   5235     return SOC_E_NONE;
   5236 }
   5237 
   5238 STATIC int
   5239 _soc_tomahawk_tdm_mmu_calendar_set(int unit, int calendar_id, int in_pipe)
   5240 {
   5241     soc_info_t *si;
   5242     _soc_tomahawk_tdm_t *tdm;
   5243     uint32 pipe_map;
   5244     soc_mem_t mem;
   5245     soc_reg_t reg;
   5246     soc_field_t field;
   5247     int pipe, slot, id, length;
   5248     int port, phy_port, mmu_port, inst;
   5249     uint32 rval = 0;
   5250     uint32 entry[SOC_MAX_MEM_WORDS];
   5251     static const soc_mem_t calendar_mems[] = {
   5252         TDM_CALENDAR0m, TDM_CALENDAR1m
   5253     };
   5254     static const soc_field_t calendar_end_fields[] = {
   5255         CAL0_ENDf, CAL1_ENDf
   5256     };
   5257 
   5258     si = &SOC_INFO(unit);
   5259     tdm = SOC_CONTROL(unit)->tdm_info;
   5260 
   5261     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   5262 
   5263     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5264         if (!(pipe_map & (1 << pipe)) ||
   5265             ((UPDATE_ALL_PIPES != in_pipe) && (pipe != in_pipe))) {
   5266             continue;
   5267         }
   5268 
   5269         for (length = _TDM_LENGTH; length > 0; length--) {
   5270             if (tdm->mmu_tdm[pipe][length - 1] != TH_NUM_EXT_PORTS) {
   5271                 break;
   5272             }
   5273         }
   5274 
   5275         reg = TDM_CONFIGr;
   5276         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   5277         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval));
   5278         if (calendar_id == -1) { /* choose "the other one" */
   5279             calendar_id = soc_reg_field_get(unit, reg, rval, CURR_CALf) ^ 1;
   5280         }
   5281         mem = SOC_MEM_UNIQUE_ACC(unit, calendar_mems[calendar_id])[pipe];
   5282         field = calendar_end_fields[calendar_id];
   5283         sal_memset(entry, 0, soc_mem_entry_words(unit, mem) * sizeof(uint32));
   5284         for (slot = 0; slot < length; slot += 2) {
   5285             phy_port = tdm->mmu_tdm[pipe][slot];
   5286             id = -1;
   5287             if (phy_port == TH_OVSB_TOKEN) {
   5288                 mmu_port = _SOC_TH_TDM_OVERSUB_TOKEN;
   5289             } else if (phy_port == TH_IDL1_TOKEN) {
   5290                 mmu_port = _SOC_TH_TDM_IDL1_TOKEN;
   5291             } else if (phy_port == TH_IDL2_TOKEN) {
   5292                 mmu_port = _SOC_TH_TDM_IDL2_TOKEN;
   5293             } else if (phy_port == NULL_TOKEN) {
   5294                 mmu_port = _SOC_TH_TDM_NULL_TOKEN;
   5295             } else if (phy_port >= TH_NUM_EXT_PORTS) {
   5296                 mmu_port = _SOC_TH_TDM_UNUSED_TOKEN;
   5297             } else {
   5298                 /* TDM code  always allocates slots for management ports.
   5299                  * If mgmgt ports are omitted from config, this mapping
   5300                  * is not set up.
   5301                  */
   5302                 id = 0xf;
   5303                 if (phy_port == 129) {
   5304                     mmu_port = 96;
   5305                 } else if (phy_port == 131){
   5306                     mmu_port = 160;
   5307                 } else {
   5308                     mmu_port = si->port_p2m_mapping[phy_port];
   5309                     port = si->port_p2l_mapping[phy_port];
   5310                     id = si->port_serdes[port];
   5311                 }
   5312             }
   5313             soc_mem_field32_set(unit, mem, entry, PORT_NUM_EVENf,
   5314                                 mmu_port & 0x3f);
   5315             soc_mem_field32_set(unit, mem, entry, PHY_PORT_ID_EVENf, id & 0xf);
   5316             phy_port = tdm->mmu_tdm[pipe][slot + 1];
   5317             id = -1;
   5318             if (phy_port == TH_OVSB_TOKEN) {
   5319                 mmu_port = _SOC_TH_TDM_OVERSUB_TOKEN;
   5320             } else if (phy_port == TH_IDL1_TOKEN) {
   5321                 mmu_port = _SOC_TH_TDM_IDL1_TOKEN;
   5322             } else if (phy_port == TH_IDL2_TOKEN) {
   5323                 mmu_port = _SOC_TH_TDM_IDL2_TOKEN;
   5324             } else if (phy_port == NULL_TOKEN) {
   5325                 mmu_port = _SOC_TH_TDM_NULL_TOKEN;
   5326             } else if (phy_port >= TH_NUM_EXT_PORTS) {
   5327                 mmu_port = _SOC_TH_TDM_UNUSED_TOKEN;
   5328             } else {
   5329                 /* TDM code  always allocates slots for management ports.
   5330                  * If mgmgt ports are omitted from config, this mapping
   5331                  * is not set up.
   5332                  */
   5333                 id = 0xf;
   5334                 if (phy_port == 129) {
   5335                     mmu_port = 96;
   5336                 } else if (phy_port == 131){
   5337                     mmu_port = 160;
   5338                 } else {
   5339                     mmu_port = si->port_p2m_mapping[phy_port];
   5340                     port = si->port_p2l_mapping[phy_port];
   5341                     id = si->port_serdes[port];
   5342                 }
   5343             }
   5344             soc_mem_field32_set(unit, mem, entry, PORT_NUM_ODDf,
   5345                                 mmu_port & 0x3f);
   5346             soc_mem_field32_set(unit, mem, entry, PHY_PORT_ID_ODDf, id & 0xf);
   5347             SOC_IF_ERROR_RETURN
   5348                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot / 2, entry));
   5349             if (tdm->mmu_tdm[pipe][slot + 2] == TH_NUM_EXT_PORTS) {
   5350                 soc_reg_field_set(unit, reg, &rval, field,
   5351                                   phy_port == TH_NUM_EXT_PORTS ? slot : slot + 1);
   5352                 break;
   5353             }
   5354         }
   5355         soc_reg_field_set(unit, reg, &rval, CURR_CALf, calendar_id);
   5356         soc_reg_field_set(unit, reg, &rval, ENABLEf, 1);
   5357         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   5358     }
   5359 
   5360     return SOC_E_NONE;
   5361 }
   5362 
   5363 STATIC int
   5364 _soc_tomahawk_tdm_mmu_oversub_group_set(int unit)
   5365 {
   5366     soc_info_t *si;
   5367     _soc_tomahawk_tdm_t *tdm;
   5368     uint32 pipe_map;
   5369     int block_info_idx;
   5370     soc_reg_t reg, reg1;
   5371     int pipe, clport, group, lane, slot, id, mode, ovs_class;
   5372     int port, phy_port, phy_port_base, mmu_port, inst;
   5373     int speed_max;
   5374     uint32 rval;
   5375     static const soc_reg_t grp_tbl_regs[] = {
   5376         OVR_SUB_GRP0_TBLr, OVR_SUB_GRP1_TBLr,
   5377         OVR_SUB_GRP2_TBLr, OVR_SUB_GRP3_TBLr,
   5378         OVR_SUB_GRP4_TBLr, OVR_SUB_GRP5_TBLr
   5379     };
   5380     static const soc_reg_t pblk_calendar_regs[] = {
   5381         PBLK0_CALENDARr, PBLK1_CALENDARr, PBLK2_CALENDARr, PBLK3_CALENDARr,
   5382         PBLK4_CALENDARr, PBLK5_CALENDARr, PBLK6_CALENDARr, PBLK7_CALENDARr
   5383     };
   5384     static const int pblk_slots[SOC_TH_PORT_RATIO_COUNT][7] = {
   5385         { 0, -1,  0,  0, -1,  0, -1 }, /* SOC_TH_PORT_RATIO_SINGLE */
   5386         { 0, -1,  2,  0, -1,  2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_1 */
   5387         { 0,  0,  2,  0,  0,  2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_2_1 */
   5388         { 0,  2,  2,  0,  2,  2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_2 */
   5389         { 0, -1,  2,  0, -1,  3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_2_1_1 */
   5390         { 0,  0,  2,  0,  0,  3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_4_1_1 */
   5391         { 0, -1,  2,  1, -1,  2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_2 */
   5392         { 0,  2,  2,  1,  2,  2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_4 */
   5393         { 0, -1,  2,  1, -1,  3, -1 }  /* SOC_TH_PORT_RATIO_QUAD */
   5394     };
   5395 
   5396     si = &SOC_INFO(unit);
   5397     tdm = SOC_CONTROL(unit)->tdm_info;
   5398 
   5399     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   5400 
   5401     reg1 = OVR_SUB_GRP_CFGr;
   5402     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5403         if (!(pipe_map & (1 << pipe))) {
   5404             continue;
   5405         }
   5406 
   5407         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   5408         for (group = 0; group < _OVS_GROUP_COUNT; group++) {
   5409             reg = grp_tbl_regs[group];
   5410             rval = 0;
   5411             for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
   5412                 phy_port = tdm->mmu_ovs_tdm[pipe][group][slot];
   5413                 if (phy_port >= TH_NUM_EXT_PORTS) {
   5414                     mmu_port = 0x3f;
   5415                     id = 0;
   5416                 } else {
   5417                     mmu_port = si->port_p2m_mapping[phy_port];
   5418                     port = si->port_p2l_mapping[phy_port];
   5419                     id = si->port_serdes[port];
   5420                 }
   5421                 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id & 0x7);
   5422                 soc_reg_field_set(unit, reg, &rval, PORT_NUMf,
   5423                                   mmu_port & 0x3f);
   5424                 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
   5425             }
   5426             /* Handle the case where the first element in the group
   5427              * is invalid but other valid ports exist in the group.
   5428              */
   5429             for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
   5430                 phy_port = tdm->mmu_ovs_tdm[pipe][group][slot];
   5431                 if (phy_port < TH_NUM_EXT_PORTS) {
   5432                     break;
   5433                 }
   5434             }
   5435             /* No valid ports found, skip group */
   5436             if (_OVS_GROUP_TDM_LENGTH == slot) {
   5437                 continue;
   5438             }
   5439             if (si->os_mixed_sister_25_50_enable == 0) {
   5440                 port = si->port_p2l_mapping[phy_port];
   5441                 speed_max = 25000 * si->port_num_lanes[port];
   5442                 if (speed_max > si->port_speed_max[port]) {
   5443                     speed_max = si->port_speed_max[port];
   5444                 }
   5445             } else {
   5446                 speed_max = tdm->speed[phy_port];
   5447             }
   5448             _soc_tomahawk_speed_to_ovs_class_mapping(unit, speed_max,
   5449                                                      &ovs_class);
   5450             rval = 0;
   5451             soc_reg_field_set(unit, reg1, &rval, SAME_SPACINGf,
   5452                               speed_max >= 40000 ? 4 : 8);
   5453             soc_reg_field_set(unit, reg1, &rval, SISTER_SPACINGf, 4);
   5454             soc_reg_field_set(unit, reg1, &rval, SPEEDf, ovs_class);
   5455             SOC_IF_ERROR_RETURN
   5456                 (soc_reg32_set(unit, reg1, inst, group, rval));
   5457         }
   5458     }
   5459 
   5460     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   5461         port = SOC_BLOCK_PORT(unit, block_info_idx);
   5462         phy_port_base = PORT_BLOCK_BASE_PORT(port);
   5463         if (si->os_mixed_sister_25_50_enable == 0) {
   5464             speed_max = 25000 * si->port_num_lanes[port];
   5465             if (speed_max > si->port_speed_max[port]) {
   5466                 speed_max = si->port_speed_max[port];
   5467             }
   5468         } else {
   5469                 phy_port = si->port_l2p_mapping[port];
   5470                 speed_max = tdm->speed[phy_port];
   5471         }
   5472         pipe = si->port_pipe[port];
   5473         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   5474         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   5475 
   5476         mode = tdm->port_ratio[clport];
   5477         reg = pblk_calendar_regs[clport & 0x7];
   5478         rval = 0;
   5479         soc_reg_field_set(unit, reg, &rval, VALIDf, 1);
   5480         soc_reg_field_set(unit, reg, &rval, SPACINGf,
   5481                           speed_max >= 40000 ? 4 : 8);
   5482         for (slot = 0; slot < 7; slot++) {
   5483             lane = pblk_slots[mode][slot];
   5484             if (lane == -1) {
   5485                 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, 0));
   5486                 continue;
   5487             }
   5488             mmu_port = si->port_p2m_mapping[phy_port_base + lane];
   5489             soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f);
   5490             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
   5491         }
   5492     }
   5493 
   5494     return SOC_E_NONE;
   5495 }
   5496 
   5497 int
   5498 _soc_tomahawk_tdm_mmu_opportunistic_set(int unit, int enable)
   5499 {
   5500     uint32 pipe_map;
   5501     soc_reg_t reg;
   5502     int pipe;
   5503     int inst;
   5504     uint32 rval;
   5505 
   5506     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   5507 
   5508     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5509         if (!(pipe_map & (1 << pipe))) {
   5510             continue;
   5511         }
   5512 
   5513         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   5514 
   5515         reg = CPU_LB_OPP_CFGr;
   5516         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval));
   5517         soc_reg_field_set(unit, reg, &rval, CPU_OPP_ENf, enable ? 1 : 0);
   5518         soc_reg_field_set(unit, reg, &rval, LB_OPP_ENf, enable ? 1 : 0);
   5519         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   5520 
   5521         reg = OPP_SCHED_CFGr;
   5522         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval));
   5523         soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, enable ? 1 : 0);
   5524         soc_reg_field_set(unit, reg, &rval, OPP2_PORT_ENf, enable ? 1 : 0);
   5525         soc_reg_field_set(unit, reg, &rval, OPP_OVR_SUB_ENf, enable ? 1 : 0);
   5526         soc_reg_field_set(unit, reg, &rval, DISABLE_PORT_NUMf, 35);
   5527         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   5528     }
   5529 
   5530     return SOC_E_NONE;
   5531 }
   5532 
   5533 int
   5534 _soc_tomahawk_tdm_mmu_hsp_set(int unit, int all_pipes)
   5535 {
   5536     soc_info_t *si;
   5537     uint32 pipe_map;
   5538     soc_reg_t reg;
   5539     int pipe;
   5540     int port, phy_port, mmu_port, inst;
   5541     uint32 port_map[_TH_PIPES_PER_DEV];
   5542     uint32 rval = 0x0;
   5543 
   5544     si = &SOC_INFO(unit);
   5545 
   5546     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   5547 
   5548     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5549         port_map[pipe] = 0;
   5550     }
   5551     SOC_PBMP_ITER(si->eq_pbm, port) {
   5552         pipe = si->port_pipe[port];
   5553         phy_port = si->port_l2p_mapping[port];
   5554         mmu_port = si->port_p2m_mapping[phy_port];
   5555         port_map[pipe] |= 1 << (mmu_port & 0x1f);
   5556     }
   5557 
   5558     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5559         if (!(pipe_map & (1 << pipe))) {
   5560             continue;
   5561         }
   5562 
   5563         if ((UPDATE_ALL_PIPES == all_pipes) || (pipe == all_pipes)) {
   5564             inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   5565             reg = TDM_HSPr;
   5566             soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[pipe]);
   5567             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval));
   5568         }
   5569     }
   5570 
   5571     return SOC_E_NONE;
   5572 }
   5573 
   5574 STATIC int
   5575 _soc_tomahawk_tdm_calculation(int unit, int initTime, _soc_tomahawk_tdm_t *tdm)
   5576 {
   5577     soc_info_t *si;
   5578     int port, phy_port;
   5579     int pipe, clport, lane, group, block_info_idx, index, cal_id, cal_grp;
   5580     int length, ovs_core_slot_count, ovs_io_slot_count, port_slot_count;
   5581     int mode[_TH_PIPES_PER_DEV];
   5582     int *tdm_idb_pipe_main, *tdm_mmu_pipe_main;
   5583     int **tdm_idb_pipe_group, **tdm_mmu_pipe_group;
   5584     tdm_soc_t _chip_pkg;
   5585     tdm_mod_t *_tdm_pkg;
   5586     soc_pbmp_t pbmp;
   5587     soc_th_port_lanes_t lanes_ctrl;
   5588 
   5589     si = &SOC_INFO(unit);
   5590 
   5591     sal_memset(tdm, 0, sizeof(_soc_tomahawk_tdm_t));
   5592     sal_memset(&_chip_pkg, 0, sizeof(tdm_soc_t));
   5593 
   5594     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5595         SOC_PBMP_ASSIGN(pbmp, si->pipe_pbm[pipe]);
   5596         SOC_PBMP_AND(pbmp, PBMP_HG_ALL(unit));
   5597         mode[pipe] = SOC_PBMP_NOT_NULL(pbmp) ? PORT_HIGIG2 : PORT_ETHERNET;
   5598     }
   5599 
   5600     for (index = 0; index < COUNTOF(tdm->pm_encap_type); index++) {
   5601         tdm->pm_encap_type[index] = PORT_ETHERNET;
   5602     }
   5603     PBMP_PORT_ITER(unit, port) {
   5604         if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   5605             continue;
   5606         }
   5607         phy_port = si->port_l2p_mapping[port];
   5608         tdm->port_state[phy_port] =
   5609             SOC_PBMP_MEMBER(si->oversub_pbm, port) ?
   5610             PORT_STATE_OVERSUB : PORT_STATE_LINERATE;
   5611         for (lane = 1; lane < si->port_num_lanes[port]; lane++) {
   5612             tdm->port_state[phy_port + lane] = PORT_STATE_CONTINUATION;
   5613         }
   5614         if (initTime) {
   5615             /* When invoked by init misc, use speed obtained from
   5616              * config file.
   5617              */
   5618             tdm->speed[phy_port] = si->port_speed_max[port];
   5619             /* bootup in normmally config */
   5620             if (si->os_mixed_sister_25_50_enable == 0) {
   5621                 tdm->speed[phy_port] = si->port_speed_max[port];
   5622             } else { /* bootup in mixed config */
   5623                 sal_memset(&lanes_ctrl, 0, sizeof(lanes_ctrl));
   5624                 lanes_ctrl.port_base = port;
   5625                 lanes_ctrl.os_mixed_sister = si->os_mixed_sister_25_50_enable;
   5626                 soc_th_os_mixed_sister_port_mode_get(unit, initTime, &lanes_ctrl);
   5627                 if (lanes_ctrl.mixed_port_mode == MIXED_DUAL_MODE_50_0_25_0 ||
   5628                     lanes_ctrl.mixed_port_mode == MIXED_DUAL_MODE_25_0_50_0 ||
   5629                     lanes_ctrl.mixed_port_mode == MIXED_DUAL_MODE_25_0_25_0) {
   5630                     tdm->speed[phy_port] = IS_HG_PORT(unit, port) ? 53000 : 50000;
   5631                 } else {
   5632                     tdm->speed[phy_port] = si->port_speed_max[port];
   5633                 }
   5634             }
   5635         } else {
   5636             /* When invoked as part of flexport transform use fixedup
   5637              * speed.
   5638              */
   5639             tdm->speed[phy_port] = si->port_init_speed[port];
   5640         }
   5641     }
   5642 
   5643     /* CLPORT */
   5644     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   5645         port = SOC_BLOCK_PORT(unit, block_info_idx);
   5646         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   5647         soc_tomahawk_port_ratio_get(unit, initTime, clport, &tdm->port_ratio[clport]);
   5648         tdm->pm_encap_type[clport] = mode[si->port_pipe[port]];
   5649     }
   5650 
   5651     /* Management ports */
   5652     SOC_PBMP_ITER(si->management_pbm, port) {
   5653         phy_port = si->port_l2p_mapping[port];
   5654         tdm->pm_encap_type[_TH_PBLKS_PER_DEV] = mode[si->port_pipe[port]];
   5655         tdm->speed[phy_port] = si->port_speed_max[port];
   5656     }
   5657 
   5658     if (LOG_CHECK(BSL_LS_SOC_TDM | BSL_INFO)) {
   5659         LOG_CLI((BSL_META_U(unit,
   5660                             "frequency: %dMHz\n"), si->frequency));
   5661         LOG_CLI((BSL_META_U(unit,
   5662                             "port speed:")));
   5663         for (index = 0; index < TH_NUM_EXT_PORTS; index++) {
   5664             if (index % 8 == 0) {
   5665                 LOG_CLI((BSL_META_U(unit,
   5666                                     "\n    ")));
   5667             }
   5668             LOG_CLI((BSL_META_U(unit,
   5669                                 " %6d"), tdm->speed[index]));
   5670         }
   5671         LOG_CLI((BSL_META_U(unit,
   5672                             "\n")));
   5673         LOG_CLI((BSL_META_U(unit,
   5674                             "port state map:")));
   5675         for (index = 0; index < TH_NUM_EXT_PORTS; index++) {
   5676             if (index % 16 == 0) {
   5677                 LOG_CLI((BSL_META_U(unit,
   5678                                     "\n    ")));
   5679             }
   5680             if (index == 0 || index == (TH_NUM_EXT_PORTS - 1)) {
   5681                 LOG_CLI((BSL_META_U(unit,
   5682                                     " ---")));
   5683             } else {
   5684                 LOG_CLI((BSL_META_U(unit,
   5685                                     " %3d"), tdm->port_state[index]));
   5686             }
   5687         }
   5688         LOG_CLI((BSL_META_U(unit,
   5689                             "\n")));
   5690         LOG_CLI((BSL_META_U(unit,
   5691                             "pm encap type:")));
   5692         for (index = 0; index < TH_NUM_PM_MOD; index++) {
   5693             if (index % 16 == 0) {
   5694                 LOG_CLI((BSL_META_U(unit,
   5695                                     "\n    ")));
   5696             }
   5697             LOG_CLI((BSL_META_U(unit,
   5698                                 " %3d"), tdm->pm_encap_type[index]));
   5699         }
   5700         LOG_CLI((BSL_META_U(unit,
   5701                             "\n")));
   5702     }
   5703 
   5704     for (index = 0; index < TH_NUM_EXT_PORTS; index++) {
   5705         tdm->tdm_globals.speed[index] = tdm->speed[index];
   5706     }
   5707     tdm->tdm_globals.clk_freq = si->frequency;
   5708     for (index = 1; index < TH_NUM_EXT_PORTS; index++) {
   5709         tdm->tdm_globals.port_rates_array[index-1] = tdm->port_state[index];
   5710     }
   5711     for (index = 1; index < TH_NUM_PM_MOD; index++) {
   5712         tdm->tdm_globals.pm_encap_type[index] = tdm->pm_encap_type[index];
   5713     }
   5714     _chip_pkg.unit = unit;
   5715     _chip_pkg.num_ext_ports = TH_NUM_EXT_PORTS;
   5716     _chip_pkg.state=sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int *),
   5717                                                            "port state list");
   5718     if (_chip_pkg.state == NULL) {
   5719         return SOC_E_MEMORY;
   5720     }
   5721     _chip_pkg.speed=sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int *),
   5722                                                            "port speed list");
   5723     if (_chip_pkg.speed == NULL) {
   5724         sal_free(_chip_pkg.state);
   5725         return SOC_E_MEMORY;
   5726     }
   5727     for (index=0; index<TH_NUM_PHY_PORTS; index++) {
   5728         _chip_pkg.state[index] = tdm->pm_encap_type[((index)/TH_NUM_PM_LNS)]==
   5729         PORT_HIGIG2?((tdm->tdm_globals.port_rates_array[index])|
   5730         PSBMP_ENCAP_HIGIG):(tdm->tdm_globals.port_rates_array[index]);
   5731     }
   5732     for (index=TH_NUM_PHY_PORTS; index<TH_NUM_EXT_PORTS; index++) {
   5733         _chip_pkg.state[index] = tdm->tdm_globals.port_rates_array[index];
   5734     }
   5735     for (index=0; index<(_chip_pkg.num_ext_ports); index++) {
   5736         _chip_pkg.speed[index] = tdm->tdm_globals.speed[index];
   5737     }
   5738     _chip_pkg.soc_vars.th.cal_universal_en = si->fabric_port_enable;
   5739     _chip_pkg.clk_freq = tdm->tdm_globals.clk_freq;
   5740     _chip_pkg.soc_vars.th.mgmt_pm_hg=
   5741             ((tdm->tdm_globals.pm_encap_type[TH_NUM_PHY_PM]==PORT_HIGIG2)&&
   5742              ((tdm->tdm_globals.speed[129]>0)||
   5743              (tdm->tdm_globals.speed[131]>0)))?(1):(0);
   5744     _chip_pkg.tvec_size = 0;
   5745     _tdm_pkg = _soc_set_tdm_tbl(SOC_SEL_TDM(&_chip_pkg));
   5746     sal_free(_chip_pkg.state);
   5747     sal_free(_chip_pkg.speed);
   5748     if (NULL == _tdm_pkg) {
   5749         LOG_CLI((BSL_META_U(unit,
   5750             "Unsupported config for TDM calendar generation\n")));
   5751         return SOC_E_FAIL;
   5752     }
   5753     else {
   5754         for (cal_id = 0; cal_id < 4; cal_id++) {
   5755             switch (cal_id) {
   5756                 case 0:
   5757                     tdm_idb_pipe_group=_tdm_pkg->_chip_data.cal_0.cal_grp;
   5758                     tdm_idb_pipe_main=_tdm_pkg->_chip_data.cal_0.cal_main;
   5759                     tdm_mmu_pipe_group=_tdm_pkg->_chip_data.cal_4.cal_grp;
   5760                     tdm_mmu_pipe_main=_tdm_pkg->_chip_data.cal_4.cal_main;
   5761                     break;
   5762                 case 1:
   5763                     tdm_idb_pipe_group=_tdm_pkg->_chip_data.cal_1.cal_grp;
   5764                     tdm_idb_pipe_main=_tdm_pkg->_chip_data.cal_1.cal_main;
   5765                     tdm_mmu_pipe_group=_tdm_pkg->_chip_data.cal_5.cal_grp;
   5766                     tdm_mmu_pipe_main=_tdm_pkg->_chip_data.cal_5.cal_main;
   5767                     break;
   5768                 case 2:
   5769                     tdm_idb_pipe_group=_tdm_pkg->_chip_data.cal_2.cal_grp;
   5770                     tdm_idb_pipe_main=_tdm_pkg->_chip_data.cal_2.cal_main;
   5771                     tdm_mmu_pipe_group=_tdm_pkg->_chip_data.cal_6.cal_grp;
   5772                     tdm_mmu_pipe_main=_tdm_pkg->_chip_data.cal_6.cal_main;
   5773                     break;
   5774                 case 3:
   5775                     tdm_idb_pipe_group=_tdm_pkg->_chip_data.cal_3.cal_grp;
   5776                     tdm_idb_pipe_main=_tdm_pkg->_chip_data.cal_3.cal_main;
   5777                     tdm_mmu_pipe_group=_tdm_pkg->_chip_data.cal_7.cal_grp;
   5778                     tdm_mmu_pipe_main=_tdm_pkg->_chip_data.cal_7.cal_main;
   5779                     break;
   5780                 default:
   5781                     tdm_idb_pipe_group=NULL;
   5782                     tdm_idb_pipe_main=NULL;
   5783                     tdm_mmu_pipe_group=NULL;
   5784                     tdm_mmu_pipe_main=NULL;
   5785             }
   5786             tdm->idb_tdm[cal_id] = sal_alloc(sizeof(int)*_TDM_LENGTH,
   5787                                                      "IDB TDM main calendar");
   5788             if (tdm->idb_tdm[cal_id] == NULL) {
   5789                 return SOC_E_MEMORY;
   5790             }
   5791             sal_memcpy(tdm->idb_tdm[cal_id], tdm_idb_pipe_main,
   5792                                                      sizeof(int)*_TDM_LENGTH);
   5793             tdm->mmu_tdm[cal_id] = sal_alloc(sizeof(int)*_TDM_LENGTH,
   5794                                                      "MMU TDM main calendar");
   5795             if (tdm->mmu_tdm[cal_id] == NULL) {
   5796                 return SOC_E_MEMORY;
   5797             }
   5798             sal_memcpy(tdm->mmu_tdm[cal_id], tdm_mmu_pipe_main,
   5799                                                      sizeof(int)*_TDM_LENGTH);
   5800             for (cal_grp = 0; cal_grp < _OVS_GROUP_COUNT; cal_grp++) {
   5801                 tdm->idb_ovs_tdm[cal_id][cal_grp] = sal_alloc(sizeof(int)*
   5802                               _OVS_GROUP_TDM_LENGTH,"IDB TDM group calendar");
   5803                 if (tdm->idb_ovs_tdm[cal_id][cal_grp] == NULL) {
   5804                     return SOC_E_MEMORY;
   5805                 }
   5806                 sal_memcpy(tdm->idb_ovs_tdm[cal_id][cal_grp],
   5807               tdm_idb_pipe_group[cal_grp], sizeof(int)*_OVS_GROUP_TDM_LENGTH);
   5808                 tdm->mmu_ovs_tdm[cal_id][cal_grp] = sal_alloc(sizeof(int)*
   5809                               _OVS_GROUP_TDM_LENGTH,"MMU TDM group calendar");
   5810                 if (tdm->mmu_ovs_tdm[cal_id][cal_grp] == NULL) {
   5811                     return SOC_E_MEMORY;
   5812                 }
   5813                 sal_memcpy(tdm->mmu_ovs_tdm[cal_id][cal_grp],
   5814               tdm_mmu_pipe_group[cal_grp], sizeof(int)*_OVS_GROUP_TDM_LENGTH);
   5815             }
   5816         }
   5817         tdm_th_free(_tdm_pkg);
   5818         sal_free(_tdm_pkg);
   5819     }
   5820 
   5821     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5822         /* Count number of TH_OVSB_TOKEN assigned by the TDM code */
   5823         for (length = _TDM_LENGTH; length > 0; length--) {
   5824             if (tdm->mmu_tdm[pipe][length - 1] != TH_NUM_EXT_PORTS) {
   5825                 break;
   5826             }
   5827         }
   5828         ovs_core_slot_count = 0;
   5829         for (index = 0; index < length; index++) {
   5830             if (tdm->mmu_tdm[pipe][index] == TH_OVSB_TOKEN) {
   5831                 ovs_core_slot_count++;
   5832             }
   5833         }
   5834 
   5835         /* Count number of slot needed for the oversub I/O bandwidth */
   5836         ovs_io_slot_count = 0;
   5837         for (group = 0; group < _OVS_GROUP_COUNT; group++) {
   5838             port_slot_count = 0;
   5839             for (index = 0; index < _OVS_GROUP_TDM_LENGTH; index++) {
   5840                 phy_port = tdm->mmu_ovs_tdm[pipe][group][index];
   5841                 if (phy_port == TH_NUM_EXT_PORTS) {
   5842                     continue;
   5843                 }
   5844                 if (port_slot_count == 0) {
   5845                     _soc_tomahawk_speed_to_slot_mapping
   5846                         (unit, tdm->speed[phy_port], &port_slot_count);
   5847                 }
   5848                 ovs_io_slot_count += port_slot_count;
   5849             }
   5850         }
   5851 
   5852         if (ovs_core_slot_count != 0) {
   5853             tdm->ovs_ratio_x1000[pipe] =
   5854                 ovs_io_slot_count * 1000 / ovs_core_slot_count;
   5855         }
   5856     }
   5857 
   5858     if (LOG_CHECK(BSL_LS_SOC_TDM | BSL_INFO)) {
   5859         for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5860             LOG_CLI((BSL_META_U(unit,
   5861                                 "Pipe %d idb_tdm:"), pipe));
   5862             for (index = 0; index < _TDM_LENGTH; index++) {
   5863                 if (index % 16 == 0) {
   5864                     LOG_CLI((BSL_META_U(unit,
   5865                                         "\n    ")));
   5866                 }
   5867                 LOG_CLI((BSL_META_U(unit,
   5868                                     " %3d"), tdm->idb_tdm[pipe][index]));
   5869             }
   5870             LOG_CLI((BSL_META_U(unit,
   5871                                 "\n")));
   5872             for (group = 0; group < _OVS_GROUP_COUNT; group++) {
   5873                 LOG_CLI((BSL_META_U(unit,
   5874                                     "Pipe %d group %d idb_ovs_tdm"), pipe, group));
   5875                 for (index = 0; index < _OVS_GROUP_TDM_LENGTH; index++) {
   5876                     if (index % 16 == 0) {
   5877                         LOG_CLI((BSL_META_U(unit,
   5878                                             "\n    ")));
   5879                     }
   5880                     LOG_CLI((BSL_META_U(unit,
   5881                                         " %3d"), tdm->idb_ovs_tdm[pipe][group][index]));
   5882                 }
   5883                 LOG_CLI((BSL_META_U(unit,
   5884                                     "\n")));
   5885             }
   5886 
   5887             LOG_CLI((BSL_META_U(unit,
   5888                                 "Pipe %d mmu_tdm:"), pipe));
   5889             for (index = 0; index < _TDM_LENGTH; index++) {
   5890                 if (index % 16 == 0) {
   5891                     LOG_CLI((BSL_META_U(unit,
   5892                                         "\n    ")));
   5893                 }
   5894                 LOG_CLI((BSL_META_U(unit,
   5895                                     " %3d"), tdm->mmu_tdm[pipe][index]));
   5896             }
   5897             LOG_CLI((BSL_META_U(unit,
   5898                                 "\n")));
   5899             for (group = 0; group < _OVS_GROUP_COUNT; group++) {
   5900                 LOG_CLI((BSL_META_U(unit,
   5901                                     "Pipe %d group %d mmu_ovs_tdm"),
   5902                          pipe, group));
   5903                 for (index = 0; index < _OVS_GROUP_TDM_LENGTH; index++) {
   5904                     if (index % 16 == 0) {
   5905                         LOG_CLI((BSL_META_U(unit,
   5906                                             "\n    ")));
   5907                     }
   5908                     LOG_CLI((BSL_META_U(unit,
   5909                                         " %3d"), tdm->mmu_ovs_tdm[pipe][group][index]));
   5910                 }
   5911                 LOG_CLI((BSL_META_U(unit,
   5912                                     "\n")));
   5913             }
   5914             LOG_CLI((BSL_META_U(unit,
   5915                                 "Pipe %d oversubscribe ratio %d.%-2d\n"),
   5916                      pipe, tdm->ovs_ratio_x1000[pipe] / 1000,
   5917                      tdm->ovs_ratio_x1000[pipe] % 1000));
   5918         }
   5919     }
   5920 
   5921     return SOC_E_NONE;
   5922 }
   5923 
   5924 STATIC int 
   5925 _soc_tomahawk_tdm_calculation_free_memory(int unit)
   5926 {
   5927     int pipe, cal_grp;
   5928     soc_control_t *soc;
   5929     _soc_tomahawk_tdm_t *tdm;
   5930 
   5931     soc = SOC_CONTROL(unit);
   5932     tdm = NULL;
   5933     if (soc!=NULL){
   5934         if(soc->tdm_info!=NULL){
   5935             tdm = soc->tdm_info;
   5936         }
   5937     }
   5938     if (tdm!=NULL){
   5939         for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   5940             if (tdm->idb_tdm[pipe]!=NULL){
   5941                 sal_free(tdm->idb_tdm[pipe]);
   5942             }
   5943             if (tdm->mmu_tdm[pipe]!=NULL){
   5944                 sal_free(tdm->mmu_tdm[pipe]);
   5945             }
   5946             for (cal_grp = 0; cal_grp < _OVS_GROUP_COUNT; cal_grp++) {
   5947                 if (tdm->idb_ovs_tdm[pipe][cal_grp]!=NULL){
   5948                     sal_free(tdm->idb_ovs_tdm[pipe][cal_grp]);
   5949                 }
   5950                 if (tdm->mmu_ovs_tdm[pipe][cal_grp]!=NULL){
   5951                     sal_free(tdm->mmu_ovs_tdm[pipe][cal_grp]);
   5952                 }
   5953             }
   5954         }
   5955     }
   5956 
   5957     return SOC_E_NONE;
   5958 }
   5959 
   5960 STATIC int
   5961 _soc_tomahawk_hash_init(int unit)
   5962 {
   5963     soc_field_t fields[4];
   5964     uint32 values[4];
   5965 
   5966 
   5967     /* L2 dedicated banks */
   5968     fields[0] = BANK0_HASH_OFFSETf;
   5969     values[0] = 0;  /* CRC32_LOWER */
   5970     fields[1] = BANK1_HASH_OFFSETf;
   5971     values[1] = 16; /* CRC32_UPPER */
   5972     SOC_IF_ERROR_RETURN
   5973         (soc_reg_fields32_modify(unit, L2_TABLE_HASH_CONTROLr, REG_PORT_ANY, 2,
   5974                                  fields, values));
   5975 
   5976     if (soc_feature(unit, soc_feature_l3)) {
   5977         /* L3 dedicated banks */
   5978         fields[0] = BANK6_HASH_OFFSETf;
   5979         values[0] = 0;  /* CRC32_LOWER */
   5980         fields[1] = BANK7_HASH_OFFSETf;
   5981         values[1] = 8;  /* CRC32 >> 8 */
   5982         fields[2] = BANK8_HASH_OFFSETf;
   5983         values[2] = 16; /* CRC32_UPPER */
   5984         fields[3] = BANK9_HASH_OFFSETf;
   5985         values[3] = 32; /* CRC16 */
   5986         SOC_IF_ERROR_RETURN
   5987             (soc_reg_fields32_modify(unit, L3_TABLE_HASH_CONTROLr, REG_PORT_ANY, 4,
   5988                                      fields, values));
   5989 
   5990         /* SHARED_TABLE_HASH_CONTROLr is not accessible in
   5991          * low, balanced latency modes */
   5992         if (SOC_REG_IS_VALID(unit, SHARED_TABLE_HASH_CONTROLr)) {
   5993             /* L2/L3/ALPM shared banks */
   5994             fields[0] = BANK2_HASH_OFFSETf;
   5995             values[0] = 4;  /* CRC32 >> 4 */
   5996             fields[1] = BANK3_HASH_OFFSETf;
   5997             values[1] = 12; /* CRC32 >> 12 */
   5998             fields[2] = BANK4_HASH_OFFSETf;
   5999             values[2] = 20; /* CRC32 >> 20 */
   6000             fields[3] = BANK5_HASH_OFFSETf;
   6001             values[3] = 24; /* CRC32 >> 24 */
   6002             SOC_IF_ERROR_RETURN
   6003                 (soc_reg_fields32_modify(unit, SHARED_TABLE_HASH_CONTROLr,
   6004                                          REG_PORT_ANY, 4, fields, values));
   6005         }
   6006     }
   6007 #ifdef SOC_ROBUST_HASH
   6008     /* Robust Hash initialization */
   6009     if (soc_feature(unit, soc_feature_robust_hash)) {
   6010         uint32 value, seed = 0;
   6011 
   6012         if (NULL == ROBUSTHASH(unit)) {
   6013             ROBUSTHASH(unit) = sal_alloc(sizeof(soc_robust_hash_db_t),
   6014                                          "soc_robust_hash");
   6015             if (ROBUSTHASH(unit) == NULL) {
   6016                 return SOC_E_MEMORY;
   6017             }
   6018             sal_memset(ROBUSTHASH(unit), 0, sizeof(soc_robust_hash_db_t));
   6019         }
   6020 
   6021         /* Enable Robust hashing for VLAN_XLATE table and configure corresponding
   6022            remap and action tables */
   6023         if ((soc_property_get(unit, "robust_hash_disable_vlan", 0)) == 1) {
   6024             /* Disable robust hashing */
   6025             SOC_IF_ERROR_RETURN
   6026                 (READ_VLAN_XLATE_HASH_CONTROLr(unit, &value));
   6027             soc_reg_field_set(unit, VLAN_XLATE_HASH_CONTROLr, &value,
   6028                                         ROBUST_HASH_ENf, 0x0);
   6029             SOC_IF_ERROR_RETURN
   6030                 (WRITE_VLAN_XLATE_HASH_CONTROLr(unit, value));
   6031 
   6032             ROBUSTHASH(unit)->ing_xlate.enable = 0;
   6033         } else {
   6034             /* Enable robust hashing */
   6035             SOC_IF_ERROR_RETURN
   6036                 (READ_VLAN_XLATE_HASH_CONTROLr(unit, &value));
   6037             soc_reg_field_set(unit, VLAN_XLATE_HASH_CONTROLr, &value,
   6038                                         ROBUST_HASH_ENf, 0x1);
   6039             SOC_IF_ERROR_RETURN
   6040                 (WRITE_VLAN_XLATE_HASH_CONTROLr(unit, value));
   6041             ROBUSTHASH(unit)->ing_xlate.enable = 1;
   6042 
   6043             /* Fill action and remap tables with random data */
   6044             ROBUSTHASH(unit)->ing_xlate.remap_tab[0] = ING_VXLT_REMAP_TABLE_Am;
   6045             ROBUSTHASH(unit)->ing_xlate.remap_tab[1] = ING_VXLT_REMAP_TABLE_Bm;
   6046             ROBUSTHASH(unit)->ing_xlate.action_tab[0] = ING_VXLT_ACTION_TABLE_Am;
   6047             ROBUSTHASH(unit)->ing_xlate.action_tab[1] = ING_VXLT_ACTION_TABLE_Bm;
   6048 
   6049             seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_VLAN, 16777213);
   6050 
   6051             SOC_IF_ERROR_RETURN
   6052                 (soc_robust_hash_table_set(unit,
   6053                                            &(ROBUSTHASH(unit)->ing_xlate),
   6054                                            seed));
   6055         }
   6056 
   6057         /* Enable Robust hashing for EGR_VLAN_XLATE table and configure corresponding
   6058            remap and action tables */
   6059         if ((soc_property_get(unit, "robust_hash_disable_egress_vlan", 0)) == 1) {
   6060             /* Disable robust hashing */
   6061             SOC_IF_ERROR_RETURN
   6062                 (READ_EGR_VLAN_XLATE_HASH_CONTROLr(unit, &value));
   6063             soc_reg_field_set(unit, EGR_VLAN_XLATE_HASH_CONTROLr, &value,
   6064                                         ROBUST_HASH_ENf, 0x0);
   6065             SOC_IF_ERROR_RETURN
   6066                 (WRITE_EGR_VLAN_XLATE_HASH_CONTROLr(unit, value));
   6067 
   6068             ROBUSTHASH(unit)->egr_xlate.enable = 0;
   6069         } else {
   6070             /* Enable robust hashing */
   6071             SOC_IF_ERROR_RETURN
   6072                 (READ_EGR_VLAN_XLATE_HASH_CONTROLr(unit, &value));
   6073             soc_reg_field_set(unit, EGR_VLAN_XLATE_HASH_CONTROLr, &value,
   6074                                         ROBUST_HASH_ENf, 0x1);
   6075             SOC_IF_ERROR_RETURN
   6076                 (WRITE_EGR_VLAN_XLATE_HASH_CONTROLr(unit, value));
   6077 
   6078             ROBUSTHASH(unit)->egr_xlate.enable = 1;
   6079 
   6080             /* Fill action and remap tables with random data */
   6081             ROBUSTHASH(unit)->egr_xlate.remap_tab[0] = EGR_VXLT_REMAP_TABLE_Am;
   6082             ROBUSTHASH(unit)->egr_xlate.remap_tab[1] = EGR_VXLT_REMAP_TABLE_Bm;
   6083             ROBUSTHASH(unit)->egr_xlate.action_tab[0] = EGR_VXLT_ACTION_TABLE_Am;
   6084             ROBUSTHASH(unit)->egr_xlate.action_tab[1] = EGR_VXLT_ACTION_TABLE_Bm;
   6085 
   6086             seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_EGRESS_VLAN,
   6087                                     16777213);
   6088 
   6089             SOC_IF_ERROR_RETURN
   6090                 (soc_robust_hash_table_set(unit,
   6091                                            &(ROBUSTHASH(unit)->egr_xlate),
   6092                                            seed));
   6093         }
   6094 
   6095         /* Enable Robust hashing for MPLS_ENTRY table and configure corresponding
   6096            remap and action tables */
   6097         if ((soc_property_get(unit, "robust_hash_disable_mpls", 0)) == 1) {
   6098             /* Disable robust hashing */
   6099             SOC_IF_ERROR_RETURN
   6100                 (READ_MPLS_ENTRY_HASH_CONTROLr(unit, &value));
   6101             soc_reg_field_set(unit, MPLS_ENTRY_HASH_CONTROLr, &value,
   6102                     ROBUST_HASH_ENf, 0x0);
   6103             SOC_IF_ERROR_RETURN
   6104                 (WRITE_MPLS_ENTRY_HASH_CONTROLr(unit, value));
   6105             ROBUSTHASH(unit)->mpls_entry.enable = 0;
   6106         } else {
   6107             /* Enable robust hashing */
   6108             SOC_IF_ERROR_RETURN
   6109                 (READ_MPLS_ENTRY_HASH_CONTROLr(unit, &value));
   6110             soc_reg_field_set(unit, MPLS_ENTRY_HASH_CONTROLr, &value,
   6111                     ROBUST_HASH_ENf, 0x1);
   6112             SOC_IF_ERROR_RETURN
   6113                 (WRITE_MPLS_ENTRY_HASH_CONTROLr(unit, value));
   6114             ROBUSTHASH(unit)->mpls_entry.enable = 1;
   6115 
   6116             /* Fill action and remap tables with random data */
   6117             ROBUSTHASH(unit)->mpls_entry.remap_tab[0] = ING_MPLS_ENTRY_REMAP_TABLE_Am;
   6118             ROBUSTHASH(unit)->mpls_entry.remap_tab[1] = ING_MPLS_ENTRY_REMAP_TABLE_Bm;
   6119             ROBUSTHASH(unit)->mpls_entry.action_tab[0] = ING_MPLS_ENTRY_ACTION_TABLE_Am;
   6120             ROBUSTHASH(unit)->mpls_entry.action_tab[1] = ING_MPLS_ENTRY_ACTION_TABLE_Bm;
   6121 
   6122             seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_MPLS, 16777213);
   6123 
   6124             SOC_IF_ERROR_RETURN
   6125                 (soc_robust_hash_table_set(unit,
   6126                                            &(ROBUSTHASH(unit)->mpls_entry),
   6127                                            seed));
   6128        }
   6129     }
   6130 #endif /* SOC_ROBUST_HASH */
   6131 
   6132     return SOC_E_NONE;
   6133 }
   6134 
   6135 /* For a given logical port, return the OBM id and the lane number */
   6136 int
   6137 soc_tomahawk_port_obm_info_get(int unit, soc_port_t port,
   6138                                int *obm_id, int *lane)
   6139 {
   6140     soc_info_t *si;
   6141     soc_port_t phy_port;
   6142     int pipe, clport, port_block_base, ports_per_pblk;
   6143 
   6144     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
   6145         (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port))) {
   6146         return SOC_E_PARAM;
   6147     }
   6148     si = &SOC_INFO(unit);
   6149     pipe = si->port_pipe[port];
   6150     phy_port = si->port_l2p_mapping[port];
   6151     port_block_base = PORT_BLOCK_BASE_PORT(port);
   6152     clport = si->port_serdes[port];
   6153 
   6154 #ifdef BCM_TOMAHAWK3_SUPPORT
   6155     if (SOC_IS_TOMAHAWK3(unit)) {
   6156         port_block_base = SOC_TH3_PORT_BLOCK_BASE_PORT(port);
   6157         ports_per_pblk = _TH3_PORTS_PER_PBLK;
   6158         /* TH3 PIPE 2/3/6/7 has reversed (mirrored) OBM number*/
   6159         *obm_id = pipe & 0x10 ? 3 - (clport & 0x3) : clport & 0x3;
   6160     } else
   6161 #endif
   6162 #ifdef BCM_TOMAHAWK2_SUPPORT
   6163     if (SOC_IS_TOMAHAWK2(unit)) {
   6164         ports_per_pblk = _TH2_PBLKS_PER_PIPE;
   6165         *obm_id = clport & 0xF;
   6166     } else
   6167 #endif
   6168     {
   6169         ports_per_pblk = _TH_PBLKS_PER_PIPE;
   6170         /* obm number is reversed (mirrored) in odd pipe */
   6171         *obm_id = pipe & 1 ? 7 - (clport & 0x7) : clport & 0x7;
   6172     }
   6173 
   6174     *lane = (phy_port - port_block_base) % ports_per_pblk;
   6175 
   6176     if (*obm_id >= ports_per_pblk) {
   6177         return SOC_E_PARAM;
   6178     }
   6179 
   6180     return SOC_E_NONE;
   6181 }
   6182 
   6183 STATIC int
   6184 _soc_tomahawk_idb_init(int unit)
   6185 {
   6186 #define _TH_BYTES_PER_OBM_CELL    16
   6187 #define _TH_CELLS_PER_OBM         1012
   6188     soc_info_t *si;
   6189     _soc_tomahawk_tdm_t *tdm;
   6190     soc_reg_t reg;
   6191     soc_mem_t mem;
   6192     soc_field_t field;
   6193     int block_info_idx, pipe, clport, obm, lane;
   6194     int port, phy_port_base;
   6195     int lossless, i, count;
   6196     uint32 rval0, rval1, fval;
   6197     uint32 rval_port_cfg = 0, rval_max_usage_cfg = 0;
   6198     uint64 rval64;
   6199     int num_lanes, oversub_ratio_idx;
   6200     uint32 entry[SOC_MAX_MEM_WORDS];
   6201     static const struct _obm_setting_s {
   6202         int discard_limit;
   6203         int lossless_xoff;
   6204         int lossy_only_lossy_low_pri;
   6205         int port_xoff[3];          /* for oversub ratio 1.5, 1.8, and above */
   6206         int lossy_low_pri[3];      /* for oversub ratio 1.5, 1.8, and above */
   6207         int lossy_discard[3];      /* for oversub ratio 1.5, 1.8, and above */
   6208     } obm_settings[2][5] = {
   6209         /* LOSSY Settings */
   6210         { /* indexed by number of lanes used in the port */
   6211             { /* 0 - invalid  */ 0 },
   6212             { /* 1 lane */
   6213                 _TH_CELLS_PER_OBM / 4, 1023, 157,
   6214                 { 1023, 1023, 1023 }, /* port_xoff */
   6215                 { 157, 157, 157 }, /* lossy_low_pri */
   6216                 { 253, 253, 253 }  /* lossy_discard */
   6217             },
   6218             { /* 2 lanes */
   6219                 _TH_CELLS_PER_OBM / 2, 1023, 410,
   6220                 { 1023, 1023, 1023 }, /* port_xoff */
   6221                 { 410, 410, 410 }, /* lossy_low_pri */
   6222                 { 506, 506, 506 }  /* lossy_discard */
   6223             },
   6224             { /* 3 - invalid  */ 0 },
   6225             { /* 4 lanes */
   6226                 _TH_CELLS_PER_OBM, 1023, 916,
   6227                 { 1023, 1023, 1023 }, /* port_xoff */
   6228                 { 916, 916, 916 }, /* lossy_low_pri */
   6229                 { 1012, 1012, 1012 }  /* lossy_discard */
   6230             }
   6231         },
   6232         /* LOSSLESS Settings*/
   6233         { /* indexed by number of lanes used in the port */
   6234             { /* 0 - invalid  */ 0 },
   6235             { /* 1 lane */
   6236                 _TH_CELLS_PER_OBM / 4, 45, 157,
   6237                 { 129, 87, 67 }, /* port_xoff */
   6238                 { 100, 76, 56 }, /* lossy_low_pri */
   6239                 { 196, 152, 112 }  /* lossy_discard */
   6240             },
   6241             { /* 2 lanes */
   6242                 _TH_CELLS_PER_OBM / 2, 108, 410,
   6243                 { 312, 248, 215 }, /* port_xoff */
   6244                 { 100, 100, 100 }, /* lossy_low_pri */
   6245                 { 196, 196, 196 }  /* lossy_discard */
   6246             },
   6247             { /* 3 - invalid  */ 0 },
   6248             { /* 4 lanes */
   6249                 _TH_CELLS_PER_OBM, 258, 916,
   6250                 { 682, 572, 517 }, /* port_xoff */
   6251                 { 100, 100, 100 }, /* lossy_low_pri */
   6252                 { 196, 196, 196 }  /* lossy_discard */
   6253             }
   6254         }
   6255     };
   6256     static const soc_reg_t obm_ctrl_regs[] = {
   6257         IDB_OBM0_CONTROLr, IDB_OBM1_CONTROLr,
   6258         IDB_OBM2_CONTROLr, IDB_OBM3_CONTROLr,
   6259         IDB_OBM4_CONTROLr, IDB_OBM5_CONTROLr,
   6260         IDB_OBM6_CONTROLr, IDB_OBM7_CONTROLr
   6261     };
   6262     static const soc_reg_t obm_ca_ctrl_regs[] = {
   6263         IDB_OBM0_CA_CONTROLr, IDB_OBM1_CA_CONTROLr,
   6264         IDB_OBM2_CA_CONTROLr, IDB_OBM3_CA_CONTROLr,
   6265         IDB_OBM4_CA_CONTROLr, IDB_OBM5_CA_CONTROLr,
   6266         IDB_OBM6_CA_CONTROLr, IDB_OBM7_CA_CONTROLr
   6267     };
   6268     static const soc_reg_t obm_thresh_regs[] = {
   6269         IDB_OBM0_THRESHOLDr, IDB_OBM1_THRESHOLDr,
   6270         IDB_OBM2_THRESHOLDr, IDB_OBM3_THRESHOLDr,
   6271         IDB_OBM4_THRESHOLDr, IDB_OBM5_THRESHOLDr,
   6272         IDB_OBM6_THRESHOLDr, IDB_OBM7_THRESHOLDr
   6273     };
   6274     static const soc_reg_t obm_fc_thresh_regs[] = {
   6275         IDB_OBM0_FC_THRESHOLDr, IDB_OBM1_FC_THRESHOLDr,
   6276         IDB_OBM2_FC_THRESHOLDr, IDB_OBM3_FC_THRESHOLDr,
   6277         IDB_OBM4_FC_THRESHOLDr, IDB_OBM5_FC_THRESHOLDr,
   6278         IDB_OBM6_FC_THRESHOLDr, IDB_OBM7_FC_THRESHOLDr
   6279     };
   6280     static const soc_reg_t obm_shared_regs[] = {
   6281         IDB_OBM0_SHARED_CONFIGr, IDB_OBM1_SHARED_CONFIGr,
   6282         IDB_OBM2_SHARED_CONFIGr, IDB_OBM3_SHARED_CONFIGr,
   6283         IDB_OBM4_SHARED_CONFIGr, IDB_OBM5_SHARED_CONFIGr,
   6284         IDB_OBM6_SHARED_CONFIGr, IDB_OBM7_SHARED_CONFIGr
   6285     };
   6286     static const soc_reg_t obm_max_usage_regs[] = {
   6287         IDB_OBM0_MAX_USAGE_SELECTr, IDB_OBM1_MAX_USAGE_SELECTr,
   6288         IDB_OBM2_MAX_USAGE_SELECTr, IDB_OBM3_MAX_USAGE_SELECTr,
   6289         IDB_OBM4_MAX_USAGE_SELECTr, IDB_OBM5_MAX_USAGE_SELECTr,
   6290         IDB_OBM6_MAX_USAGE_SELECTr, IDB_OBM7_MAX_USAGE_SELECTr
   6291     };
   6292     static const soc_reg_t obm_port_config_regs[] = {
   6293         IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr,
   6294         IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr,
   6295         IDB_OBM4_PORT_CONFIGr, IDB_OBM5_PORT_CONFIGr,
   6296         IDB_OBM6_PORT_CONFIGr, IDB_OBM7_PORT_CONFIGr
   6297     };
   6298     static const soc_reg_t obm_fc_config_regs[] = {
   6299         IDB_OBM0_FLOW_CONTROL_CONFIGr, IDB_OBM1_FLOW_CONTROL_CONFIGr,
   6300         IDB_OBM2_FLOW_CONTROL_CONFIGr, IDB_OBM3_FLOW_CONTROL_CONFIGr,
   6301         IDB_OBM4_FLOW_CONTROL_CONFIGr, IDB_OBM5_FLOW_CONTROL_CONFIGr,
   6302         IDB_OBM6_FLOW_CONTROL_CONFIGr, IDB_OBM7_FLOW_CONTROL_CONFIGr
   6303     };
   6304     static const soc_field_t obm_bypass_fields[] = {
   6305         PORT0_BYPASS_ENABLEf, PORT1_BYPASS_ENABLEf,
   6306         PORT2_BYPASS_ENABLEf, PORT3_BYPASS_ENABLEf
   6307     };
   6308     static const soc_field_t obm_oversub_fields[] = {
   6309         PORT0_OVERSUB_ENABLEf, PORT1_OVERSUB_ENABLEf,
   6310         PORT2_OVERSUB_ENABLEf, PORT3_OVERSUB_ENABLEf
   6311     };
   6312     static const soc_mem_t obm_pri_map_mem[][4] = {
   6313         {IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m,
   6314          IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m
   6315         },
   6316         {IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m,
   6317          IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m
   6318         },
   6319         {IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m,
   6320          IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m
   6321         },
   6322         {IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m,
   6323          IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m
   6324         },
   6325         {IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m,
   6326          IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m
   6327         },
   6328         {IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m,
   6329          IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m
   6330         },
   6331         {IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m,
   6332          IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m
   6333         },
   6334         {IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m,
   6335          IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m
   6336         },
   6337     };
   6338     static const soc_field_t obm_ob_pri_fields[] = {
   6339         OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf,
   6340         OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
   6341         OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf,
   6342         OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf,
   6343         OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf,
   6344         OFFSET15_OB_PRIORITYf
   6345     };
   6346     static const int hw_mode_values[SOC_TH_PORT_RATIO_COUNT] = {
   6347         0, 1, 1, 1, 3, 5, 4, 6, 2
   6348     };
   6349 
   6350     si = &SOC_INFO(unit);
   6351     tdm = SOC_CONTROL(unit)->tdm_info;
   6352 
   6353     if (SOC_IS_TOMAHAWKPLUS(unit)) {
   6354         lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 
   6355                                     SOC_TH_MMU_LOSSLESS_DEFAULT_DISABLE);
   6356     } else {
   6357         lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 
   6358                                     SOC_TH_MMU_LOSSLESS_DEFAULT_ENABLE);
   6359     }
   6360 
   6361     rval_port_cfg = 0;
   6362     reg = SOC_REG_UNIQUE_ACC(unit, obm_port_config_regs[0])[0];
   6363     soc_reg_field_set(unit, reg, &rval_port_cfg, PORT_PRIf, 2);
   6364 
   6365     rval_max_usage_cfg = 0;
   6366     reg = SOC_REG_UNIQUE_ACC(unit, obm_max_usage_regs[0])[0];
   6367     soc_reg_field_set(unit, reg, &rval_max_usage_cfg, PRIORITY_SELECTf, 2);
   6368 
   6369     sal_memset(entry, 0, sizeof(idb_obm0_pri_map_port0_entry_t));
   6370     mem = SOC_MEM_UNIQUE_ACC(unit, obm_pri_map_mem[0][0])[0];
   6371 
   6372     count = COUNTOF(obm_ob_pri_fields);
   6373     for (i = 0; i < count; i++) {
   6374         soc_mem_field32_set(unit, mem, entry, obm_ob_pri_fields[i], 2);
   6375     }
   6376 
   6377     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   6378         port = SOC_BLOCK_PORT(unit, block_info_idx);
   6379         phy_port_base = PORT_BLOCK_BASE_PORT(port);
   6380         pipe = si->port_pipe[port];
   6381         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   6382         /* obm number is reversed (mirrored) in odd pipe */
   6383         obm = pipe & 1 ? 7 - (clport & 0x7) : clport & 0x7;
   6384 
   6385         /* Set cell assembly mode then toggle reset to send initial credit
   6386          * to EP */
   6387         reg = SOC_REG_UNIQUE_ACC(unit, obm_ca_ctrl_regs[obm])[pipe];
   6388         rval0 = 0;
   6389         soc_reg_field_set(unit, reg, &rval0, PORT_MODEf,
   6390                           hw_mode_values[tdm->port_ratio[clport]]);
   6391         rval1 = rval0;
   6392         soc_reg_field_set(unit, reg, &rval0, PORT0_RESETf, 1);
   6393         soc_reg_field_set(unit, reg, &rval0, PORT1_RESETf, 1);
   6394         soc_reg_field_set(unit, reg, &rval0, PORT2_RESETf, 1);
   6395         soc_reg_field_set(unit, reg, &rval0, PORT3_RESETf, 1);
   6396         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   6397         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval1));
   6398 
   6399         /* Enable oversub */
   6400         reg = SOC_REG_UNIQUE_ACC(unit, obm_ctrl_regs[obm])[pipe];
   6401         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval0));
   6402         for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) {
   6403             if (si->port_p2l_mapping[phy_port_base + lane] == -1) {
   6404                 continue;
   6405             }
   6406             field = obm_bypass_fields[lane];
   6407             soc_reg_field_set(unit, reg, &rval0, field, 1);
   6408             field = obm_oversub_fields[lane];
   6409             soc_reg_field_set(unit, reg, &rval0, field, 1);
   6410         }
   6411 
   6412         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   6413         if (!SOC_PBMP_MEMBER(si->oversub_pbm, port)) {
   6414             continue;
   6415         }
   6416 
   6417         /* Configure shared config */
   6418         reg = SOC_REG_UNIQUE_ACC(unit, obm_shared_regs[obm])[pipe];
   6419         SOC_IF_ERROR_RETURN
   6420             (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6421         soc_reg64_field32_set(unit, reg, &rval64, DISCARD_THRESHOLDf, 1023);
   6422         soc_reg64_field32_set(unit, reg, &rval64, SOP_THRESHOLDf, 1023);
   6423         soc_reg64_field32_set(unit, reg, &rval64, SOP_DISCARD_MODEf, 1);
   6424         SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6425 
   6426         if (lossless) {
   6427             if (tdm->ovs_ratio_x1000[pipe] >= 1800) { /* ratio >= 1.8 */
   6428                 oversub_ratio_idx = 2;
   6429             } else if (tdm->ovs_ratio_x1000[pipe] >= 1500) { /* ratio >= 1.5 */
   6430                 oversub_ratio_idx = 1;
   6431             } else {
   6432                 oversub_ratio_idx = 0;
   6433             }
   6434 
   6435             for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) {
   6436                 port = si->port_p2l_mapping[phy_port_base + lane];
   6437                 if (port == -1) {
   6438                     continue;
   6439                 }
   6440                 num_lanes = si->port_num_lanes[port];
   6441 
   6442                 /* Configure threshold */
   6443                 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe];
   6444                 SOC_IF_ERROR_RETURN
   6445                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6446                 fval = obm_settings[1][num_lanes].discard_limit;
   6447                 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf, fval);
   6448                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf,
   6449                                       1023);
   6450                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf,
   6451                                       1023);
   6452                 fval = obm_settings[1][num_lanes].lossy_low_pri[oversub_ratio_idx];
   6453                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf, fval);
   6454                 fval = obm_settings[1][num_lanes].lossy_discard[oversub_ratio_idx];
   6455                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf, fval);
   6456                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_MINf, 0);
   6457                 SOC_IF_ERROR_RETURN
   6458                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6459 
   6460                 /* Configure flow control threshold */
   6461                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe];
   6462                 SOC_IF_ERROR_RETURN
   6463                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6464                 fval = obm_settings[1][num_lanes].port_xoff[oversub_ratio_idx];
   6465                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf, fval);
   6466                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf, fval - 10);
   6467                 fval = obm_settings[1][num_lanes].lossless_xoff;
   6468                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf,
   6469                                       fval);
   6470                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf,
   6471                                       fval);
   6472                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf,
   6473                                       fval - 10);
   6474                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf,
   6475                                       fval - 10);
   6476                 SOC_IF_ERROR_RETURN
   6477                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6478 
   6479                 /* Configure flow control config */
   6480                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_config_regs[obm])[pipe];
   6481                 SOC_IF_ERROR_RETURN
   6482                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6483                 soc_reg64_field32_set(unit, reg, &rval64, PORT_FC_ENf, 1);
   6484                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_FC_ENf, 1);
   6485                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_FC_ENf, 1);
   6486                 soc_reg64_field32_set(unit, reg, &rval64,
   6487                                       LOSSLESS0_PRIORITY_PROFILEf, 0xff);
   6488                 soc_reg64_field32_set(unit, reg, &rval64,
   6489                                       LOSSLESS1_PRIORITY_PROFILEf, 0xff);
   6490                 SOC_IF_ERROR_RETURN
   6491                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6492 
   6493                 /* OBM Port config */
   6494                 reg = SOC_REG_UNIQUE_ACC(unit, obm_port_config_regs[obm])[pipe];
   6495                 SOC_IF_ERROR_RETURN
   6496                     (soc_reg32_set(unit, reg, REG_PORT_ANY, lane,
   6497                                    rval_port_cfg));
   6498 
   6499                 mem = SOC_MEM_UNIQUE_ACC
   6500                         (unit, obm_pri_map_mem[obm][lane])[pipe];
   6501                 SOC_IF_ERROR_RETURN
   6502                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, entry));
   6503             }
   6504 
   6505             reg = SOC_REG_UNIQUE_ACC(unit, obm_max_usage_regs[obm])[pipe];
   6506             SOC_IF_ERROR_RETURN
   6507                 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0,
   6508                                rval_max_usage_cfg));
   6509 
   6510         } else { /* lossy */
   6511             for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) {
   6512                 port = si->port_p2l_mapping[phy_port_base + lane];
   6513                 if (port == -1) {
   6514                     continue;
   6515                 }
   6516                 num_lanes = si->port_num_lanes[port];
   6517 
   6518                 /* Configure threshold */
   6519                 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe];
   6520                 SOC_IF_ERROR_RETURN
   6521                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6522                 fval = obm_settings[0][num_lanes].discard_limit;
   6523                 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf, fval);
   6524                 /* same as DISCARD_LIMIT setting */
   6525                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf, fval);
   6526                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf,
   6527                                       1023);
   6528                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf,
   6529                                       1023);
   6530                 fval = obm_settings[0][num_lanes].lossy_only_lossy_low_pri;
   6531                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf, fval);
   6532                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_MINf, 0);
   6533                 SOC_IF_ERROR_RETURN
   6534                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6535 
   6536                 /* Configure flow control threshold */
   6537                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe];
   6538                 SOC_IF_ERROR_RETURN
   6539                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   6540                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf, 1023);
   6541                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf, 1023);
   6542                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf,
   6543                                       1023);
   6544                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf,
   6545                                       1023);
   6546                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf, 1023);
   6547                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf, 1023);
   6548                 SOC_IF_ERROR_RETURN
   6549                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
   6550             }
   6551         }
   6552     }
   6553 
   6554     /* Toggle cpu port cell assembly reset to send initial credit to EP */
   6555     reg = IDB_CA_CPU_CONTROLr;
   6556     rval0 = 0;
   6557     soc_reg_field_set(unit, reg, &rval0, PORT_RESETf, 1);
   6558     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   6559     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 0));
   6560 
   6561     /* Toggle loopback port cell assembly reset to send initial credit to EP */
   6562     reg = IDB_CA_LPBK_CONTROLr;
   6563     rval0 = 0;
   6564     soc_reg_field_set(unit, reg, &rval0, PORT_RESETf, 1);
   6565     PBMP_LB_ITER(unit, port) {
   6566         reg = SOC_REG_UNIQUE_ACC(unit, IDB_CA_LPBK_CONTROLr)
   6567             [si->port_pipe[port]];
   6568         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0));
   6569         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 0));
   6570     }
   6571 
   6572     return SOC_E_NONE;
   6573 }
   6574 
   6575 extern int
   6576 (*_phy_tsce_firmware_set_helper[SOC_MAX_NUM_DEVICES])(int, int, uint8 *, int);
   6577 extern int
   6578 (*_phy_tscf_firmware_set_helper[SOC_MAX_NUM_DEVICES])(int, int, uint8 *, int);
   6579 
   6580 STATIC int
   6581 _soc_tomahawk_tscx_firmware_set(int unit, int port, uint8 *array, int datalen)
   6582 {
   6583     soc_mem_t mem = IS_CL_PORT(unit, port) ?
   6584                     CLPORT_WC_UCMEM_DATAm : XLPORT_WC_UCMEM_DATAm;
   6585     soc_reg_t reg = IS_CL_PORT(unit, port) ?
   6586                     CLPORT_WC_UCMEM_CTRLr : XLPORT_WC_UCMEM_CTRLr;
   6587 
   6588     return soc_warpcore_firmware_set(unit, port, array, datalen, 0, mem, reg);
   6589 }
   6590 
   6591 #define TSC_REG_ADDR_TSCID_SET(_phy_reg, _phyad)    \
   6592                             ((_phy_reg) |= ((_phyad) & 0x1f) << 19)
   6593 
   6594 STATIC int
   6595 _soc_tomahawk_mdio_addr_to_port(uint32 phy_addr)
   6596 {
   6597     int bus, offset;
   6598 
   6599     /* Must be internal MDIO address */
   6600     if ((phy_addr & 0x80) == 0) {
   6601         return 0;
   6602     }
   6603 
   6604     /*
   6605      * Internal phy address:
   6606      * bus 0 phy 1 to 24 are mapped to Physical port 1 to 24
   6607      * bus 1 phy 1 to 16 are mapped to Physical port 25 to 40
   6608      * bus 2 phy 1 to 24 are mapped to Physical port 41 to 64
   6609      * bus 3 phy 1 to 24 are mapped to Physical port 85 to 88
   6610      * bus 4 phy 1 to 16 are mapped to Physical port 89 to 104
   6611      * bus 5 phy 1 to 24 are mapped to Physical port 105 to 128
   6612      * bus 6 phy 1 is mapped to Physical port 129 and
   6613      *       phy 3 is mapped to Physical port 131
   6614      */
   6615     bus = PHY_ID_BUS_NUM(phy_addr);
   6616     if (bus > 6) {
   6617         return 0;
   6618     }
   6619     switch (bus) {
   6620     case 0: offset = 0;
   6621         break;
   6622     case 1: offset = 24;
   6623         break;
   6624     case 2: offset = 40;
   6625         break;
   6626     case 3: offset = 64;
   6627         break;
   6628     case 4: offset = 88;
   6629         break;
   6630     case 5: offset = 104;
   6631         break;
   6632     case 6: offset = 128;
   6633         if ((phy_addr & 0x1f) == 2 || (phy_addr & 0x1f) > 3) {
   6634             return 0;
   6635         }
   6636         break;
   6637     default:
   6638         return 0;
   6639     }
   6640 
   6641     return (phy_addr & 0x1f) + offset;
   6642 }
   6643 
   6644 STATIC int
   6645 _soc_tomahawk_tscx_reg_read(int unit, uint32 phy_addr,
   6646                             uint32 phy_reg, uint32 *phy_data)
   6647 {
   6648     int rv, blk, port;
   6649     int phy_port = _soc_tomahawk_mdio_addr_to_port(phy_addr);
   6650 
   6651 #ifdef BCM_TOMAHAWK2_SUPPORT
   6652     if (SOC_IS_TOMAHAWK2(unit)) {
   6653         phy_port = soc_tomahawk2_mdio_addr_to_port(phy_addr);
   6654     }
   6655 #endif
   6656 
   6657     port = SOC_INFO(unit).port_p2l_mapping[phy_port];
   6658     blk = SOC_PORT_BLOCK(unit, phy_port);
   6659     LOG_INFO(BSL_LS_SOC_MII,
   6660              (BSL_META_U(unit,
   6661                          "soc_tomahawk_tscx_reg_read[%d]: %d/%d/%d/%d\n"),
   6662               unit, phy_addr, phy_port, port, blk));
   6663     TSC_REG_ADDR_TSCID_SET(phy_reg, phy_addr);
   6664     rv = soc_sbus_tsc_reg_read(unit, port, blk, phy_addr,
   6665                                phy_reg, phy_data);
   6666     return rv;
   6667 }
   6668 
   6669 STATIC int
   6670 _soc_tomahawk_tscx_reg_write(int unit, uint32 phy_addr,
   6671                              uint32 phy_reg, uint32 phy_data)
   6672 {
   6673     int rv, blk, port;
   6674     int phy_port = _soc_tomahawk_mdio_addr_to_port(phy_addr);
   6675 
   6676 #ifdef BCM_TOMAHAWK2_SUPPORT
   6677     if (SOC_IS_TOMAHAWK2(unit)) {
   6678         phy_port = soc_tomahawk2_mdio_addr_to_port(phy_addr);
   6679     }
   6680 #endif
   6681 
   6682     port = SOC_INFO(unit).port_p2l_mapping[phy_port];
   6683     blk = SOC_PORT_BLOCK(unit, phy_port);
   6684     LOG_INFO(BSL_LS_SOC_MII,
   6685              (BSL_META_U(unit,
   6686                          "soc_tomahawk_tscx_reg_write[%d]: %d/%d/%d/%d\n"),
   6687               unit, phy_addr, phy_port, port, blk));
   6688     TSC_REG_ADDR_TSCID_SET(phy_reg, phy_addr);
   6689     rv = soc_sbus_tsc_reg_write(unit, port, blk, phy_addr,
   6690                                 phy_reg, phy_data);
   6691     return rv;
   6692 }
   6693 
   6694 STATIC int
   6695 _soc_th_ledup_init(int unit)
   6696 {
   6697     uint32 rval = 0;
   6698     int ix, pval1, pval2, pval_size;
   6699 
   6700     typedef struct led_remap_s {
   6701         uint32 reg_addr;
   6702         uint32 port0;
   6703         uint32 port1;
   6704         uint32 port2;
   6705         uint32 port3;
   6706     } led_remap_t;
   6707 
   6708     led_remap_t led0_remap[] = {
   6709         { CMIC_LEDUP0_PORT_ORDER_REMAP_0_3r,
   6710          REMAP_PORT_0f, REMAP_PORT_1f, REMAP_PORT_2f, REMAP_PORT_3f },
   6711         { CMIC_LEDUP0_PORT_ORDER_REMAP_4_7r,
   6712          REMAP_PORT_4f, REMAP_PORT_5f, REMAP_PORT_6f, REMAP_PORT_7f },
   6713         { CMIC_LEDUP0_PORT_ORDER_REMAP_8_11r,
   6714          REMAP_PORT_8f, REMAP_PORT_9f, REMAP_PORT_10f, REMAP_PORT_11f },
   6715         { CMIC_LEDUP0_PORT_ORDER_REMAP_12_15r,
   6716          REMAP_PORT_12f, REMAP_PORT_13f, REMAP_PORT_14f, REMAP_PORT_15f },
   6717         { CMIC_LEDUP0_PORT_ORDER_REMAP_16_19r,
   6718          REMAP_PORT_16f, REMAP_PORT_17f, REMAP_PORT_18f, REMAP_PORT_19f },
   6719         { CMIC_LEDUP0_PORT_ORDER_REMAP_20_23r,
   6720          REMAP_PORT_20f, REMAP_PORT_21f, REMAP_PORT_22f, REMAP_PORT_23f },
   6721         { CMIC_LEDUP0_PORT_ORDER_REMAP_24_27r,
   6722          REMAP_PORT_24f, REMAP_PORT_25f, REMAP_PORT_26f, REMAP_PORT_27f },
   6723         { CMIC_LEDUP0_PORT_ORDER_REMAP_28_31r,
   6724          REMAP_PORT_28f, REMAP_PORT_29f, REMAP_PORT_30f, REMAP_PORT_31f },
   6725         { CMIC_LEDUP0_PORT_ORDER_REMAP_32_35r,
   6726          REMAP_PORT_32f, REMAP_PORT_33f, REMAP_PORT_34f, REMAP_PORT_35f },
   6727         { CMIC_LEDUP0_PORT_ORDER_REMAP_36_39r,
   6728          REMAP_PORT_36f, REMAP_PORT_37f, REMAP_PORT_38f, REMAP_PORT_39f },
   6729         { CMIC_LEDUP0_PORT_ORDER_REMAP_40_43r,
   6730          REMAP_PORT_40f, REMAP_PORT_41f, REMAP_PORT_42f, REMAP_PORT_43f },
   6731         { CMIC_LEDUP0_PORT_ORDER_REMAP_44_47r,
   6732          REMAP_PORT_44f, REMAP_PORT_45f, REMAP_PORT_46f, REMAP_PORT_47f },
   6733         { CMIC_LEDUP0_PORT_ORDER_REMAP_48_51r,
   6734          REMAP_PORT_48f, REMAP_PORT_49f, REMAP_PORT_50f, REMAP_PORT_51f },
   6735         { CMIC_LEDUP0_PORT_ORDER_REMAP_52_55r,
   6736          REMAP_PORT_52f, REMAP_PORT_53f, REMAP_PORT_54f, REMAP_PORT_55f },
   6737         { CMIC_LEDUP0_PORT_ORDER_REMAP_56_59r,
   6738          REMAP_PORT_56f, REMAP_PORT_57f, REMAP_PORT_58f, REMAP_PORT_59f },
   6739         { CMIC_LEDUP0_PORT_ORDER_REMAP_60_63r,
   6740          REMAP_PORT_60f, REMAP_PORT_61f, REMAP_PORT_62f, REMAP_PORT_63f }
   6741     };
   6742 
   6743     led_remap_t led1_remap[] = {
   6744         { CMIC_LEDUP1_PORT_ORDER_REMAP_0_3r,
   6745          REMAP_PORT_0f, REMAP_PORT_1f, REMAP_PORT_2f, REMAP_PORT_3f },
   6746         { CMIC_LEDUP1_PORT_ORDER_REMAP_4_7r,
   6747          REMAP_PORT_4f, REMAP_PORT_5f, REMAP_PORT_6f, REMAP_PORT_7f },
   6748         { CMIC_LEDUP1_PORT_ORDER_REMAP_8_11r,
   6749          REMAP_PORT_8f, REMAP_PORT_9f, REMAP_PORT_10f, REMAP_PORT_11f },
   6750         { CMIC_LEDUP1_PORT_ORDER_REMAP_12_15r,
   6751          REMAP_PORT_12f, REMAP_PORT_13f, REMAP_PORT_14f, REMAP_PORT_15f },
   6752         { CMIC_LEDUP1_PORT_ORDER_REMAP_16_19r,
   6753          REMAP_PORT_16f, REMAP_PORT_17f, REMAP_PORT_18f, REMAP_PORT_19f },
   6754         { CMIC_LEDUP1_PORT_ORDER_REMAP_20_23r,
   6755          REMAP_PORT_20f, REMAP_PORT_21f, REMAP_PORT_22f, REMAP_PORT_23f },
   6756         { CMIC_LEDUP1_PORT_ORDER_REMAP_24_27r,
   6757          REMAP_PORT_24f, REMAP_PORT_25f, REMAP_PORT_26f, REMAP_PORT_27f },
   6758         { CMIC_LEDUP1_PORT_ORDER_REMAP_28_31r,
   6759          REMAP_PORT_28f, REMAP_PORT_29f, REMAP_PORT_30f, REMAP_PORT_31f },
   6760         { CMIC_LEDUP1_PORT_ORDER_REMAP_32_35r,
   6761          REMAP_PORT_32f, REMAP_PORT_33f, REMAP_PORT_34f, REMAP_PORT_35f },
   6762         { CMIC_LEDUP1_PORT_ORDER_REMAP_36_39r,
   6763          REMAP_PORT_36f, REMAP_PORT_37f, REMAP_PORT_38f, REMAP_PORT_39f },
   6764         { CMIC_LEDUP1_PORT_ORDER_REMAP_40_43r,
   6765          REMAP_PORT_40f, REMAP_PORT_41f, REMAP_PORT_42f, REMAP_PORT_43f },
   6766         { CMIC_LEDUP1_PORT_ORDER_REMAP_44_47r,
   6767          REMAP_PORT_44f, REMAP_PORT_45f, REMAP_PORT_46f, REMAP_PORT_47f },
   6768         { CMIC_LEDUP1_PORT_ORDER_REMAP_48_51r,
   6769          REMAP_PORT_48f, REMAP_PORT_49f, REMAP_PORT_50f, REMAP_PORT_51f },
   6770         { CMIC_LEDUP1_PORT_ORDER_REMAP_52_55r,
   6771          REMAP_PORT_52f, REMAP_PORT_53f, REMAP_PORT_54f, REMAP_PORT_55f },
   6772         { CMIC_LEDUP1_PORT_ORDER_REMAP_56_59r,
   6773          REMAP_PORT_56f, REMAP_PORT_57f, REMAP_PORT_58f, REMAP_PORT_59f },
   6774         { CMIC_LEDUP1_PORT_ORDER_REMAP_60_63r,
   6775          REMAP_PORT_60f, REMAP_PORT_61f, REMAP_PORT_62f, REMAP_PORT_63f }
   6776     };
   6777 
   6778     led_remap_t led2_remap[] = {
   6779         { CMIC_LEDUP2_PORT_ORDER_REMAP_0_3r,
   6780          REMAP_PORT_0f, REMAP_PORT_1f, REMAP_PORT_2f, REMAP_PORT_3f },
   6781         { CMIC_LEDUP2_PORT_ORDER_REMAP_4_7r,
   6782          REMAP_PORT_4f, REMAP_PORT_5f, REMAP_PORT_6f, REMAP_PORT_7f },
   6783         { CMIC_LEDUP2_PORT_ORDER_REMAP_8_11r,
   6784          REMAP_PORT_8f, REMAP_PORT_9f, REMAP_PORT_10f, REMAP_PORT_11f },
   6785         { CMIC_LEDUP2_PORT_ORDER_REMAP_12_15r,
   6786          REMAP_PORT_12f, REMAP_PORT_13f, REMAP_PORT_14f, REMAP_PORT_15f },
   6787         { CMIC_LEDUP2_PORT_ORDER_REMAP_16_19r,
   6788          REMAP_PORT_16f, REMAP_PORT_17f, REMAP_PORT_18f, REMAP_PORT_19f },
   6789         { CMIC_LEDUP2_PORT_ORDER_REMAP_20_23r,
   6790          REMAP_PORT_20f, REMAP_PORT_21f, REMAP_PORT_22f, REMAP_PORT_23f },
   6791         { CMIC_LEDUP2_PORT_ORDER_REMAP_24_27r,
   6792          REMAP_PORT_24f, REMAP_PORT_25f, REMAP_PORT_26f, REMAP_PORT_27f },
   6793         { CMIC_LEDUP2_PORT_ORDER_REMAP_28_31r,
   6794          REMAP_PORT_28f, REMAP_PORT_29f, REMAP_PORT_30f, REMAP_PORT_31f },
   6795         { CMIC_LEDUP2_PORT_ORDER_REMAP_32_35r,
   6796          REMAP_PORT_32f, REMAP_PORT_33f, REMAP_PORT_34f, REMAP_PORT_35f },
   6797         { CMIC_LEDUP2_PORT_ORDER_REMAP_36_39r,
   6798          REMAP_PORT_36f, REMAP_PORT_37f, REMAP_PORT_38f, REMAP_PORT_39f },
   6799         { CMIC_LEDUP2_PORT_ORDER_REMAP_40_43r,
   6800          REMAP_PORT_40f, REMAP_PORT_41f, REMAP_PORT_42f, REMAP_PORT_43f },
   6801         { CMIC_LEDUP2_PORT_ORDER_REMAP_44_47r,
   6802          REMAP_PORT_44f, REMAP_PORT_45f, REMAP_PORT_46f, REMAP_PORT_47f },
   6803         { CMIC_LEDUP2_PORT_ORDER_REMAP_48_51r,
   6804          REMAP_PORT_48f, REMAP_PORT_49f, REMAP_PORT_50f, REMAP_PORT_51f },
   6805         { CMIC_LEDUP2_PORT_ORDER_REMAP_52_55r,
   6806          REMAP_PORT_52f, REMAP_PORT_53f, REMAP_PORT_54f, REMAP_PORT_55f },
   6807         { CMIC_LEDUP2_PORT_ORDER_REMAP_56_59r,
   6808          REMAP_PORT_56f, REMAP_PORT_57f, REMAP_PORT_58f, REMAP_PORT_59f },
   6809         { CMIC_LEDUP2_PORT_ORDER_REMAP_60_63r,
   6810          REMAP_PORT_60f, REMAP_PORT_61f, REMAP_PORT_62f, REMAP_PORT_63f }
   6811     };
   6812 
   6813 
   6814     pval_size = COUNTOF(led0_remap);
   6815     pval2 = (pval_size >> 1) - 1;
   6816 
   6817     /* Configure LED-0 remap register settings.
   6818      * LED-0 chain provides port status for tile0 (ports 1-32)
   6819      * and tile 3 (ports 97-128).
   6820      * Scan chain order: 32, 31, ...., 1, 128, 127, ...., 97
   6821      * LED port status for port 32 arrives first at the CMIC block and
   6822      * port 97's LED status arrives last.
   6823      */
   6824     for (ix = 0; ix < pval_size ; ix++) {
   6825         if (ix == pval_size >> 1) {
   6826             pval2 = pval_size -1;
   6827         }
   6828 
   6829         pval1 = ix << 2;
   6830 
   6831         rval = 0;
   6832         soc_reg_field_set(unit, led0_remap[pval2].reg_addr, &rval,
   6833                 led0_remap[pval2].port3, pval1);
   6834         soc_reg_field_set(unit, led0_remap[pval2].reg_addr, &rval,
   6835                 led0_remap[pval2].port2, pval1 + 1);
   6836         soc_reg_field_set(unit, led0_remap[pval2].reg_addr, &rval,
   6837                 led0_remap[pval2].port1, pval1 + 2);
   6838         soc_reg_field_set(unit, led0_remap[pval2].reg_addr, &rval,
   6839                 led0_remap[pval2].port0, pval1 + 3);
   6840         soc_pci_write(unit, soc_reg_addr(unit,
   6841                       led0_remap[pval2].reg_addr, REG_PORT_ANY, 0), rval);
   6842         pval2--;
   6843     }
   6844 
   6845     /* Configure LED-1 remap register settings.
   6846      * LED-1 chain provides port status for tile1 (ports 33-64)
   6847      * and tile 2 (ports 65-96).
   6848      * Scan chain order: 33, 34, 35, ...., 96
   6849      * LED port status for port 33 arrives first at the CMIC block and
   6850      * port 96's LED status arrives last.
   6851      */
   6852     for (ix = 0; ix < pval_size ; ix++) {
   6853         pval1 = ix << 2;
   6854 
   6855         rval = 0;
   6856         soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval,
   6857                 led1_remap[ix].port3, pval1);
   6858         soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval,
   6859                 led1_remap[ix].port2, pval1 + 1);
   6860         soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval,
   6861                 led1_remap[ix].port1, pval1 + 2);
   6862         soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval,
   6863                 led1_remap[ix].port0, pval1 + 3);
   6864         soc_pci_write(unit, soc_reg_addr(unit,
   6865                       led1_remap[ix].reg_addr, REG_PORT_ANY, 0), rval);
   6866     }
   6867 
   6868     /* Configure LED-2 remap register settings.
   6869      * LED-2 chain provides port status for management ports (129-132).
   6870      * Scan chain port order is - 132 (unused), 131, 130 (unused), 129.
   6871      * Unused remapping port registers are programmed to a larger value.
   6872      */
   6873     for (ix = 0; ix < pval_size ; ix++) {
   6874         rval = 0;
   6875         soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval,
   6876                 led2_remap[ix].port0, 0x3F);
   6877         soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval,
   6878                 led2_remap[ix].port1, 0x3F);
   6879         soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval,
   6880                 led2_remap[ix].port2, 0x3F);
   6881         soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval,
   6882                 led2_remap[ix].port3, 0x3F);
   6883 
   6884         if (ix == 0) {
   6885             soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval,
   6886                     led2_remap[ix].port1, 1);
   6887             soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval,
   6888                     led2_remap[ix].port3, 0);
   6889         }
   6890 
   6891         soc_pci_write(unit, soc_reg_addr(unit, led2_remap[ix].reg_addr,
   6892                                          REG_PORT_ANY, 0), rval);
   6893     }
   6894 
   6895     /* initialize the LED processors data ram */
   6896     rval = 0;
   6897     for (ix = 0; ix < 256; ix++) {
   6898         WRITE_CMIC_LEDUP0_DATA_RAMr(unit,ix, rval);
   6899         WRITE_CMIC_LEDUP1_DATA_RAMr(unit,ix, rval);
   6900         soc_pci_write(unit,
   6901                       soc_reg_addr(unit, CMIC_LEDUP2_DATA_RAMr, REG_PORT_ANY, ix),
   6902                       rval);
   6903     }
   6904 
   6905     return SOC_E_NONE;
   6906 }
   6907 
   6908 static const soc_reg_t pvtmon_result_reg[] = {
   6909     TOP_PVTMON_RESULT_0r, TOP_PVTMON_RESULT_1r,
   6910     TOP_PVTMON_RESULT_2r, TOP_PVTMON_RESULT_3r,
   6911     TOP_PVTMON_RESULT_4r, TOP_PVTMON_RESULT_5r,
   6912     TOP_PVTMON_RESULT_6r, TOP_PVTMON_RESULT_7r
   6913 };
   6914 
   6915 STATIC int
   6916 soc_th_port_config_validate(int unit)
   6917 {
   6918     int encap, ovs, lport, blk;
   6919     int port_sister_speed[4] = {-1, -1, -1, -1};
   6920     int port_status[4] = {0};
   6921     int port_base, port_base_speed = 0;
   6922     soc_info_t *si = &SOC_INFO(unit);
   6923     int mixed_25_50_en = 0;
   6924     int i = 0, idx = 0;
   6925 
   6926     ovs = si->oversub_mode;
   6927     mixed_25_50_en = si->os_mixed_sister_25_50_enable;
   6928 
   6929     if (!ovs) {
   6930         return SOC_E_NONE;
   6931     }
   6932 
   6933     for (blk = 0; blk < SOC_MAX_NUM_BLKS; blk++) {
   6934         if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CLPORT) {
   6935             encap = SOC_ENCAP_COUNT;
   6936             i = 0;
   6937             for (idx = 0; idx < 4; idx++) {
   6938                 port_sister_speed[idx] = -1;
   6939                 port_status[idx] = 0;
   6940             }
   6941 
   6942             SOC_PBMP_ITER(si->block_bitmap[blk], lport) {
   6943                 if (encap == SOC_ENCAP_COUNT) {
   6944                     encap = IS_HG_PORT(unit, lport) ?
   6945                             SOC_ENCAP_HIGIG2 : SOC_ENCAP_IEEE;
   6946                     port_base = lport;
   6947                     port_base_speed = si->port_speed_max[port_base];
   6948                     ovs = SOC_PBMP_MEMBER(si->oversub_pbm, port_base) ? 1 : 0;
   6949                 }
   6950 
   6951                 port_sister_speed[i] = si->port_speed_max[lport];
   6952                 port_status[i] = (!SOC_PBMP_MEMBER(si->all.disabled_bitmap, lport)) ? 1 : 0;
   6953                 i++;
   6954             }
   6955 
   6956             /*
   6957              * The port config was restricted.
   6958              * portmap_1.0=1:100
   6959              * portmap_2.0=2:25:i
   6960              * portmap_3.0=3:50:i
   6961              * portmap_4.0=4:25:i
   6962              */
   6963             if (((port_base_speed == 100000) && (port_sister_speed[1] == 25000) &&
   6964                  (port_sister_speed[2] == 50000) && (port_sister_speed[3] == 25000) &&
   6965                  (port_status[0]) && (!port_status[1]) && (!port_status[2]) && (!port_status[3])) ||
   6966                 ((port_sister_speed[0] == 25000) && (port_sister_speed[1] == 25000) &&
   6967                  (port_sister_speed[2] == 50000) && (port_status[0]) && (port_status[1]) &&
   6968                  (port_status[2]))) {
   6969                 LOG_ERROR(BSL_LS_SOC_PORT,
   6970                           (BSL_META_U(unit,
   6971                                       "Unsupported port config in oversub mode on port macro %d\n"),
   6972                           SOC_BLOCK_NUMBER(unit, blk)));
   6973                 return SOC_E_CONFIG;
   6974             }
   6975             if (!mixed_25_50_en &&
   6976                 (((port_sister_speed[0] == 25000) &&
   6977                   (port_sister_speed[2] == 50000) &&
   6978                   (port_status[0]) && (port_status[2])) ||
   6979                  ((port_sister_speed[0] == 50000) &&
   6980                   (port_sister_speed[2] == 25000) &&
   6981                   (port_status[0]) && port_status[2]))) {
   6982                 LOG_ERROR(BSL_LS_SOC_PORT,
   6983                           (BSL_META_U(unit,
   6984                                       "Unsupported port config in mixed mode on port macro %d\n"),
   6985                            SOC_BLOCK_NUMBER(unit, blk)));
   6986                 return SOC_E_CONFIG;
   6987             }
   6988         }
   6989     }
   6990 
   6991     return SOC_E_NONE;
   6992 }
   6993 
   6994 STATIC int
   6995 _soc_tomahawk_misc_init(int unit)
   6996 {
   6997 #ifdef BCM_TOMAHAWKX_SUPPORT
   6998     static int rtag7_field_width[] = { 16, 16, 4, 16, 8, 8, 16, 16 };
   6999     soc_mem_t mem;
   7000     soc_reg_t reg;
   7001     uint32 rval, rval1, fval;
   7002     uint64 rval64;
   7003     int rv, pipe = 0;
   7004     soc_pbmp_t pbmp;
   7005     uint8 rev_id;
   7006     uint16 dev_id;
   7007     int port_chk, num_port = 136;
   7008     int port, phy_port_base, lport;
   7009     _soc_tomahawk_tdm_t *tdm;
   7010     uint32 entry[SOC_MAX_MEM_WORDS];
   7011     int block_info_idx, parity_enable;
   7012     int clport, lane, mode, class, index;
   7013     int count, sub_sel, offset;
   7014     int freq, target_freq, divisor, dividend, delay;
   7015     soc_control_t *soc = SOC_CONTROL(unit);
   7016     soc_info_t *si = &SOC_INFO(unit);
   7017     int ecmp_mode = 0;
   7018     int fabric_port_enable = 1;
   7019     static soc_field_t port_fields[_TH_PORTS_PER_PBLK] = {
   7020         PORT0f, PORT1f, PORT2f, PORT3f
   7021     };
   7022     static const int mode_encodings[SOC_TH_PORT_RATIO_COUNT] = {
   7023         4, 3, 3, 3, 2, 2, 1, 1, 0
   7024     };
   7025     int phy_port_mgmt0, phy_port_mgmt1;
   7026 #if defined(BCM_TOMAHAWK2_SUPPORT)
   7027     egr_mmu_cell_credit_entry_t credit_entry;
   7028     char *board_name;
   7029 #endif
   7030 
   7031     soc_cm_get_id(unit, &dev_id, &rev_id);
   7032 
   7033     /* Stop the mem scan task before all of the parity init takes place */
   7034     SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_stop(unit));
   7035     SOC_IF_ERROR_RETURN(soc_generic_sram_mem_scan_stop(unit));
   7036 
   7037     /* Prevent ASF from accessing phy */
   7038     SOC_IF_ERROR_RETURN(soc_th_asf_deinit(unit));
   7039 
   7040     parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE);
   7041     if (parity_enable) {
   7042         if ((!SAL_BOOT_SIMULATION || SAL_BOOT_QUICKTURN) &&
   7043             !SOC_WARM_BOOT(unit)) {
   7044 
   7045             /* Initialize PORT MIB counter */
   7046             rval = 0;
   7047             SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   7048                 port = SOC_BLOCK_PORT(unit, block_info_idx);
   7049                 soc_reg_field_set(unit, CLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf);
   7050                 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MIB_RESETr(unit, port, rval));
   7051                 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MIB_RESETr(unit, port, 0));
   7052             }
   7053             rval = 0;
   7054             SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_XLPORT) {
   7055                 port = SOC_BLOCK_PORT(unit, block_info_idx);
   7056                 soc_reg_field_set(unit, XLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf);
   7057                 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, rval));
   7058                 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, 0));
   7059             }
   7060             /* Certain mems/regs need to be cleared before enabling SER */
   7061             if (SOC_IS_TOMAHAWK(unit)) {
   7062                 SOC_IF_ERROR_RETURN(soc_tomahawk_clear_mmu_memory(unit));
   7063             }
   7064 #ifdef BCM_TOMAHAWK2_SUPPORT
   7065             else if (SOC_IS_TOMAHAWK2(unit)) {
   7066                 SOC_IF_ERROR_RETURN(soc_tomahawk2_clear_mmu_memory(unit)); 
   7067             }
   7068 #endif
   7069         }
   7070 
   7071         /* Check the whether the alpm tables use cache to recover*/
   7072         soc_ser_alpm_cache_check(unit);
   7073 
   7074         /* Enable logging of SER events */
   7075         soc_ser_log_init(unit, NULL, 0);
   7076 
   7077         /* Enable l2_mgmt interrupt */
   7078         SOC_IF_ERROR_RETURN
   7079             (soc_reg_field32_modify(unit, L2_MGMT_INTR_MASKr, REG_PORT_ANY,
   7080                                     SER_FIFO_NOT_EMPTYf, 1));
   7081 #ifdef BCM_CMICM_SUPPORT
   7082         if (soc_feature(unit, soc_feature_cmicm)) {
   7083             (void)soc_cmicm_intr3_enable(unit, 0x2); /* L2_MGMT_TO_CMIC_INTR bit 1 */
   7084         }
   7085 #endif
   7086 #ifdef BCM_TOMAHAWK2_SUPPORT
   7087         if (SOC_IS_TOMAHAWK2(unit)) {
   7088             SOC_IF_ERROR_RETURN(soc_tomahawk2_clear_enabled_port_data(unit));
   7089         }
   7090 #endif
   7091         SOC_IF_ERROR_RETURN(soc_tomahawk_tcam_ser_init(unit));
   7092         
   7093         SOC_IF_ERROR_RETURN(soc_tomahawk_ser_enable_all(unit, TRUE));
   7094         
   7095         soc_tomahawk_ser_register(unit);
   7096 #if defined(SER_TR_TEST_SUPPORT)
   7097         /*Initialize chip-specific functions for SER testing*/
   7098         soc_th_ser_test_register(unit);
   7099 #endif /*defined(SER_TR_TEST_SUPPORT*/
   7100     }
   7101 
   7102     if (!SOC_IS_RELOADING(unit) && !SOC_WARM_BOOT(unit)) {
   7103 #ifdef BCM_TOMAHAWK2_SUPPORT
   7104         if (SOC_IS_TOMAHAWK2(unit)) {
   7105             SOC_IF_ERROR_RETURN(soc_tomahawk2_init_mmu_memory(unit));
   7106         } else
   7107 #endif
   7108         {
   7109             SOC_IF_ERROR_RETURN(_soc_tomahawk_clear_all_memory(unit, 1));
   7110         }
   7111 
   7112         /* Dummy call to clear garbage h/w values */
   7113         SOC_IF_ERROR_RETURN
   7114             (soc_tomahawk_temperature_monitor_get(unit, COUNTOF(pvtmon_result_reg),
   7115                                                   NULL, NULL));
   7116     }
   7117 
   7118 #ifdef BCM_TOMAHAWK2_SUPPORT
   7119     if (SOC_IS_TOMAHAWK2(unit)) {
   7120         int latency;
   7121         int lmode = SOC_SWITCH_BYPASS_MODE_NONE;
   7122 
   7123         SOC_IF_ERROR_RETURN(soc_th_latency_get(unit, &lmode));
   7124 
   7125         /* Set the latency in Slot Pipeline config register, need to be
   7126          * programmed before any traffic going through the IP */
   7127         latency = soc_th2_slot_pipeline_latency_get(si->dpp_clk_ratio_x10, lmode);
   7128         reg = SLOT_PIPELINE_CONFIGr;
   7129         rval = 0;
   7130         soc_reg_field_set(unit, reg, &rval, LATENCYf, latency);
   7131         soc_reg_field_set(unit, reg, &rval, WR_ENf, 1);
   7132         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   7133     }
   7134 #endif
   7135 
   7136 #ifdef BCM_TOMAHAWK2_SUPPORT
   7137     if (SOC_IS_TOMAHAWK2(unit)) {
   7138         SOC_IF_ERROR_RETURN(_soc_tomahawk2_port_mapping_init(unit));
   7139     } else
   7140 #endif
   7141     {
   7142         SOC_IF_ERROR_RETURN(_soc_tomahawk_port_mapping_init(unit));
   7143     }
   7144 
   7145     /*
   7146      * Parse config at init time and cache property value for use at
   7147      * run time
   7148      */
   7149     if (SOC_PBMP_NOT_NULL(PBMP_HG_ALL(unit))) {
   7150         fabric_port_enable = 1;
   7151     } else {
   7152         fabric_port_enable = soc_property_get(unit, spn_FABRIC_PORT_ENABLE, 1);
   7153     }
   7154     SOC_CONTROL_LOCK(unit);
   7155     si->fabric_port_enable = fabric_port_enable;
   7156     SOC_CONTROL_UNLOCK(unit);
   7157 
   7158     if (dev_id == BCM56968_DEVICE_ID) {
   7159         if ((soc_property_get(unit, spn_SWITCH_BYPASS_MODE, 
   7160             SOC_SWITCH_BYPASS_MODE_NONE)) != SOC_SWITCH_BYPASS_MODE_NONE) {
   7161             LOG_ERROR(BSL_LS_SOC_COMMON,
   7162                         (BSL_META_U(unit,
   7163                                     "Low latency and Balanced latency modes not"
   7164                                     "supported on BCM56968 \n")));
   7165             return SOC_E_CONFIG;
   7166         }
   7167         if (SOC_PBMP_NEQ(si->ether.bitmap, si->management_pbm) &&
   7168             !SOC_PBMP_MEMBER(si->hg.bitmap, si->port_p2l_mapping[129]) &&
   7169             !SOC_PBMP_MEMBER(si->hg.bitmap, si->port_p2l_mapping[131])) {
   7170             LOG_ERROR(BSL_LS_SOC_COMMON,
   7171                         (BSL_META_U(unit,
   7172                             "Port config error!! The MGMT/CPU ports support "
   7173                             "Eth/HiGig encap and the General ports only "
   7174                             "support HiGig encap on BCM56968.\n")));
   7175             return SOC_E_CONFIG;
   7176         }
   7177     }
   7178 
   7179     for(port_chk = 0; port_chk < num_port; port_chk++) {
   7180         if (si->port_speed_max[port_chk] > 0 &&
   7181             SOC_PBMP_MEMBER(PBMP_ALL(unit), port_chk)) {
   7182             rv = soc_th_port_speed_supported(unit, port_chk,
   7183                                              si->port_speed_max[port_chk]);
   7184             if (SOC_FAILURE(rv)) {
   7185                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7186                             (BSL_META_U(unit,
   7187                                         "Unsupported port speed : port - %d, "
   7188                                         "speed - %d\n"), port_chk,
   7189                                         si->port_speed_max[port_chk]));
   7190                 return rv;
   7191             }
   7192         }
   7193     }
   7194 
   7195 #if defined(BCM_TOMAHAWK_SUPPORT)
   7196     if (SOC_IS_TOMAHAWK(unit)) {
   7197         SOC_IF_ERROR_RETURN(soc_th_port_config_validate(unit));
   7198     }
   7199 #endif /* BCM_TOMAHAWK_SUPPORT */
   7200 
   7201 #if defined(BCM_TOMAHAWK2_SUPPORT)
   7202     if (SOC_IS_TOMAHAWK2(unit)) {
   7203         /* Check sister ports */
   7204         SOC_IF_ERROR_RETURN(soc_port_sister_validate(unit, _TH2_PORTS_PER_PBLK));
   7205 
   7206         /* Check if speed and encap mode matched */
   7207         SOC_IF_ERROR_RETURN(soc_port_speed_encap_validate(unit));
   7208 
   7209         /* Check line rate bandwidth for each pipe */
   7210         SOC_IF_ERROR_RETURN(soc_th2_max_lr_bandwidth_validate(unit));
   7211 
   7212         /* Check the speed classes */
   7213         SOC_IF_ERROR_RETURN(soc_th2_speed_class_validate(unit));
   7214     }
   7215 #endif /* BCM_TOMAHAWK2_SUPPORT */
   7216 
   7217     if (!SAL_BOOT_XGSSIM) {
   7218         if (SOC_IS_TOMAHAWK(unit)) {
   7219             if (soc->tdm_info == NULL) {
   7220                 soc->tdm_info = sal_alloc(sizeof(_soc_tomahawk_tdm_t),
   7221                                           "Tomahakw TDM info");
   7222                 if (soc->tdm_info == NULL) {
   7223                     return SOC_E_MEMORY;
   7224                 }
   7225             }
   7226             tdm = soc->tdm_info;
   7227             /* Calculate TDM calendars */
   7228             rv = _soc_tomahawk_tdm_calculation(unit, TRUE, tdm);
   7229             if (SOC_FAILURE(rv)){
   7230                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7231                           (BSL_META_U(unit,
   7232                                       "FAILED in"
   7233                                       "_soc_tomahawk_tdm_calculation\n")));
   7234                 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
   7235                 return rv;
   7236             }
   7237             /* Set IDB calendars */
   7238             rv = _soc_tomahawk_tdm_idb_calendar_set(unit, 0, UPDATE_ALL_PIPES);
   7239             if (SOC_FAILURE(rv)){
   7240                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7241                           (BSL_META_U(unit,
   7242                                       "FAILED in"
   7243                                       "_soc_tomahawk_tdm_idb_calendar_set\n")));
   7244                 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
   7245                 return rv;
   7246             }
   7247             rv = _soc_tomahawk_tdm_idb_oversub_group_set(unit);
   7248             if (SOC_FAILURE(rv)){
   7249                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7250                           (BSL_META_U(unit,
   7251                                       "FAILED in"
   7252                                       "_soc_tomahawk_tdm_idb_oversub_group_set\n")));
   7253                 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
   7254                 return rv;
   7255             }
   7256             rv = _soc_tomahawk_tdm_idb_opportunistic_set(unit, TRUE);
   7257             if (SOC_FAILURE(rv)){
   7258                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7259                           (BSL_META_U(unit,
   7260                                       "FAILED in"
   7261                                       "_soc_tomahawk_tdm_idb_opportunistic_set\n")));
   7262                 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
   7263                 return rv;
   7264             }
   7265             rv = _soc_tomahawk_tdm_idb_hsp_set(unit, UPDATE_ALL_PIPES);
   7266             if (SOC_FAILURE(rv)){
   7267                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7268                           (BSL_META_U(unit,
   7269                                       "FAILED in"
   7270                                       "_soc_tomahawk_tdm_idb_hsp_set\n")));
   7271                 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
   7272                 return rv;
   7273             }
   7274             /* Set MMU calendars */
   7275             rv = _soc_tomahawk_tdm_mmu_calendar_set(unit, 0, UPDATE_ALL_PIPES);
   7276             if (SOC_FAILURE(rv)){
   7277                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7278                           (BSL_META_U(unit,
   7279                                       "FAILED in"
   7280                                       "_soc_tomahawk_tdm_mmu_calendar_set\n")));
   7281                 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
   7282                 return rv;
   7283             }
   7284             rv = _soc_tomahawk_tdm_mmu_oversub_group_set(unit);
   7285             if (SOC_FAILURE(rv)){
   7286                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7287                           (BSL_META_U(unit,
   7288                                       "FAILED in"
   7289                                       "_soc_tomahawk_tdm_mmu_oversub_group_set\n")));
   7290                 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
   7291                 return rv;
   7292             }
   7293             SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
   7294             rv = _soc_tomahawk_tdm_mmu_opportunistic_set(unit, TRUE);
   7295             if (SOC_FAILURE(rv)){
   7296                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7297                           (BSL_META_U(unit,
   7298                                       "FAILED in"
   7299                                       "_soc_tomahawk_tdm_mmu_opportunistic_set\n")));
   7300                 return rv;
   7301             }
   7302             rv = _soc_tomahawk_tdm_mmu_hsp_set(unit, UPDATE_ALL_PIPES);
   7303             if (SOC_FAILURE(rv)){
   7304                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7305                           (BSL_META_U(unit,
   7306                                       "FAILED in"
   7307                                       "_soc_tomahawk_tdm_mmu_hsp_set\n")));
   7308                 return rv;
   7309             }
   7310             /* Initialize IDB */
   7311             rv = _soc_tomahawk_idb_init(unit);
   7312             if (SOC_FAILURE(rv)){
   7313                 LOG_ERROR(BSL_LS_SOC_COMMON,
   7314                           (BSL_META_U(unit,
   7315                                       "FAILED in"
   7316                                       "_soc_tomahawk_idb_init\n")));
   7317                 return rv;
   7318             }
   7319 #ifdef BCM_TOMAHAWK2_SUPPORT
   7320         } else if (SOC_IS_TOMAHAWK2(unit)) {
   7321             SOC_IF_ERROR_RETURN(_soc_tomahawk2_tdm_init(unit));
   7322             SOC_IF_ERROR_RETURN(_soc_tomahawk2_idb_init(unit));
   7323 #endif
   7324         }
   7325     }
   7326 
   7327     sal_memset(entry, 0, sizeof(cpu_pbm_entry_t));
   7328     soc_mem_pbmp_field_set(unit, CPU_PBMm, entry, BITMAPf, &PBMP_CMIC(unit));
   7329     SOC_IF_ERROR_RETURN
   7330         (soc_mem_write(unit, CPU_PBMm, MEM_BLOCK_ALL, 0, entry));
   7331 
   7332     sal_memset(entry, 0, sizeof(cpu_pbm_2_entry_t));
   7333     soc_mem_pbmp_field_set(unit, CPU_PBM_2m, entry, BITMAPf, &PBMP_CMIC(unit));
   7334     SOC_IF_ERROR_RETURN
   7335         (soc_mem_write(unit, CPU_PBM_2m, MEM_BLOCK_ALL, 0, entry));
   7336 
   7337 #if __GNUC__ > 6
   7338 #pragma GCC diagnostic push
   7339 #pragma GCC diagnostic ignored "-Wmemset-elt-size"
   7340 #endif
   7341     /*
   7342      * We are NOT doing a sal_memset(entry,0,sizeof(entry)) for
   7343      * performance reasons, because the actual soc_mem_field_set()
   7344      * will only write sizeof(device_loopback_ports_bitmap_entry_t)=17
   7345      * bytes while sizeof(entry)=SOC_MAX_MEM_BYTES can be up to 651
   7346      * depending on which devices are compiled in.
   7347      */
   7348     sal_memset(entry, 0, sizeof(device_loopback_ports_bitmap_entry_t));
   7349 #if __GNUC__ > 6
   7350 #pragma GCC diagnostic pop
   7351 #endif
   7352     soc_mem_pbmp_field_set(unit, DEVICE_LOOPBACK_PORTS_BITMAPm, entry, BITMAPf,
   7353                            &PBMP_LB(unit));
   7354     SOC_IF_ERROR_RETURN
   7355         (soc_mem_write(unit, DEVICE_LOOPBACK_PORTS_BITMAPm, MEM_BLOCK_ALL, 0,
   7356                        entry));
   7357 
   7358     PBMP_LB_ITER(unit, port) {
   7359         mem = SOC_MEM_UNIQUE_ACC(unit, MULTIPASS_LOOPBACK_BITMAPm)
   7360             [si->port_pipe[port]];
   7361         sal_memset(entry, 0, sizeof(multipass_loopback_bitmap_entry_t));
   7362         SOC_PBMP_PORT_SET(pbmp, port);
   7363         soc_mem_pbmp_field_set(unit, mem, &entry, BITMAPf, &pbmp);
   7364         SOC_IF_ERROR_RETURN
   7365             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, entry));
   7366     }
   7367 
   7368     sal_memset(entry, 0, sizeof(egr_ing_port_entry_t));
   7369     soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 1);
   7370     PBMP_HG_ITER(unit, port) {
   7371         SOC_IF_ERROR_RETURN
   7372             (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry));
   7373     }
   7374     SOC_IF_ERROR_RETURN
   7375         (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, si->cpu_hg_index,
   7376                        entry));
   7377     soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 2);
   7378     PBMP_LB_ITER(unit, port) {
   7379         SOC_IF_ERROR_RETURN
   7380             (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry));
   7381     }
   7382 
   7383     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
   7384         port = SOC_BLOCK_PORT(unit, block_info_idx);
   7385         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
   7386         phy_port_base = PORT_BLOCK_BASE_PORT(port);
   7387 
   7388         /* Assert CLPORT soft reset */
   7389         rval = 0;
   7390         for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) {
   7391             if (si->port_p2l_mapping[phy_port_base + lane] != -1) {
   7392                 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, &rval,
   7393                                   port_fields[lane], 1);
   7394             }
   7395         }
   7396         SOC_IF_ERROR_RETURN(WRITE_CLPORT_SOFT_RESETr(unit, port, rval));
   7397 
   7398         /* Set port mode */
   7399         soc_tomahawk_port_ratio_get(unit, 1 /*initTime*/, clport, &mode);
   7400         rval = 0;
   7401         soc_reg_field_set(unit, CLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf,
   7402                           mode_encodings[mode]);
   7403         soc_reg_field_set(unit, CLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf,
   7404                           mode_encodings[mode]);
   7405         SOC_IF_ERROR_RETURN(WRITE_CLPORT_MODE_REGr(unit, port, rval));
   7406 
   7407         /* De-assert XLPORT soft reset */
   7408         SOC_IF_ERROR_RETURN(WRITE_CLPORT_SOFT_RESETr(unit, port, 0));
   7409 
   7410         /* Enable CLPORT */
   7411         rval = 0;
   7412         rval1 = 0;
   7413         soc_reg_field_set(unit, CLPORT_FLOW_CONTROL_CONFIGr, &rval1,
   7414                           MERGE_MODE_ENf, 1);
   7415         for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) {
   7416             lport = si->port_p2l_mapping[phy_port_base + lane];
   7417             if (lport != -1) {
   7418                 soc_reg_field_set(unit, CLPORT_ENABLE_REGr, &rval,
   7419                                   port_fields[lane], 1);
   7420                 SOC_IF_ERROR_RETURN
   7421                     (WRITE_CLPORT_FLOW_CONTROL_CONFIGr(unit, lport, rval1));
   7422             }
   7423         }
   7424         SOC_IF_ERROR_RETURN(WRITE_CLPORT_ENABLE_REGr(unit, port, rval));
   7425     }
   7426 #ifdef BCM_TOMAHAWK2_SUPPORT
   7427     if (SOC_IS_TOMAHAWK2(unit)) {
   7428         phy_port_mgmt0 = _TH2_PHY_PORT_MNG0;
   7429         phy_port_mgmt1 = _TH2_PHY_PORT_MNG1;
   7430     } else
   7431 #endif /* BCM_TOMAHAWK2_SUPPORT */
   7432     {
   7433         phy_port_mgmt0 = 129;
   7434         phy_port_mgmt1 = 131;
   7435     }
   7436 
   7437     SOC_PBMP_ITER(si->management_pbm, port) {
   7438         /* Assert XLPORT soft reset */
   7439         rval = 0;
   7440         if (si->port_p2l_mapping[phy_port_mgmt0] != -1) { /* management port 0 */
   7441             soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, PORT0f, 1);
   7442         }
   7443         if (si->port_p2l_mapping[phy_port_mgmt1] != -1) { /* management port 1 */
   7444             soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, PORT2f, 1);
   7445         }
   7446         SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, rval));
   7447 
   7448         /* Set port mode based upon lanes config */
   7449         rval = 0;
   7450         /* Note - this is a special h/w requirement to use dual lane mode */
   7451         fval = 3;
   7452         soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf,
   7453                           fval);
   7454         soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf,
   7455                           fval);
   7456         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, port, rval));
   7457 
   7458         /* De-assert XLPORT soft reset */
   7459         SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, 0));
   7460 
   7461         /* Enable XLPORT */
   7462         rval = 0;
   7463         if (si->port_p2l_mapping[phy_port_mgmt0] != -1) { /* management port 0 */
   7464             soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, PORT0f, 1);
   7465         }
   7466         if (si->port_p2l_mapping[phy_port_mgmt1] != -1) { /* management port 1 */
   7467             soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, PORT2f, 1);
   7468         }
   7469         SOC_IF_ERROR_RETURN(WRITE_XLPORT_ENABLE_REGr(unit, port, rval));
   7470 
   7471         rval = 0;
   7472         soc_reg_field_set(unit, XLPORT_FLOW_CONTROL_CONFIGr, &rval,
   7473                           MERGE_MODE_ENf, 1);
   7474         SOC_IF_ERROR_RETURN
   7475             (WRITE_XLPORT_FLOW_CONTROL_CONFIGr(unit, port, rval));
   7476     }
   7477 
   7478     SOC_IF_ERROR_RETURN(READ_MMU_GCFG_MISCCONFIGr(unit, &rval));
   7479     soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, REFRESH_ENf, 1);
   7480     SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval));
   7481 
   7482     /* Enable dual hash tables */
   7483     SOC_IF_ERROR_RETURN(_soc_tomahawk_hash_init(unit));
   7484 
   7485     /* Configure EP credit */
   7486     freq = si->frequency;
   7487 #if defined(BCM_TOMAHAWK2_SUPPORT)
   7488     if (soc_feature(unit, soc_feature_egr_mmu_cell_credit_is_memory)) {
   7489         PBMP_ALL_ITER(unit, port) {
   7490             SOC_IF_ERROR_RETURN(
   7491                 soc_th_port_asf_speed_to_mmu_cell_credit(unit, port, 
   7492                     si->port_speed_max[port], &fval));
   7493             SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ANY,
   7494                                 si->port_l2p_mapping[port], &credit_entry));
   7495             soc_EGR_MMU_CELL_CREDITm_field32_set(unit, &credit_entry,
   7496                                                  CREDITf, fval);
   7497             SOC_IF_ERROR_RETURN(WRITE_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ALL,
   7498                                 si->port_l2p_mapping[port], &credit_entry));
   7499         }
   7500     } else
   7501 #endif
   7502     {
   7503         reg = EGR_MMU_CELL_CREDITr;
   7504         rval = 0;
   7505         PBMP_ALL_ITER(unit, port) {
   7506             SOC_IF_ERROR_RETURN(
   7507                 soc_th_port_asf_speed_to_mmu_cell_credit(unit, port, 
   7508                     si->port_speed_max[port], &fval));
   7509             soc_reg_field_set(unit, reg, &rval, CREDITf, fval);
   7510             SOC_IF_ERROR_RETURN(WRITE_EGR_MMU_CELL_CREDITr(unit, port, rval));
   7511         }
   7512     }
   7513 
   7514     /* Configure egress transmit start count */
   7515     mem = EGR_XMIT_START_COUNTm;
   7516     sal_memset(entry, 0, sizeof(egr_xmit_start_count_entry_t));
   7517     soc_mem_field32_set(unit, EGR_XMIT_START_COUNTm, entry, THRESHOLDf, 18);
   7518     PBMP_ALL_ITER(unit, port) {
   7519         for (class = 0; class < 13; class++) {
   7520             index = (port % 34) * 16 + class;
   7521             pipe = si->port_pipe[port];
   7522             SOC_IF_ERROR_RETURN
   7523                 (soc_mem_write(unit, SOC_MEM_UNIQUE_ACC(unit, mem)[pipe],
   7524                                MEM_BLOCK_ALL, index, entry));
   7525         }
   7526     
   7527         /* Update HSP port multicast T2OQ setting, and this is not supported on TH2 */
   7528         if (SOC_PBMP_MEMBER(si->eq_pbm, port) && !SOC_IS_TOMAHAWK2(unit)) {
   7529             SOC_IF_ERROR_RETURN(_soc_tomahawk_mc_toq_cfg(unit, port, TRUE));
   7530         }
   7531     }
   7532     rval = 0;
   7533     SOC_IF_ERROR_RETURN(READ_MMU_SCFG_TOQ_MC_CFG0r(unit, &rval));
   7534     soc_reg_field_set(unit, MMU_SCFG_TOQ_MC_CFG0r, &rval,
   7535                       MCQE_FULL_THRESHOLDf, 0);
   7536     SOC_IF_ERROR_RETURN(WRITE_MMU_SCFG_TOQ_MC_CFG0r(unit, rval));
   7537 
   7538     /* Ingress Force SAF */
   7539 #ifdef BCM_TOMAHAWK2_SUPPORT
   7540     if (SOC_IS_TOMAHAWK2(unit)) {
   7541         SOC_IF_ERROR_RETURN(_soc_tomahawk2_ing_fsaf_init(unit));
   7542     }
   7543 #endif
   7544 
   7545     /* Egress Force SAF */
   7546     if (SOC_PBMP_NOT_NULL(si->oversub_pbm)) {
   7547         uint32 cd = 0, dd = si->frequency;
   7548         int factor = SOC_IS_TOMAHAWK2(unit) ? 178125 : 118750;
   7549         mem = EDB_1DBG_Bm;
   7550 
   7551         sal_memset(entry, 0, sizeof(edb_1dbg_b_entry_t));
   7552 
   7553         PBMP_ALL_ITER(unit, port) {
   7554             fval = ((si->port_speed_max[port] / 10) * factor) / 100000;
   7555             soc_mem_field32_set(unit, mem, &entry, FIELD_Bf, fval);
   7556             SOC_IF_ERROR_RETURN
   7557                 (soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   7558                                si->port_l2p_mapping[port], entry));
   7559         }
   7560 
   7561         for (index = 0; index < NUM_PIPE(unit); index++) {
   7562             if (SOC_PBMP_IS_NULL(si->pipe_pbm[index])) {
   7563                 continue;
   7564             }
   7565             reg = SOC_REG_UNIQUE_ACC(unit, EDB_1DBG_Ar)[index];
   7566             if (SOC_IS_TOMAHAWK2(unit)) {
   7567                 SOC_IF_ERROR_RETURN
   7568                     (soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval64));
   7569                 cd = 135 * si->frequency / 10;
   7570                 dd = 15 * si->frequency / 10;
   7571                 soc_reg64_field32_set(unit, EDB_1DBG_Ar, &rval64, FIELD_Af, dd);
   7572                 soc_reg64_field32_set(unit, EDB_1DBG_Ar, &rval64, FIELD_Bf, cd);
   7573                 soc_reg64_field32_set(unit, EDB_1DBG_Ar, &rval64, FIELD_Cf, 25);
   7574                 SOC_IF_ERROR_RETURN
   7575                     (soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval64));
   7576             } else {
   7577                 SOC_IF_ERROR_RETURN
   7578                     (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   7579                 switch (si->frequency) {
   7580                 case 850: cd = 7650;
   7581                     break;
   7582                 case 765: cd = 6885;
   7583                     break;
   7584                 case 672: cd = 6048;
   7585                     break;
   7586                 case 645: cd = 5805;
   7587                     break;
   7588                 case 545: cd = 4905;
   7589                     break;
   7590                 default:
   7591                     break;
   7592                 }
   7593                 soc_reg_field_set(unit, EDB_1DBG_Ar, &rval, FIELD_Af, dd);
   7594                 soc_reg_field_set(unit, EDB_1DBG_Ar, &rval, FIELD_Bf, cd);
   7595                 soc_reg_field_set(unit, EDB_1DBG_Ar, &rval, FIELD_Cf, 8);
   7596                 SOC_IF_ERROR_RETURN
   7597                     (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   7598             }
   7599         }
   7600     }
   7601 
   7602     /* Enable egress */
   7603     sal_memset(entry, 0, sizeof(egr_enable_entry_t));
   7604     soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 1);
   7605     PBMP_ALL_ITER(unit, port) {
   7606         if (SOC_IS_TOMAHAWK2(unit)) {
   7607             SOC_IF_ERROR_RETURN
   7608                 (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, 
   7609                                    si->port_l2p_mapping[port], entry));
   7610         } else {
   7611             SOC_IF_ERROR_RETURN
   7612                 (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, port, entry));
   7613         }
   7614     }
   7615 
   7616     sal_memset(entry, 0, sizeof(epc_link_bmap_entry_t));
   7617     soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf,
   7618                            &PBMP_CMIC(unit));
   7619     if (soc_mem_field_valid(unit, EPC_LINK_BMAPm, ENABLE_SOBMH_BLOCKINGf)) {
   7620         soc_mem_field32_set(unit, EPC_LINK_BMAPm, entry, ENABLE_SOBMH_BLOCKINGf,
   7621                             soc_property_get(unit, "epc_sobmh_block", 0));
   7622     }
   7623     SOC_IF_ERROR_RETURN(WRITE_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL, 0, entry));
   7624 
   7625 #ifdef BCM_TOMAHAWK2_SUPPORT
   7626     if (SOC_IS_TOMAHAWK2(unit)) {
   7627         /* enable all ports */
   7628         ing_dest_port_enable_entry_t ingr_entry;
   7629 
   7630         sal_memset(&ingr_entry, 0, sizeof(ingr_entry));
   7631         soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, &ingr_entry, 
   7632                                PORT_BITMAPf, &PBMP_ALL(unit));
   7633         SOC_IF_ERROR_RETURN(WRITE_ING_DEST_PORT_ENABLEm(unit, MEM_BLOCK_ALL, 0,
   7634                                                         &ingr_entry));
   7635     }
   7636 #endif
   7637     SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, &rval64));
   7638     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   7639                           L3SRC_HIT_ENABLEf, 1);
   7640     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   7641                           L2DST_HIT_ENABLEf, 1);
   7642     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   7643                           APPLY_EGR_MASK_ON_L2f, 1);
   7644     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   7645                           APPLY_EGR_MASK_ON_L3f, 1);
   7646     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   7647                           ARP_RARP_TO_FPf, 0x3); /* enable both ARP & RARP */
   7648     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   7649                           ARP_VALIDATION_ENf, 1);
   7650     if (soc_feature(unit, soc_feature_port_lag_failover)) {
   7651         soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   7652                               IGNORE_HG_HDR_LAG_FAILOVERf, 0);
   7653     } else {
   7654         soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   7655                               IGNORE_HG_HDR_LAG_FAILOVERf, 1);
   7656     }
   7657     SOC_IF_ERROR_RETURN(WRITE_ING_CONFIG_64r(unit, rval64));
   7658 
   7659     SOC_IF_ERROR_RETURN
   7660         (soc_reg_field32_modify(unit, EGR_CONFIG_1r, REG_PORT_ANY, RING_MODEf,
   7661                                 1));
   7662     /* This bit controls MAC_DA format on MPB bus used for L3UC extended view packet flow */
   7663     if (soc_property_get(unit, spn_EMBEDDED_NH_VP_SUPPORT, 0)) {
   7664         SOC_IF_ERROR_RETURN
   7665             (soc_reg_field32_modify(unit, EGR_CONFIG_1r, REG_PORT_ANY,
   7666                                     MACDA_OUI_PROFILE_ENABLEf, 1));
   7667     }
   7668 
   7669     /* The HW defaults for EGR_VLAN_CONTROL_1.VT_MISS_UNTAG == 1, which
   7670      * causes the outer tag to be removed from packets that don't have
   7671      * a hit in the egress vlan tranlation table. Set to 0 to disable this.
   7672      */
   7673     rval = 0;
   7674     soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, VT_MISS_UNTAGf, 0);
   7675 
   7676     /* Enable pri/cfi remarking on egress ports. */
   7677     soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, REMARK_OUTER_DOT1Pf,
   7678                       1);
   7679     PBMP_ALL_ITER(unit, port) {
   7680         SOC_IF_ERROR_RETURN(WRITE_EGR_VLAN_CONTROL_1r(unit, port, rval));
   7681     }
   7682 
   7683     SOC_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   7684     SOC_PBMP_REMOVE(pbmp, PBMP_LB(unit));
   7685     SOC_IF_ERROR_RETURN(soc_mem_read(unit, ING_EN_EFILTER_BITMAPm,
   7686                                      MEM_BLOCK_ANY, 0, &entry));
   7687     soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm, &entry, BITMAPf,
   7688                            &pbmp);
   7689     SOC_IF_ERROR_RETURN(soc_mem_write(unit, ING_EN_EFILTER_BITMAPm,
   7690                                       MEM_BLOCK_ANY, 0, &entry));
   7691 
   7692     /* Multicast range initialization */
   7693     SOC_IF_ERROR_RETURN
   7694         (soc_hbx_higig2_mcast_sizes_set(unit,
   7695              soc_property_get(unit, spn_HIGIG2_MULTICAST_VLAN_RANGE,
   7696                               SOC_HBX_MULTICAST_RANGE_DEFAULT),
   7697              soc_property_get(unit, spn_HIGIG2_MULTICAST_L2_RANGE,
   7698                               soc_mem_index_count(unit, L2MCm) / 2),
   7699              soc_property_get(unit, spn_HIGIG2_MULTICAST_L3_RANGE,
   7700                               soc_mem_index_count(unit, L2MCm) / 2)));
   7701     SOC_IF_ERROR_RETURN
   7702         (soc_hbx_mcast_size_set(unit, soc_property_get(unit,
   7703              spn_MULTICAST_L2_RANGE, soc_mem_index_count(unit, L2MCm) / 2)));
   7704     SOC_IF_ERROR_RETURN
   7705         (soc_hbx_ipmc_size_set(unit, soc_property_get(unit,
   7706              spn_MULTICAST_L3_RANGE, soc_mem_index_count(unit, L2MCm) / 2)));
   7707 
   7708 #if 0
   7709     
   7710     if (SAL_BOOT_QUICKTURN && SOC_IS_TOMAHAWK(unit)) {
   7711         PBMP_PORT_ITER(unit, port) {
   7712             if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   7713                 continue;
   7714             }
   7715             SOC_IF_ERROR_RETURN
   7716                 (soc_tomahawk_port_speed_update(unit, port,
   7717                                                 si->port_speed_max[port]));
   7718         }
   7719     }
   7720 #endif
   7721 
   7722     freq = si->frequency;
   7723     /*
   7724      * Set external MDIO freq to around 2MHz
   7725      * target_freq = core_clock_freq * DIVIDEND / DIVISOR / 2
   7726      */
   7727     target_freq = 2;
   7728     divisor = (freq + (target_freq * 2 - 1)) / (target_freq * 2);
   7729     divisor = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVISOR, divisor);
   7730     dividend = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVIDEND, 1);
   7731     rval = 0;
   7732 
   7733     if (soc_feature(unit, soc_feature_cmicm)) {
   7734         soc_reg_field_set(unit, CMIC_RATE_ADJUSTr, &rval, DIVISORf, divisor);
   7735         soc_reg_field_set(unit, CMIC_RATE_ADJUSTr, &rval, DIVIDENDf, dividend);
   7736         WRITE_CMIC_RATE_ADJUSTr(unit, rval);
   7737 
   7738         /*
   7739          * Set internal MDIO freq to around 12MHz
   7740          * Valid range is from 2.5MHz to 20MHz
   7741          * target_freq = core_clock_freq * DIVIDEND / DIVISOR / 2
   7742          * or
   7743          * DIVISOR = core_clock_freq * DIVIDENT / (target_freq * 2)
   7744          */
   7745         target_freq = 12;
   7746         divisor = (freq + (target_freq * 2 - 1)) / (target_freq * 2);
   7747         divisor = soc_property_get(unit, spn_RATE_INT_MDIO_DIVISOR, divisor);
   7748         dividend = soc_property_get(unit, spn_RATE_INT_MDIO_DIVIDEND, 1);
   7749         rval = 0;
   7750         soc_reg_field_set (unit, CMIC_RATE_ADJUST_INT_MDIOr, &rval, DIVISORf,
   7751                            divisor);
   7752         soc_reg_field_set (unit, CMIC_RATE_ADJUST_INT_MDIOr, &rval, DIVIDENDf,
   7753                            dividend);
   7754         WRITE_CMIC_RATE_ADJUST_INT_MDIOr(unit, rval);
   7755 
   7756         delay = soc_property_get(unit, spn_MDIO_OUTPUT_DELAY, 10);
   7757         if (delay >= 1  && delay <= 15) {
   7758             READ_CMIC_MIIM_CONFIGr(unit, &rval);
   7759             soc_reg_field_set(unit, CMIC_MIIM_CONFIGr, &rval, MDIO_OUT_DELAYf,
   7760                               delay);
   7761             WRITE_CMIC_MIIM_CONFIGr(unit, rval);
   7762         }
   7763 
   7764         if (!SOC_WARM_BOOT(unit)) {
   7765 #ifdef BCM_TOMAHAWK2_SUPPORT
   7766             if (SOC_IS_TOMAHAWK2(unit)) {
   7767                 SOC_IF_ERROR_RETURN(soc_th2_ledup_init(unit));
   7768             } else
   7769 #endif
   7770             {
   7771                 SOC_IF_ERROR_RETURN(_soc_th_ledup_init(unit));
   7772             }
   7773         }
   7774     }
   7775     
   7776     _phy_tsce_firmware_set_helper[unit] = _soc_tomahawk_tscx_firmware_set;
   7777     _phy_tscf_firmware_set_helper[unit] = _soc_tomahawk_tscx_firmware_set;
   7778 
   7779     rval = 0;
   7780     soc_reg32_get(unit, MMU_SCFG_TOQ_MC_CFG2r, REG_PORT_ANY, 0, &rval);
   7781     soc_reg_field_set(unit, MMU_SCFG_TOQ_MC_CFG2r, &rval,
   7782                       EPRG_KILL_TIMEOUTf, 512);
   7783     SOC_IF_ERROR_RETURN
   7784         (soc_tomahawk_sc_reg32_set(unit, MMU_SCFG_TOQ_MC_CFG2r,
   7785                                    -1, -1, 0, rval));
   7786 
   7787     SOC_IF_ERROR_RETURN
   7788         (soc_counter_tomahawk_status_enable(unit, TRUE));
   7789 
   7790     /* Check if Hierarchical ECMP mode is set */
   7791     rval = 0;
   7792     SOC_IF_ERROR_RETURN(READ_ECMP_CONFIGr(unit, &rval));
   7793     /*
   7794      * If ecmp mode is Fast ECMP (low latency), ecmp mode cannot be changed
   7795      * to Hierarchical or Single
   7796      */
   7797     if (rval != 0) {
   7798         if (soc_property_get(unit, spn_L3_ECMP_LEVELS, 1) == 2) {
   7799             ecmp_mode = 3;
   7800             soc_reg_field_set(unit, ECMP_CONFIGr, &rval, ECMP_MODEf, ecmp_mode);
   7801             SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIGr(unit, rval));
   7802         }
   7803     }
   7804 
   7805     /* Populate and enable RTAG7 Macro flow offset table */
   7806     if (soc_mem_is_valid(unit, RTAG7_FLOW_BASED_HASHm)) {
   7807         count = soc_mem_index_max(unit, RTAG7_FLOW_BASED_HASHm);
   7808         sal_memset(entry, 0, sizeof(rtag7_flow_based_hash_entry_t));
   7809         for (index = 0; index < count; ) {
   7810             for (sub_sel = 0; sub_sel < 8 && index < count; sub_sel++) {
   7811                 for (offset = 0;
   7812                      offset < rtag7_field_width[sub_sel] && index < count;
   7813                      offset++) {
   7814                     if (ecmp_mode == 3) {
   7815                         soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry,
   7816                                             SUB_SEL_ECMP_LEVEL2f, sub_sel);
   7817                         soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry,
   7818                                             OFFSET_ECMP_LEVEL2f, offset);
   7819                     }
   7820                     soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry,
   7821                                         SUB_SEL_ECMPf, sub_sel);
   7822                     soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry,
   7823                                         OFFSET_ECMPf, offset);
   7824                     SOC_IF_ERROR_RETURN
   7825                         (soc_mem_write(unit, RTAG7_FLOW_BASED_HASHm,
   7826                                        MEM_BLOCK_ANY, index, &entry));
   7827                     index++;
   7828                 }
   7829             }
   7830         }
   7831         rval = 0;
   7832         soc_reg_field_set(unit, RTAG7_HASH_SELr, &rval, USE_FLOW_SEL_ECMPf, 1);
   7833         soc_reg_field_set(unit, RTAG7_HASH_SELr, &rval,
   7834                                                 USE_FLOW_SEL_TRILL_ECMPf, 1);
   7835         SOC_IF_ERROR_RETURN(WRITE_RTAG7_HASH_SELr(unit, rval));
   7836     }
   7837 #ifdef INCLUDE_AVS
   7838     /* Register tomahawk related functions */
   7839 #ifdef BCM_TOMAHAWK2_SUPPORT
   7840     if (SOC_IS_TOMAHAWK2(unit)) {
   7841         soc_th2_avs_init(unit);
   7842     } else
   7843 #endif /* BCM_TOMAHAWK2_SUPPORT  */
   7844     {
   7845         soc_th_avs_init(unit);
   7846     }
   7847 #endif /* INCLUDE_AVS  */
   7848 
   7849 #ifdef BCM_TOMAHAWK2_SUPPORT
   7850     if (SOC_IS_TOMAHAWK2(unit)) {
   7851         /* Add board properity which can be used in rc.soc */
   7852         board_name = soc_property_get_str(unit, spn_BOARD_NAME);
   7853         if (board_name) {
   7854             if (soc_mem_config_set == NULL) {
   7855                 LOG_WARN(BSL_LS_SOC_COMMON,
   7856                      (BSL_META_U(unit, "unit %d : soc_mem_config_set() is NULL\n"),
   7857                       unit));
   7858             } else {
   7859                 if (sal_strcmp(board_name, "BCM956970K64") == 0) {
   7860                     soc_mem_config_set("bcm956970k64", "1");
   7861                 } else if (sal_strcmp(board_name, "BCM956970K32") == 0) {
   7862                     soc_mem_config_set("bcm956970k32", "1");
   7863                 } else if (sal_strcmp(board_name, "BCM956970S") == 0) {
   7864                     soc_mem_config_set("bcm956970s", "1");
   7865                 }
   7866             }
   7867         }
   7868     }
   7869 #endif
   7870 
   7871     /* Mem Scan thread start should be the last step in Misc init */
   7872     if (parity_enable) {
   7873         SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_start(unit));
   7874         SOC_IF_ERROR_RETURN(soc_generic_sram_mem_scan_start(unit));
   7875     }
   7876 
   7877     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   7878                 (BSL_META_U(unit,
   7879                             "MISC Init completed (u=%d)\n"), unit));
   7880     return SOC_E_NONE;
   7881 #else
   7882     return SOC_E_UNAVAIL;
   7883 #endif
   7884 }
   7885 
   7886 /*
   7887  * Function used for index calculation of certain memories,
   7888  * where index is derived from more than one key.
   7889  * Eg. (Port, SP) or (Port, PG)
   7890  * Defined as Macro: SOC_TH_MMU_PIPED_MEM_INDEX
   7891  * Note: If no special indexig required, return the same index.
   7892  */
   7893 uint32 _soc_th_piped_mem_index(int unit, soc_port_t port,
   7894                                soc_mem_t mem, int arr_off)
   7895 {
   7896     int     mmu_port, index;
   7897 
   7898     mmu_port = SOC_TH_MMU_PORT(unit, port);
   7899 
   7900     switch (mem) {
   7901         case MMU_THDM_DB_PORTSP_CONFIGm:
   7902         case MMU_THDM_MCQE_PORTSP_CONFIGm:
   7903             index = (_TH_MMU_PORTS_PER_PIPE * arr_off) + (mmu_port & 0x3f);
   7904             break;
   7905         case THDI_PORT_SP_CONFIGm:
   7906         case MMU_THDU_CONFIG_PORTm:
   7907         case MMU_THDU_RESUME_PORTm:
   7908         case MMU_THDU_COUNTER_PORTm:
   7909             index = ((mmu_port & 0x3f) * _TH_MMU_NUM_POOL) + arr_off;
   7910             break;
   7911         case THDI_PORT_PG_CONFIGm:
   7912             index = ((mmu_port & 0x3f) * _TH_MMU_NUM_PG) + arr_off;
   7913             break;
   7914         default:
   7915             return arr_off;
   7916     }
   7917 
   7918     return index;
   7919 }
   7920 
   7921 STATIC void
   7922 _soc_th_mmu_init_dev_config(int unit, _soc_mmu_device_info_t *devcfg,
   7923                             int lossless)
   7924 {
   7925 #define _TH_TDM_MCQE_RSVD_OVERSHOOT 12
   7926 #define _TH_MCQE_RSVD_PER_MCQ 6
   7927     uint32 total_rsvd_mcq = 0;
   7928     int port;
   7929     soc_info_t *si = &SOC_INFO(unit);;
   7930     sal_memset(devcfg, 0, sizeof(_soc_mmu_device_info_t));
   7931 
   7932     devcfg->max_pkt_byte = _TH_MMU_MAX_PACKET_BYTES;
   7933     devcfg->mmu_hdr_byte = _TH_MMU_PACKET_HEADER_BYTES;
   7934     devcfg->jumbo_pkt_size = _TH_MMU_JUMBO_FRAME_BYTES;
   7935     devcfg->default_mtu_size = _TH_MMU_DEFAULT_MTU_BYTES;
   7936     devcfg->mmu_cell_size = _TH_MMU_BYTES_PER_CELL;
   7937     devcfg->mmu_total_cell = _TH_MMU_TOTAL_CELLS_PER_XPE;
   7938 #ifdef  BCM_TOMAHAWKPLUS_SUPPORT
   7939     if (SOC_IS_TOMAHAWKPLUS(unit)) {
   7940         devcfg->mmu_total_cell = _THP_MMU_TOTAL_CELLS_PER_XPE;
   7941     }
   7942 #endif
   7943     devcfg->num_pg = _TH_MMU_NUM_PG;
   7944     devcfg->num_service_pool = _TH_MMU_NUM_POOL;
   7945     devcfg->flags = SOC_MMU_CFG_F_PORT_MIN | SOC_MMU_CFG_F_PORT_POOL_MIN |
   7946                     SOC_MMU_CFG_F_RQE | SOC_MMU_CFG_F_EGR_MCQ_ENTRY;
   7947     devcfg->total_mcq_entry = _TH_MMU_TOTAL_MCQ_ENTRY(unit);
   7948     /* Device reservation for MCQ Entry - 6 cells for each MC queue */
   7949     PBMP_ALL_ITER(unit, port) {
   7950         if (IS_CPU_PORT(unit, port)) {
   7951             continue;
   7952         }
   7953         total_rsvd_mcq += (si->port_num_cosq[port] * _TH_MCQE_RSVD_PER_MCQ);
   7954     }
   7955     total_rsvd_mcq >>= 1; /* Converting it to per XPE */
   7956     total_rsvd_mcq += ((SOC_TH_NUM_CPU_QUEUES * _TH_MCQE_RSVD_PER_MCQ) +
   7957                        _TH_TDM_MCQE_RSVD_OVERSHOOT);
   7958     devcfg->total_mcq_entry -= total_rsvd_mcq;
   7959     devcfg->total_rqe_queue_entry = _TH_MMU_TOTAL_RQE_ENTRY(unit) -
   7960                                     SOC_TH_MMU_RQE_ENTRY_RSVD_PER_XPE;
   7961     devcfg->rqe_queue_num = _TH_MMU_NUM_RQE_QUEUES;
   7962 }
   7963 
   7964 STATIC int
   7965 _soc_th_default_pg_headroom(int unit, soc_port_t port,
   7966                             int lossless)
   7967 {
   7968     int speed = 1000, hdrm = 0;
   7969     uint8 port_oversub = 0;
   7970 
   7971     if (IS_CPU_PORT(unit, port)) {
   7972         return 77;
   7973     } else if (!lossless) {
   7974         return 0;
   7975     } else if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
   7976         return 166;
   7977     } else if (IS_LB_PORT(unit, port)) {
   7978         return 150;
   7979     }
   7980 
   7981     speed = SOC_INFO(unit).port_init_speed[port] ?
   7982             SOC_INFO(unit).port_init_speed[port] :
   7983             SOC_INFO(unit).port_speed_max[port];
   7984 
   7985     if (SOC_PBMP_NOT_NULL(PBMP_OVERSUB(unit))) {
   7986         port_oversub = 1;
   7987     }
   7988 
   7989     if ((speed >= 1000) && (speed < 20000)) {
   7990         hdrm = port_oversub ? 189 : 166;
   7991     } else if ((speed >= 20000) && (speed <= 30000)) {
   7992         hdrm = port_oversub ? 217 : 194;
   7993     } else if ((speed >= 30000) && (speed <= 42000)) {
   7994         hdrm = port_oversub ? 340 : 286;
   7995     } else if ((speed >= 50000) && (speed < 100000)) {
   7996         hdrm = port_oversub ? 358 : 304;
   7997     } else if (speed >= 100000) {
   7998         hdrm = port_oversub ? 648 : 519;
   7999     } else {
   8000         hdrm = port_oversub ? 189 : 166;
   8001     }
   8002     return hdrm;
   8003 }
   8004 
   8005 /* Function to get the number of ports present in a given Port Macro */
   8006 int
   8007 soc_th_ports_per_pm_get(int unit, int pm_id)
   8008 {
   8009     soc_info_t *si;
   8010     int phy_port_base, num_ports = 0;
   8011 
   8012     si = &SOC_INFO(unit);
   8013     if (pm_id >= _TH_PBLKS_PER_DEV) {
   8014        return SOC_E_PARAM;
   8015     }
   8016     phy_port_base = 1 + (pm_id * _TH_PORTS_PER_PBLK);
   8017 
   8018     if (si->port_p2l_mapping[phy_port_base] != -1) {
   8019         num_ports = 1;
   8020         if ((si->port_num_lanes[phy_port_base] == 2) &&
   8021             (si->port_p2l_mapping[phy_port_base + 2] != -1)) {
   8022             /* for cases when num_lanes is given in the config (40g).
   8023              */
   8024             num_ports = 2;
   8025         }
   8026 
   8027         /* When phy_port_base + 1 is valid,
   8028          *      All 4 ports of the PM(port macro) are valid.
   8029          * When phy_port_base + 2 is valid,
   8030          *      The PM is operating in Dual lane mode
   8031          */
   8032         if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
   8033             num_ports = 4;
   8034             if (si->port_p2l_mapping[phy_port_base + 2] == -1) {
   8035                 num_ports = 2;
   8036             }
   8037         } else if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
   8038             num_ports = 2;
   8039         }
   8040     }
   8041     return num_ports;
   8042 }
   8043 
   8044 /* Function to reserve cells for CutThru(CT) and Flex ports
   8045  * Parameters:
   8046  *      unit          - (IN) Unit number.
   8047  *      pipe          - (IN) Pipe number
   8048  *      flex          - (IN) Config has Flex ports or Not
   8049  *      lossless      - (IN) MMU Lossless or Lossy
   8050  *      asf_profile   - (IN) ASF profile configuration
   8051  *      rsvd_buffer   - (OUT) Buffers reserved per resource (Ing/Egr/ASF)
   8052  * Returns:
   8053  *      SOC_E_xxx
   8054  */
   8055 int
   8056 soc_th_mmu_additional_buffer_reserve(int unit, int pipe, int flex,
   8057                                      int lossless, int asf_profile,
   8058                                      _soc_mmu_rsvd_buffer_t *rsvd_buffer)
   8059 {
   8060     /* array indexed by num_ports/pm 1, 2, 4 */
   8061     int similar_speed_asf_cells_lr[] = {20, 40, 80}; /* Line Rate */
   8062     int extreme_speed_asf_cells_lr[] = {46, 92, 184}; /* Line Rate */
   8063     int similar_speed_asf_cells_ob[] = {48, 96, 168}; /* Oversub mode */
   8064     int extreme_speed_asf_cells_ob[] = {56, 112, 224}; /* Oversub mode */
   8065     int hdrm_lossless_cells[] = {648, 358, 217};
   8066     int zero_cells[] = {0, 0, 0};
   8067     int *rsvd_asf_cells_p, *headroom_cells_p;
   8068     int id, min_pm_id = 0, max_pm_id = 0, oversub_mode = FALSE;
   8069     int pg_min_cells = 0, qgrp_min_cells = 0, hdrm_cells = 0, asf_cells = 0;
   8070     int total_reserve = 0, num_ports = 0;
   8071     uint8 two_port_pm = FALSE, four_port_pm = FALSE;
   8072     soc_info_t *si;
   8073 
   8074     si = &SOC_INFO(unit);
   8075 
   8076     if ((pipe >= NUM_PIPE(unit)) || (!rsvd_buffer)) {
   8077         return SOC_E_PARAM;
   8078     }
   8079 
   8080     sal_memset(rsvd_buffer, 0, sizeof(_soc_mmu_rsvd_buffer_t));
   8081 
   8082     if (SOC_PBMP_NOT_NULL(si->oversub_pbm)) {
   8083         oversub_mode = TRUE;
   8084     }
   8085 
   8086     rsvd_asf_cells_p = zero_cells;
   8087 
   8088     if (oversub_mode == TRUE) {
   8089         if (asf_profile == 1) {
   8090             rsvd_asf_cells_p = similar_speed_asf_cells_ob;
   8091         } else if (asf_profile == 2) {
   8092             rsvd_asf_cells_p = extreme_speed_asf_cells_ob;
   8093         }
   8094     } else {
   8095         if (asf_profile == 1) {
   8096             rsvd_asf_cells_p = similar_speed_asf_cells_lr;
   8097         } else if (asf_profile == 2) {
   8098             rsvd_asf_cells_p = extreme_speed_asf_cells_lr;
   8099         }
   8100     }
   8101 
   8102     headroom_cells_p = zero_cells;
   8103     if (flex && (lossless != 0)) {
   8104         headroom_cells_p = hdrm_lossless_cells;
   8105     }
   8106 
   8107     min_pm_id = pipe * _TH_PBLKS_PER_PIPE;
   8108     max_pm_id = min_pm_id + _TH_PBLKS_PER_PIPE;
   8109 
   8110     for (id = min_pm_id; id < max_pm_id; id++) {
   8111         num_ports = soc_th_ports_per_pm_get(unit, id);
   8112         switch (num_ports) {
   8113             case 1:
   8114                 hdrm_cells = headroom_cells_p[0];
   8115                 asf_cells = rsvd_asf_cells_p[0];
   8116                 break;
   8117             case 2:
   8118                 hdrm_cells = headroom_cells_p[1];
   8119                 asf_cells = rsvd_asf_cells_p[1];
   8120                 two_port_pm = TRUE;
   8121                 break;
   8122             case 4:
   8123                 hdrm_cells = headroom_cells_p[2];
   8124                 asf_cells = rsvd_asf_cells_p[2];
   8125                 four_port_pm = TRUE;
   8126                 break;
   8127             default:
   8128                 continue;
   8129         }
   8130         if (flex) {
   8131             
   8132             pg_min_cells = 0; /*(lossless[unit]) ? 8 : 0; */
   8133         }
   8134         qgrp_min_cells = (lossless) ? 0 : 16;
   8135         if (lossless) {
   8136             rsvd_buffer->ing_rsvd_cells += (hdrm_cells + pg_min_cells +
   8137                                             qgrp_min_cells) * num_ports;
   8138         } else {
   8139             rsvd_buffer->ing_rsvd_cells += (hdrm_cells + pg_min_cells) * num_ports;
   8140         }
   8141         rsvd_buffer->egr_rsvd_cells += qgrp_min_cells * num_ports;
   8142         rsvd_buffer->asf_rsvd_cells += asf_cells;
   8143     }
   8144 
   8145     if (asf_profile == 1) {
   8146         /* In Similar speed CT profile, cap limits in bytes are as follows
   8147          * 150K for 1 port/pm case
   8148          * 200K for 2 port/pm case
   8149          * 250K for 3/4 port/pm case
   8150          */
   8151         int cap_limit = 0;
   8152         if (four_port_pm == TRUE) {
   8153             cap_limit = 250;
   8154         } else if (two_port_pm == TRUE) {
   8155             cap_limit = 200;
   8156         } else {
   8157             cap_limit = 150;
   8158         }
   8159         /* calculating the cap_limit in cells */
   8160         cap_limit = ((cap_limit * 1024) + (_TH_MMU_BYTES_PER_CELL - 1)) /
   8161                     _TH_MMU_BYTES_PER_CELL;
   8162         cap_limit = (cap_limit + 1) / 2; /* Each pipe belongs to 2 XPEs.
   8163                                           * Hence half the value */
   8164         if (rsvd_buffer->asf_rsvd_cells > cap_limit) {
   8165             rsvd_buffer->asf_rsvd_cells = cap_limit;
   8166         }
   8167     }
   8168 
   8169     total_reserve = rsvd_buffer->ing_rsvd_cells;
   8170     total_reserve += rsvd_buffer->egr_rsvd_cells;
   8171     total_reserve += rsvd_buffer->asf_rsvd_cells;
   8172 
   8173     LOG_VERBOSE(BSL_LS_SOC_MMU,
   8174                 (BSL_META_U(unit,
   8175                             "MMU config: Cells rsvd for Pipe %d,"
   8176                             " Flex/ASF per XPE: %d, Ing: %d,"
   8177                             " Egr: %d, ASF: %d\n"),
   8178                             pipe, total_reserve, rsvd_buffer->ing_rsvd_cells,
   8179                             rsvd_buffer->egr_rsvd_cells,
   8180                             rsvd_buffer->asf_rsvd_cells));
   8181     return SOC_E_NONE;
   8182 }
   8183 
   8184 #define DEFAULT_VALUE_MAGIC (0xFFFFFF)
   8185 
   8186 STATIC void
   8187 _soc_th_mmu_config_buf_default_v5_0(int unit, _soc_mmu_cfg_buf_t *buf,
   8188                                     _soc_mmu_device_info_t *devcfg,
   8189                                     int lossless)
   8190 {
   8191 #define DEFAULT_PG_NUM 7  /* Default Priority Group Num */
   8192 #define DEFAULT_POOL_ID 0 /* Default Service/Shared Pool Id */
   8193     soc_info_t *si;
   8194     _soc_mmu_cfg_buf_pool_t *buf_pool;
   8195     _soc_mmu_cfg_buf_port_t *buf_port;
   8196     _soc_mmu_cfg_buf_port_pool_t *buf_port_pool;
   8197     _soc_mmu_cfg_buf_prigroup_t *buf_prigroup;
   8198     _soc_mmu_cfg_buf_queue_t *buf_queue;
   8199     _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue;
   8200     int max_packet_cells, default_mtu_cells;
   8201     int port, idx;
   8202     int total_pool_size = 0, egr_shared_total = 0;
   8203     int in_reserved = 0;
   8204     uint32 color_limit = 0;
   8205     int rqe_entry_shared_total, asf_rsvd = 0, ing_rsvd = 0, egr_rsvd = 0;
   8206     _soc_mmu_cfg_buf_qgroup_t *queue_grp;
   8207     int asf_profile;
   8208 
   8209     si = &SOC_INFO(unit);
   8210 
   8211     asf_profile = soc_property_get(unit, spn_ASF_MEM_PROFILE,
   8212                                    _SOC_TH_ASF_MEM_PROFILE_SIMILAR);
   8213 
   8214     LOG_VERBOSE(BSL_LS_SOC_MMU,
   8215                 (BSL_META_U(unit,
   8216                             "Initializing default MMU config(v5.3). (u=%d), "
   8217                             "Lossless %s, Flex %s, ASF profile %d\n"),
   8218                             unit, lossless ? "YES": "NO",
   8219                             si->flex_eligible ? "YES": "NO", asf_profile));
   8220     max_packet_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->max_pkt_byte +
   8221                                                    devcfg->mmu_hdr_byte,
   8222                                                    devcfg->mmu_cell_size);
   8223     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size +
   8224                                                    devcfg->mmu_hdr_byte,
   8225                                                    devcfg->mmu_cell_size);
   8226 
   8227     total_pool_size = devcfg->mmu_total_cell; /* per XPE limit */
   8228 
   8229 
   8230     for (idx = 0; idx < NUM_PIPE(unit); idx++) {
   8231         soc_th_mmu_additional_buffer_reserve(unit, idx, si->flex_eligible,
   8232                                              lossless, asf_profile,
   8233                                              &buf->rsvd_buffers[idx]);
   8234         if (asf_rsvd < buf->rsvd_buffers[idx].asf_rsvd_cells) {
   8235             asf_rsvd = buf->rsvd_buffers[idx].asf_rsvd_cells;
   8236         }
   8237         if (egr_rsvd < buf->rsvd_buffers[idx].egr_rsvd_cells) {
   8238             egr_rsvd = buf->rsvd_buffers[idx].egr_rsvd_cells;
   8239         }
   8240         if (ing_rsvd < buf->rsvd_buffers[idx].ing_rsvd_cells) {
   8241             ing_rsvd = buf->rsvd_buffers[idx].ing_rsvd_cells;
   8242         }
   8243     }
   8244 
   8245     buf->headroom = 2 * max_packet_cells;
   8246 
   8247     in_reserved += buf->headroom;
   8248 
   8249     egr_shared_total = total_pool_size - ((lossless) ? 88 : 0) -
   8250                        ((asf_rsvd + egr_rsvd) << 1);
   8251     LOG_VERBOSE(BSL_LS_SOC_MMU,
   8252                 (BSL_META_U(unit,
   8253                             "MMU config: Total Shared size: %d\n"),
   8254                             egr_shared_total));
   8255 
   8256     rqe_entry_shared_total = devcfg->total_rqe_queue_entry - 88;
   8257 
   8258     for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   8259         buf_pool = &buf->pools[idx];
   8260 
   8261         if (idx == 0) {  /* 100% scale up by 100 */
   8262             buf_pool->size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   8263             buf_pool->yellow_size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   8264             buf_pool->red_size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   8265             buf_pool->total_mcq_entry = 10000 | _MMU_CFG_BUF_PERCENT_FLAG;
   8266             buf_pool->total_rqe_entry = rqe_entry_shared_total;
   8267         } else {
   8268             buf_pool->size = 0;
   8269             buf_pool->yellow_size = 0;
   8270             buf_pool->red_size = 0;
   8271             buf_pool->total_mcq_entry = 0;
   8272             buf_pool->total_rqe_entry = 0;
   8273         }
   8274     }
   8275 
   8276     color_limit = 0 | _MMU_CFG_BUF_DYNAMIC_FLAG;
   8277     for (idx = 0; idx < SOC_TH_MMU_CFG_QGROUP_MAX; idx++) {
   8278         /* Default Settings: QGRP min will be used by Lossy Queues only */
   8279         queue_grp = &buf->qgroups[idx];
   8280         queue_grp->guarantee = 0;
   8281         queue_grp->pool_resume = 16;
   8282         queue_grp->yellow_resume = 16;
   8283         queue_grp->red_resume = 16;
   8284         if (lossless) {
   8285             queue_grp->pool_scale = -1;
   8286             queue_grp->guarantee = 0;
   8287             queue_grp->pool_limit = 0;
   8288             queue_grp->discard_enable = 1;
   8289             queue_grp->red_limit = 0;
   8290             queue_grp->yellow_limit = 0;
   8291         } else {
   8292         /* resume limits - accounted for 8 cell granularity */
   8293             queue_grp->guarantee = 16;
   8294             queue_grp->pool_limit = 0;
   8295             queue_grp->discard_enable = 1;
   8296             queue_grp->pool_scale = 8;
   8297             queue_grp->red_limit = color_limit;
   8298             queue_grp->yellow_limit = color_limit;
   8299         }
   8300     }
   8301 
   8302     PBMP_ALL_ITER(unit, port) {
   8303         if (port >= SOC_MMU_CFG_PORT_MAX) {
   8304             break;
   8305         }
   8306         buf_port = &buf->ports[port];
   8307 
   8308         /* internal priority to priority group mapping */
   8309         for (idx = 0; idx < _TH_MMU_NUM_INT_PRI; idx++) {
   8310             buf_port->pri_to_prigroup[idx] = DEFAULT_PG_NUM;
   8311         }
   8312 
   8313         /* priority group to pool mapping */
   8314         for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   8315             buf_port->prigroups[idx].pool_idx = DEFAULT_POOL_ID;
   8316         }
   8317 
   8318         for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   8319             buf_port_pool = &buf_port->pools[idx];
   8320             buf_port_pool->guarantee = 0;
   8321             buf_port_pool->pool_limit = 0;
   8322             buf_port_pool->pool_resume = 0;
   8323             if (idx == DEFAULT_POOL_ID) {
   8324                 buf_port_pool->pool_limit = total_pool_size;
   8325                 buf_port_pool->pool_resume = total_pool_size - 16;
   8326             }
   8327             in_reserved += buf_port_pool->guarantee;
   8328         }
   8329 
   8330         buf_port->pkt_size = max_packet_cells;
   8331 
   8332         /* priority group */
   8333         for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   8334             buf_prigroup = &buf_port->prigroups[idx];
   8335             buf_prigroup->guarantee = 0;
   8336             buf_prigroup->user_delay = -1;
   8337             buf_prigroup->switch_delay = -1;
   8338             buf_prigroup->pkt_size = max_packet_cells;
   8339             buf_prigroup->device_headroom_enable = 0;
   8340             buf_prigroup->pool_limit = 0;
   8341             buf_prigroup->pool_floor = 0;
   8342             buf_prigroup->pool_scale = -1;
   8343             buf_prigroup->headroom = 0;
   8344             buf_prigroup->pool_resume = 0;
   8345             buf_prigroup->flow_control_enable = 0;
   8346             if (idx == DEFAULT_PG_NUM) {
   8347                 buf_prigroup->device_headroom_enable = 1;
   8348                 buf_prigroup->flow_control_enable = lossless;
   8349                 /* Init pool_limit to DEFAULT_VALUE_MAGIC to check if user
   8350                    have pool_limit setting in config file. */
   8351                 buf_prigroup->pool_limit = DEFAULT_VALUE_MAGIC;
   8352                 if (lossless) {
   8353                     buf_prigroup->guarantee = default_mtu_cells;
   8354                     buf_prigroup->headroom =
   8355                         _soc_th_default_pg_headroom(unit, port, lossless);
   8356                     buf_prigroup->pool_scale = 8;
   8357                 } else if (IS_CPU_PORT(unit, port)) {
   8358                     buf_prigroup->headroom =
   8359                         _soc_th_default_pg_headroom(unit, port, lossless);
   8360                 }
   8361             }
   8362         }
   8363 
   8364         /* multicast queue */
   8365         for (idx = 0; idx < si->port_num_cosq[port]; idx++) {
   8366             buf_queue = &buf_port->queues[idx];
   8367 
   8368             buf_queue->qgroup_id = -1;
   8369             buf_queue->mcq_entry_guarantee = 4;
   8370             color_limit = 0 | _MMU_CFG_BUF_DYNAMIC_FLAG
   8371                             | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;;
   8372             if (lossless) {
   8373                 buf_queue->guarantee = 0;
   8374                 buf_queue->discard_enable = 0;
   8375                 buf_queue->pool_scale = -1;
   8376                 buf_queue->pool_limit = egr_shared_total;
   8377                 buf_queue->yellow_limit = egr_shared_total;
   8378                 buf_queue->red_limit = egr_shared_total;
   8379                 buf_queue->color_discard_enable = 0;
   8380                 buf_queue->pool_resume = 16;
   8381             } else {
   8382                 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   8383                     buf_queue->guarantee = 8;
   8384                 } else {
   8385                     buf_queue->guarantee = 0;
   8386                 }
   8387                 buf_queue->discard_enable = 1;
   8388                 buf_queue->pool_scale = 8;
   8389                 buf_queue->pool_limit = 0;
   8390                 buf_queue->yellow_limit = color_limit;
   8391                 buf_queue->red_limit = color_limit;
   8392                 buf_queue->color_discard_enable = 0;
   8393                 /* pool_resume - accounted for 8 cell granularity */
   8394                 buf_queue->pool_resume = 16;
   8395             }
   8396         }
   8397 
   8398         /* unicast queue */
   8399         for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) {
   8400             buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx];
   8401 
   8402             buf_queue->qgroup_id = -1;
   8403             color_limit = 0 | _MMU_CFG_BUF_DYNAMIC_FLAG
   8404                             | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;
   8405             if (lossless) {
   8406                 buf_queue->guarantee = 0;
   8407                 buf_queue->discard_enable = 0;
   8408                 buf_queue->pool_scale = -1;
   8409                 buf_queue->pool_limit = egr_shared_total;
   8410                 buf_queue->red_limit = egr_shared_total;
   8411                 buf_queue->yellow_limit = egr_shared_total;
   8412                 buf_queue->color_discard_enable = 0;
   8413                 /* resume limits - accounted for 8 cell granularity */
   8414                 buf_queue->pool_resume = 16;
   8415                 buf_queue->yellow_resume = 16;
   8416                 buf_queue->red_resume = 16;
   8417             } else {
   8418                 buf_queue->guarantee = 0;
   8419                 buf_queue->discard_enable = 1;
   8420                 buf_queue->pool_scale = 8;
   8421                 buf_queue->pool_limit = 0;
   8422                 buf_queue->red_limit = color_limit;
   8423                 buf_queue->yellow_limit = color_limit;
   8424                 buf_queue->color_discard_enable = 0;
   8425                 /* resume limits - accounted for 8 cell granularity */
   8426                 buf_queue->pool_resume = 16;
   8427                 buf_queue->yellow_resume = 16;
   8428                 buf_queue->red_resume = 16;
   8429 
   8430                 /* Enable QGROUP in LOSSY MODE */
   8431                 buf_queue->qgroup_id = 0;
   8432                 buf_queue->qgroup_min_enable = 1;
   8433             }
   8434         }
   8435 
   8436         /* queue to pool mapping */
   8437         for (idx = 0;
   8438              idx < si->port_num_cosq[port] + si->port_num_uc_cosq[port]; idx++) {
   8439             buf_port->queues[idx].pool_idx = DEFAULT_POOL_ID;
   8440         }
   8441     }
   8442 
   8443     /* RQE */
   8444     for (idx = 0; idx < _TH_MMU_NUM_RQE_QUEUES; idx++) {
   8445         buf_rqe_queue = &buf->rqe_queues[idx];
   8446         buf_rqe_queue->pool_idx = DEFAULT_POOL_ID;
   8447         buf_rqe_queue->guarantee = 8;
   8448         color_limit = 0 | _MMU_CFG_BUF_DYNAMIC_FLAG;
   8449         if (lossless) {
   8450             buf_rqe_queue->discard_enable = 0;
   8451             buf_rqe_queue->pool_scale = -1;
   8452             buf_rqe_queue->pool_limit = egr_shared_total;
   8453             buf_rqe_queue->red_limit = egr_shared_total;
   8454             buf_rqe_queue->yellow_limit = egr_shared_total;
   8455         } else {
   8456             buf_rqe_queue->discard_enable = 1;
   8457             buf_rqe_queue->pool_scale = 8;
   8458             buf_rqe_queue->pool_limit = 0;
   8459             buf_rqe_queue->red_limit = color_limit;
   8460             buf_rqe_queue->yellow_limit = color_limit;
   8461         }
   8462     }
   8463 }
   8464 STATIC int
   8465 _soc_th_pool_scale_to_limit(int size, int scale)
   8466 {
   8467     int factor = 1000;
   8468 
   8469     switch (scale) {
   8470         case 7: factor = 875; break;
   8471         case 6: factor = 750; break;
   8472         case 5: factor = 625; break;
   8473         case 4: factor = 500; break;
   8474         case 3: factor = 375; break;
   8475         case 2: factor = 250; break;
   8476         case 1: factor = 125; break;
   8477         case 0:
   8478         default:
   8479             factor = 1000; break;
   8480     }
   8481     return (size * factor)/1000;
   8482 }
   8483 
   8484 STATIC int
   8485 _soc_th_mmu_config_buf_set_hw(int unit, _soc_mmu_cfg_buf_t *buf,
   8486                               _soc_mmu_device_info_t *devcfg, int lossless)
   8487 {
   8488 #define DEFAULT_PG_NUM 7  /* Default Priority Group Num */
   8489     soc_info_t *si;
   8490     _soc_mmu_cfg_buf_pool_t *buf_pool;
   8491     _soc_mmu_cfg_buf_port_t *buf_port;
   8492     _soc_mmu_cfg_buf_qgroup_t *queue_grp;
   8493     mmu_thdo_config_qgroup_entry_t cfg_qgrp;
   8494     mmu_thdo_offset_qgroup_entry_t offset_qgrp;
   8495     _soc_mmu_cfg_buf_port_pool_t *buf_port_pool;
   8496     thdi_port_sp_config_entry_t thdi_sp_config;
   8497     thdi_port_pg_config_entry_t pg_config_mem;
   8498     _soc_mmu_cfg_buf_prigroup_t *buf_prigroup;
   8499     _soc_mmu_cfg_buf_queue_t *buf_queue;
   8500     _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue;
   8501     uint32 entry0[SOC_MAX_MEM_WORDS], entry1[SOC_MAX_MEM_WORDS];
   8502     soc_reg_t reg = INVALIDr;
   8503     soc_mem_t mem0, mem1, mem2, mem3;
   8504     uint32 fval, rval, rval2, rval3;
   8505     int base, numq, qbase, rqlen;
   8506     int port, idx, midx, pval, pri, index1;
   8507     int jumbo_frame_cells, default_mtu_cells;
   8508     int limit, ing_limit = 0, egr_limit, rlimit;
   8509     int pipe;
   8510     uint32 mgmt_hdrm, mgmt_pg_min, lb_hdrm, cpu_hdrm;
   8511     uint32 mgmt_q_min, lb_q_min, cpu_q_min, cpu_pg_min;
   8512     uint32 total_mcqe_rsvd, cpu_mcqe_rsvd;
   8513     uint32 rqe_rsvd = _TH_MMU_NUM_RQE_QUEUES * 8;
   8514     static const soc_mem_t mmu_thdi_port_mem[] = {
   8515         THDI_PORT_SP_CONFIGm,
   8516         THDI_PORT_PG_CONFIGm
   8517     };
   8518     static const soc_mem_t mmu_thdo_q_uc_mem[] = {
   8519         MMU_THDU_CONFIG_QUEUEm,
   8520         MMU_THDU_OFFSET_QUEUEm,
   8521         MMU_THDU_Q_TO_QGRP_MAPm
   8522     };
   8523     static const soc_mem_t mmu_thdo_qgrp_uc_mem[] = {
   8524         MMU_THDU_CONFIG_QGROUPm,
   8525         MMU_THDU_OFFSET_QGROUPm
   8526     };
   8527     static const soc_mem_t mmu_thdo_port_uc_mem[] = {
   8528         MMU_THDU_CONFIG_PORTm,
   8529         MMU_THDU_RESUME_PORTm
   8530     };
   8531     static const soc_mem_t mmu_thdo_q_mc_mem[] = {
   8532         MMU_THDM_DB_QUEUE_CONFIGm,
   8533         MMU_THDM_DB_QUEUE_OFFSETm,
   8534         MMU_THDM_MCQE_QUEUE_CONFIGm,
   8535         MMU_THDM_MCQE_QUEUE_OFFSETm
   8536     };
   8537 
   8538     static const soc_mem_t mmu_thdo_port_mc_mem[] = {
   8539         MMU_THDM_DB_PORTSP_CONFIGm,
   8540         MMU_THDM_MCQE_PORTSP_CONFIGm
   8541     };
   8542 
   8543     static const soc_field_t prigroup_reg[] = {
   8544         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   8545     };
   8546     static const soc_field_t prigroup_field[] = {
   8547         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   8548         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   8549         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   8550         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   8551     };
   8552     static const soc_field_t prigroup_spid_field[] = {
   8553         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   8554         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   8555     };
   8556     int pool_resume = 0;
   8557     uint16      dev_id;
   8558     uint8       rev_id;
   8559     int         ing_rsvd = 0, egr_rsvd = 0, asf_rsvd = 0;
   8560     int         pool_pg_headroom = 0, queue_guarantee = 0;
   8561 
   8562     soc_cm_get_id(unit, &dev_id, &rev_id);
   8563     si = &SOC_INFO(unit);
   8564     jumbo_frame_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->jumbo_pkt_size +
   8565                                                     devcfg->mmu_hdr_byte,
   8566                                                     devcfg->mmu_cell_size);
   8567     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size +
   8568                                                    devcfg->mmu_hdr_byte,
   8569                                                    devcfg->mmu_cell_size);
   8570     pool_resume = 2 * jumbo_frame_cells;
   8571 
   8572     rval = 0;
   8573     fval = _TH_MMU_PHYSICAL_CELLS_PER_XPE - _TH_MMU_RSVD_CELLS_CFAP_PER_XPE;
   8574 #ifdef  BCM_TOMAHAWKPLUS_SUPPORT
   8575     if (SOC_IS_TOMAHAWKPLUS(unit)) {
   8576         fval = _THP_MMU_PHYSICAL_CELLS_PER_XPE - _THP_MMU_RSVD_CELLS_CFAP_PER_XPE;
   8577     }
   8578 #endif
   8579     soc_reg_field_set(unit, CFAPFULLTHRESHOLDSETr, &rval, CFAPFULLSETPOINTf,
   8580                       fval);
   8581     SOC_IF_ERROR_RETURN(
   8582         soc_tomahawk_xpe_reg32_set(unit, CFAPFULLTHRESHOLDSETr, -1, -1,
   8583                                    -1, rval));
   8584 
   8585     rval = 0;
   8586     soc_reg_field_set(unit, CFAPFULLTHRESHOLDRESETr, &rval,
   8587                       CFAPFULLRESETPOINTf, fval - (2 * jumbo_frame_cells));
   8588     SOC_IF_ERROR_RETURN(
   8589         soc_tomahawk_xpe_reg32_set(unit, CFAPFULLTHRESHOLDRESETr, -1, -1,
   8590                                    -1, rval));
   8591 
   8592     rval = 0;
   8593     soc_reg_field_set(unit, CFAPBANKFULLr, &rval, LIMITf, 767);
   8594     for (idx = 0; idx < SOC_REG_NUMELS(unit, CFAPBANKFULLr); idx++) {
   8595         SOC_IF_ERROR_RETURN(
   8596             soc_tomahawk_xpe_reg32_set(unit, CFAPBANKFULLr, -1, -1, idx, rval));
   8597     }
   8598 
   8599     for (idx = 0; idx < NUM_PIPE(unit); idx++) {
   8600         if (asf_rsvd < buf->rsvd_buffers[idx].asf_rsvd_cells) {
   8601             asf_rsvd = buf->rsvd_buffers[idx].asf_rsvd_cells;
   8602         }
   8603         if (egr_rsvd < buf->rsvd_buffers[idx].egr_rsvd_cells) {
   8604             egr_rsvd = buf->rsvd_buffers[idx].egr_rsvd_cells;
   8605         }
   8606         if (ing_rsvd < buf->rsvd_buffers[idx].ing_rsvd_cells) {
   8607             ing_rsvd = buf->rsvd_buffers[idx].ing_rsvd_cells;
   8608         }
   8609     }
   8610     /* Converting 1 pipe value to 2 pipe (1 XPE handles 2 pipes) */
   8611     ing_rsvd <<= 1;
   8612     egr_rsvd <<= 1;
   8613     asf_rsvd <<= 1;
   8614     asf_rsvd -= 1; /* To offset approximation */
   8615 
   8616     LOG_VERBOSE(BSL_LS_SOC_MMU,
   8617                 (BSL_META_U(unit,
   8618                             "MMU config set HW: Cells rsvd per XPE: %d\n"),
   8619                             (ing_rsvd + egr_rsvd + asf_rsvd)));
   8620 
   8621     mgmt_hdrm = 0;
   8622     mgmt_q_min = (lossless) ? 0 : 16;
   8623     mgmt_pg_min = 0;
   8624     SOC_PBMP_ITER(si->management_pbm, port) {
   8625         mgmt_hdrm += _soc_th_default_pg_headroom(unit, port, lossless);
   8626     }
   8627     lb_hdrm = 0;
   8628     lb_q_min = 0;
   8629     SOC_PBMP_ITER(si->lb_pbm, port) {
   8630         lb_hdrm += _soc_th_default_pg_headroom(unit, port, lossless);
   8631         if (!lossless) {
   8632             lb_q_min += (10 * 8) >> 1; /* Taking half, 2 pipe = 1 xpe */
   8633         }
   8634     }
   8635     cpu_hdrm = _soc_th_default_pg_headroom(unit, CMIC_PORT(unit), lossless);
   8636     cpu_q_min = (lossless) ? 0 : (48 * 8);
   8637     cpu_pg_min =
   8638         buf->ports[CMIC_PORT(unit)].prigroups[DEFAULT_PG_NUM].guarantee;
   8639     /* internal priority to priority group mapping */
   8640     PBMP_ALL_ITER(unit, port) {
   8641         buf_port = &buf->ports[port];
   8642 
   8643         if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
   8644             buf_prigroup = &buf_port->prigroups[DEFAULT_PG_NUM];
   8645             mgmt_pg_min += buf_prigroup->guarantee;
   8646         }
   8647         for (idx = 0; idx < 16; idx++) {
   8648             if (idx % 8 == 0) { /* 8 fields per register */
   8649                 reg = prigroup_reg[idx / 8];
   8650                 rval = 0;
   8651             }
   8652             soc_reg_field_set(unit, reg, &rval, prigroup_field[idx],
   8653                               buf_port->pri_to_prigroup[idx]);
   8654             if (idx % 8 == 7) { /* 8 fields per register */
   8655                 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   8656             }
   8657         }
   8658     }
   8659 
   8660     /* Input thresholds */
   8661     rval = 0;
   8662     soc_reg_field_set(unit, THDI_GLOBAL_HDRM_LIMITr,
   8663                       &rval, GLOBAL_HDRM_LIMITf, buf->headroom / 2);
   8664     /* Per XPE register */
   8665     SOC_IF_ERROR_RETURN(
   8666         soc_tomahawk_xpe_reg32_set(unit, THDI_GLOBAL_HDRM_LIMITr,
   8667                                    -1, -1, 0, rval));
   8668 
   8669     for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   8670         buf_pool = &buf->pools[idx];
   8671         if (((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0)
   8672             || (buf_pool->prigroup_headroom == 0)) {
   8673             continue;
   8674         }
   8675 
   8676         if (FALSE == si->flex_eligible) {
   8677             int temp_headroom = 0;
   8678             if (lossless) {
   8679                 /* Calculate PG headroom for Layer A. CPU, No Mgmt*/
   8680                 pool_pg_headroom = ((buf_pool->prigroup_headroom -
   8681                                     (cpu_hdrm + mgmt_hdrm)) >> 1) + cpu_hdrm;
   8682                 /* Calculate PG headroom for Layer B. No CPU, Mgmt */
   8683                 temp_headroom = ((buf_pool->prigroup_headroom -
   8684                                  (cpu_hdrm + mgmt_hdrm)) >> 1) + mgmt_hdrm;
   8685                 if (temp_headroom > pool_pg_headroom) {
   8686                     pool_pg_headroom = temp_headroom;
   8687                 }
   8688             } else {
   8689                 pool_pg_headroom = cpu_hdrm;
   8690             }
   8691         } else {
   8692             int temp_headroom = 0;
   8693             /* Calculate PG headroom for Layer A. CPU, No Mgmt */
   8694             pool_pg_headroom = ing_rsvd + (lb_hdrm >> 1) + cpu_hdrm;
   8695 
   8696             /* Calculate PG headroom for Layer B. No CPU, Mgmt */
   8697             temp_headroom = ing_rsvd + (lb_hdrm >> 1) + mgmt_hdrm;
   8698             if (temp_headroom > pool_pg_headroom) {
   8699                 pool_pg_headroom = temp_headroom;
   8700             }
   8701         }
   8702 
   8703         limit = buf_pool->total -
   8704             (((buf_pool->prigroup_guarantee - mgmt_pg_min - cpu_pg_min) >> 1) +
   8705              mgmt_pg_min + asf_rsvd + pool_pg_headroom + buf->headroom) -
   8706             (lossless ? (rqe_rsvd + cpu_q_min + mgmt_q_min) : 0);
   8707         ing_limit = limit;
   8708 
   8709         if (limit > 0) {
   8710             rval = 0;
   8711             soc_reg_field_set(unit, THDI_BUFFER_CELL_LIMIT_SPr, &rval, LIMITf,
   8712                               limit);
   8713             SOC_IF_ERROR_RETURN(
   8714                 soc_tomahawk_xpe_reg32_set(unit, THDI_BUFFER_CELL_LIMIT_SPr,
   8715                                            -1, -1, idx, rval));
   8716         }
   8717 
   8718         rval = 0;
   8719         soc_reg_field_set(unit, THDI_CELL_RESET_LIMIT_OFFSET_SPr, &rval,
   8720                           OFFSETf, pool_resume);
   8721         SOC_IF_ERROR_RETURN(
   8722             soc_tomahawk_xpe_reg32_set(unit, THDI_CELL_RESET_LIMIT_OFFSET_SPr,
   8723                                        -1, -1, idx, rval));
   8724 
   8725         rval = 0;
   8726         soc_reg_field_set(unit, THDI_HDRM_BUFFER_CELL_LIMIT_HPr, &rval,
   8727                           LIMITf, pool_pg_headroom);
   8728         SOC_IF_ERROR_RETURN(
   8729             soc_tomahawk_xpe_reg32_set(unit, THDI_HDRM_BUFFER_CELL_LIMIT_HPr,
   8730                                        -1, -1, idx, rval));
   8731     }
   8732     rval = 0;
   8733     SOC_IF_ERROR_RETURN(
   8734         soc_tomahawk_xpe_reg32_set(unit, THDI_BUFFER_CELL_LIMIT_PUBLIC_POOLr,
   8735                                    -1, -1, 0, rval));
   8736 
   8737     /* Input port per port settings */
   8738     PBMP_ALL_ITER(unit, port) {
   8739         pipe = si->port_pipe[port];
   8740         buf_port = &buf->ports[port];
   8741 
   8742         rval = 0;
   8743         for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   8744             soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval,
   8745                               prigroup_spid_field[idx],
   8746                               buf_port->prigroups[idx].pool_idx);
   8747         }
   8748         SOC_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, port, rval));
   8749 
   8750         /* Per port per pool settings */
   8751         mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdi_port_mem[0])[pipe];
   8752         if (mem0 == INVALIDm) {
   8753             continue;
   8754         }
   8755         for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   8756             buf_port_pool = &buf_port->pools[idx];
   8757             midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, mmu_thdi_port_mem[0],
   8758                                               idx);
   8759             sal_memset(&thdi_sp_config, 0, sizeof(thdi_sp_config));
   8760             soc_mem_field32_set(unit, mem0, &thdi_sp_config,
   8761                                 PORT_SP_MIN_LIMITf, buf_port_pool->guarantee);
   8762             soc_mem_field32_set(unit, mem0, &thdi_sp_config,
   8763                            PORT_SP_RESUME_LIMITf, buf_port_pool->pool_resume);
   8764             soc_mem_field32_set(unit, mem0, &thdi_sp_config,
   8765                                PORT_SP_MAX_LIMITf, buf_port_pool->pool_limit);
   8766             SOC_IF_ERROR_RETURN
   8767                 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL,
   8768                                midx, &thdi_sp_config));
   8769         }
   8770 
   8771         fval = 0;
   8772         for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
   8773             if (buf_port->prigroups[idx].flow_control_enable != 0) {
   8774                 for (pri=0; pri < 16; pri++) {
   8775                     if (buf_port->pri_to_prigroup[pri] == idx) {
   8776                         fval |= 1 << pri;
   8777                     }
   8778                 }
   8779             }
   8780         }
   8781 
   8782         rval = 0;
   8783         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   8784                                           INPUT_PORT_RX_ENABLEf, 1);
   8785         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   8786                           PORT_PRI_XON_ENABLEf, fval);
   8787         soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   8788                           PORT_PAUSE_ENABLEf, fval ? 1 : 0);
   8789         SOC_IF_ERROR_RETURN(WRITE_THDI_INPUT_PORT_XON_ENABLESr(unit,
   8790                                                                port, rval));
   8791 
   8792         rval = 0;
   8793         soc_reg_field_set(unit, THDI_PORT_MAX_PKT_SIZEr, &rval,
   8794                             PORT_MAX_PKT_SIZEf, buf_port->pkt_size);
   8795         SOC_IF_ERROR_RETURN(WRITE_THDI_PORT_MAX_PKT_SIZEr(unit, rval));
   8796 
   8797         /* Input port per port per priority group settings */
   8798         mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdi_port_mem[1])[pipe];
   8799         if (mem1 == INVALIDm) {
   8800             continue;
   8801         }
   8802         for (idx = 0; idx < _TH_MMU_NUM_PG; idx++)
   8803         {
   8804             buf_prigroup = &buf->ports[port].prigroups[idx];
   8805 
   8806             midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, mmu_thdi_port_mem[1],
   8807                                               idx);
   8808             sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem));
   8809             soc_mem_field32_set(unit, mem1, &pg_config_mem,
   8810                                 PG_MIN_LIMITf, buf_prigroup->guarantee);
   8811 
   8812             if (buf_prigroup->pool_scale != -1) {
   8813                 soc_mem_field32_set(unit, mem1, &pg_config_mem,
   8814                                     PG_SHARED_DYNAMICf, 1);
   8815                 soc_mem_field32_set(unit, mem1, &pg_config_mem,
   8816                                     PG_SHARED_LIMITf,
   8817                                     buf_prigroup->pool_scale);
   8818             } else {
   8819                 if (buf_prigroup->pool_limit == DEFAULT_VALUE_MAGIC) {
   8820                     soc_mem_field32_set(unit, mem1, &pg_config_mem,
   8821                                         PG_SHARED_LIMITf,
   8822                                         ing_limit);
   8823                 } else {
   8824                     soc_mem_field32_set(unit, mem1, &pg_config_mem,
   8825                                         PG_SHARED_LIMITf,
   8826                                         buf_prigroup->pool_limit);
   8827                 }
   8828             }
   8829 
   8830             soc_mem_field32_set(unit, mem1, &pg_config_mem,
   8831                                 PG_GBL_HDRM_ENf,
   8832                                 buf_prigroup->device_headroom_enable);
   8833             soc_mem_field32_set(unit, mem1, &pg_config_mem,
   8834                                 PG_HDRM_LIMITf, buf_prigroup->headroom);
   8835 
   8836             soc_mem_field32_set(unit, mem1, &pg_config_mem,
   8837                                 PG_RESET_OFFSETf, buf_prigroup->pool_resume / 8);
   8838 
   8839             soc_mem_field32_set(unit, mem1, &pg_config_mem,
   8840                                 PG_RESET_FLOORf, buf_prigroup->pool_floor);
   8841 
   8842             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1,
   8843                                               MEM_BLOCK_ALL, midx,
   8844                                               &pg_config_mem));
   8845         }
   8846     }
   8847 
   8848 
   8849     /***********************************
   8850      * THDO
   8851  */
   8852     /* output thresholds */
   8853     SOC_IF_ERROR_RETURN(READ_OP_THDU_CONFIGr(unit, &rval));
   8854     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval,
   8855                       ENABLE_QUEUE_AND_GROUP_TICKETf, 1);
   8856     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval,
   8857                       ENABLE_UPDATE_COLOR_RESUMEf, 0);
   8858     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, MOP_POLICY_1Bf, 1);
   8859     soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, MOP_POLICY_1Af, 0);
   8860     SOC_IF_ERROR_RETURN(WRITE_OP_THDU_CONFIGr(unit, rval));
   8861 
   8862     rval = 0;
   8863     SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval));
   8864     soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval,
   8865                       MOP_POLICYf, 1);
   8866     SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval));
   8867 
   8868     /* Output port per port per queue setting for regular multicast queue */
   8869     cpu_mcqe_rsvd = 0;
   8870     total_mcqe_rsvd = 0;
   8871     egr_limit = 0;
   8872 
   8873     port = CMIC_PORT(unit);
   8874     numq = si->port_num_cosq[port];
   8875     for (idx = 0; idx < numq; idx++) {
   8876         buf_queue = &buf->ports[port].queues[idx];
   8877         cpu_mcqe_rsvd += buf_queue->mcq_entry_guarantee;
   8878     }
   8879 
   8880     /* per service pool settings */
   8881     for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   8882         buf_pool = &buf->pools[idx];
   8883         if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) {
   8884             continue;
   8885         }
   8886 
   8887         queue_guarantee = egr_rsvd;
   8888         if (lossless == 0) {
   8889             queue_guarantee += (lb_q_min + cpu_q_min + mgmt_q_min);
   8890         }
   8891         limit = buf_pool->total - (queue_guarantee + asf_rsvd + rqe_rsvd);
   8892 
   8893         if (limit <= 0) {
   8894             limit = 0;
   8895         }
   8896         egr_limit = limit;
   8897 
   8898         rval = 0;
   8899         soc_reg_field_set(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, &rval,
   8900                           SHARED_LIMITf, limit);
   8901         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8902             MMU_THDM_DB_POOL_SHARED_LIMITr, -1, -1, idx, rval));
   8903 
   8904         rval = 0;
   8905         soc_reg_field_set(unit, MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr,
   8906                           &rval, YELLOW_SHARED_LIMITf, sal_ceil_func(limit, 8));
   8907         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8908             MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr, -1, -1, idx, rval));
   8909 
   8910         rval = 0;
   8911         soc_reg_field_set(unit, MMU_THDM_DB_POOL_RED_SHARED_LIMITr,
   8912                           &rval, RED_SHARED_LIMITf, sal_ceil_func(limit, 8));
   8913         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8914             MMU_THDM_DB_POOL_RED_SHARED_LIMITr, -1, -1, idx, rval));
   8915 
   8916         rval = 0;
   8917         soc_reg_field_set(unit, MMU_THDM_DB_POOL_RESUME_LIMITr,
   8918                           &rval, RESUME_LIMITf, sal_ceil_func(limit, 8));
   8919         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8920             MMU_THDM_DB_POOL_RESUME_LIMITr, -1, -1, idx, rval));
   8921 
   8922         rval = 0;
   8923         soc_reg_field_set(unit, MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr,
   8924                           &rval, YELLOW_RESUME_LIMITf, sal_ceil_func(limit, 8));
   8925         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8926             MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr, -1, -1, idx, rval));
   8927 
   8928         rval = 0;
   8929         soc_reg_field_set(unit, MMU_THDM_DB_POOL_RED_RESUME_LIMITr,
   8930                           &rval, RED_RESUME_LIMITf, sal_ceil_func(limit, 8));
   8931         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8932             MMU_THDM_DB_POOL_RED_RESUME_LIMITr, -1, -1, idx, rval));
   8933 
   8934         /* mcq entries */
   8935         total_mcqe_rsvd = ((buf_pool->mcq_entry_reserved -
   8936                            cpu_mcqe_rsvd) >> 1) + cpu_mcqe_rsvd;
   8937         limit = buf_pool->total_mcq_entry - total_mcqe_rsvd;
   8938         if (limit <= 0) {
   8939             continue;
   8940         }
   8941 
   8942         rval = 0;
   8943         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_SHARED_LIMITr,
   8944                           &rval, SHARED_LIMITf, limit/4);
   8945         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8946             MMU_THDM_MCQE_POOL_SHARED_LIMITr, -1, -1, idx, rval));
   8947 
   8948         rval = 0;
   8949         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr,
   8950                           &rval, YELLOW_SHARED_LIMITf, limit/8);
   8951         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8952             MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr, -1, -1, idx, rval));
   8953 
   8954         rval = 0;
   8955         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr,
   8956                           &rval, RED_SHARED_LIMITf, limit/8);
   8957         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8958             MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr, -1, -1, idx, rval));
   8959 
   8960         rval = 0;
   8961         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RESUME_LIMITr,
   8962                           &rval, RESUME_LIMITf, limit/8);
   8963         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8964             MMU_THDM_MCQE_POOL_RESUME_LIMITr, -1, -1, idx, rval));
   8965 
   8966         rval = 0;
   8967         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_YELLOW_RESUME_LIMITr,
   8968                           &rval, YELLOW_RESUME_LIMITf, limit/8);
   8969         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8970             MMU_THDM_MCQE_POOL_YELLOW_RESUME_LIMITr, -1, -1, idx, rval));
   8971 
   8972         rval = 0;
   8973         soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RED_RESUME_LIMITr,
   8974                                        &rval, RED_RESUME_LIMITf, limit/8);
   8975         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   8976             MMU_THDM_MCQE_POOL_RED_RESUME_LIMITr, -1, -1, idx, rval));
   8977     }
   8978 
   8979 
   8980     PBMP_ALL_ITER(unit, port) {
   8981         pipe = si->port_pipe[port];
   8982         numq = si->port_num_cosq[port];
   8983         qbase = si->port_cosq_base[port];
   8984         if (numq == 0) {
   8985             continue;
   8986         }
   8987 
   8988         mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[0])[pipe];
   8989         mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[1])[pipe];
   8990         if ((mem0 == INVALIDm) || (mem1 == INVALIDm)) {
   8991             continue;
   8992         }
   8993         base = qbase;
   8994         for (idx = 0; idx < numq; idx++) {
   8995             buf_queue = &buf->ports[port].queues[idx];
   8996             sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_config_0_entry_t));
   8997 
   8998             soc_mem_field32_set(unit, mem0, entry0,
   8999                                 Q_MIN_LIMITf, buf_queue->guarantee);
   9000             if (buf_queue->discard_enable) {
   9001                 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_ENABLEf, 1);
   9002             }
   9003             if (buf_queue->color_discard_enable) {
   9004                 soc_mem_field32_set(unit, mem0, entry0, Q_COLOR_LIMIT_ENABLEf,
   9005                                     1);
   9006             }
   9007             if (buf_queue->pool_scale != -1) {
   9008                 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_DYNAMICf, 1);
   9009                 soc_mem_field32_set(unit, mem0, entry0,
   9010                            Q_SHARED_ALPHAf, buf_queue->pool_scale);
   9011             } else {
   9012                 /* Q_LIMIT_DYNAMIC_CELLf is 0 */
   9013                 soc_mem_field32_set(unit, mem0, entry0,
   9014                                     Q_SHARED_LIMITf, egr_limit);
   9015             }
   9016             if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   9017                 (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   9018                 soc_mem_field32_set(unit, mem0, entry0,
   9019                                     Q_COLOR_LIMIT_DYNAMICf, 1);
   9020                 soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf,
   9021                      buf_queue->yellow_limit
   9022                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   9023                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   9024                 soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf,
   9025                      buf_queue->red_limit
   9026                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   9027                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   9028             } else {
   9029                 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
   9030                 soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf,
   9031                      sal_ceil_func(egr_limit, 8));
   9032                 soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf,
   9033                      sal_ceil_func(egr_limit, 8));
   9034             }
   9035 
   9036             soc_mem_field32_set(unit, mem0, entry0,
   9037                                 Q_SPIDf, buf_queue->pool_idx);
   9038 
   9039             SOC_IF_ERROR_RETURN
   9040                 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, base + idx, entry0));
   9041 
   9042             sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_offset_entry_t));
   9043 
   9044             soc_mem_field32_set(unit, mem1, entry0, RESUME_OFFSETf, 2);
   9045             soc_mem_field32_set(unit, mem1, entry0,
   9046                                 YELLOW_RESUME_OFFSET_PROFILE_SELf, 0);
   9047             soc_mem_field32_set(unit, mem1, entry0,
   9048                                 RED_RESUME_OFFSET_PROFILE_SELf, 0);
   9049             SOC_IF_ERROR_RETURN
   9050                 (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, base + idx,
   9051                                entry0));
   9052 
   9053             rval = 0;
   9054             SOC_IF_ERROR_RETURN(
   9055                 WRITE_MMU_THDM_DB_QUEUE_RESUME_OFFSET_PROFILE_YELLOWr(unit, 0,
   9056                                                                       2));
   9057 
   9058             rval = 0;
   9059             SOC_IF_ERROR_RETURN(
   9060                 WRITE_MMU_THDM_DB_QUEUE_RESUME_OFFSET_PROFILE_REDr(unit, 0, 2));
   9061         }
   9062 
   9063         mem2 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[2])[pipe];
   9064         mem3 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[3])[pipe];
   9065         if ((mem2 == INVALIDm) || (mem3 == INVALIDm)) {
   9066             continue;
   9067         }
   9068 
   9069         for (idx = 0; idx < numq; idx++) {
   9070             buf_queue = &buf->ports[port].queues[idx];
   9071             buf_pool = &buf->pools[buf_queue->pool_idx];
   9072             if (buf_pool->total == 0) {
   9073                 continue;
   9074             }
   9075             total_mcqe_rsvd = ((buf_pool->mcq_entry_reserved -
   9076                                cpu_mcqe_rsvd) >> 1) + cpu_mcqe_rsvd;
   9077             limit = buf_pool->total_mcq_entry - total_mcqe_rsvd;
   9078             if (limit <= 0) {
   9079                 continue;
   9080             }
   9081 
   9082             sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_config_entry_t));
   9083 
   9084             soc_mem_field32_set(unit, mem2, entry0,
   9085                                 Q_MIN_LIMITf,
   9086                                 buf_queue->mcq_entry_guarantee/4);
   9087 
   9088             if (buf_queue->discard_enable) {
   9089                 soc_mem_field32_set(unit, mem2, entry0, Q_LIMIT_ENABLEf, 1);
   9090             }
   9091             if (buf_queue->color_discard_enable) {
   9092                 soc_mem_field32_set(unit, mem2, entry0, Q_COLOR_LIMIT_ENABLEf,
   9093                                     1);
   9094             }
   9095             if (buf_queue->pool_scale != -1) {
   9096                 soc_mem_field32_set(unit, mem2, entry0, Q_LIMIT_DYNAMICf, 1);
   9097                 soc_mem_field32_set(unit, mem2, entry0,
   9098                                     Q_SHARED_ALPHAf,
   9099                                     buf_queue->pool_scale);
   9100             } else {
   9101                 /* Q_LIMIT_DYNAMIC_CELLf is 0 */
   9102                 soc_mem_field32_set(unit, mem2, entry0,
   9103                                     Q_SHARED_LIMITf, limit/4);
   9104             }
   9105             if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   9106                 (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   9107                 soc_mem_field32_set(unit, mem2, entry0,
   9108                                     Q_COLOR_LIMIT_DYNAMICf, 1);
   9109                 soc_mem_field32_set(unit, mem2, entry0, YELLOW_SHARED_LIMITf,
   9110                      buf_queue->yellow_limit
   9111                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   9112                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   9113                 soc_mem_field32_set(unit, mem2, entry0, RED_SHARED_LIMITf,
   9114                      buf_queue->red_limit
   9115                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   9116                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   9117             } else {
   9118                 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
   9119                 soc_mem_field32_set(unit, mem2, entry0, YELLOW_SHARED_LIMITf,
   9120                                     limit / 8);
   9121                 soc_mem_field32_set(unit, mem2, entry0, RED_SHARED_LIMITf,
   9122                                     limit / 8);
   9123 
   9124             }
   9125 
   9126             soc_mem_field32_set(unit, mem2, entry0,
   9127                                 Q_SPIDf, buf_queue->pool_idx);
   9128 
   9129             SOC_IF_ERROR_RETURN
   9130                 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, base + idx, entry0));
   9131 
   9132             sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_offset_entry_t));
   9133 
   9134             soc_mem_field32_set(unit, mem3, entry0, RESUME_OFFSETf, 1);
   9135             soc_mem_field32_set(unit, mem3, entry0,
   9136                                 YELLOW_RESUME_OFFSET_PROFILE_SELf, 0);
   9137             soc_mem_field32_set(unit, mem3, entry0,
   9138                                 RED_RESUME_OFFSET_PROFILE_SELf, 0);
   9139             SOC_IF_ERROR_RETURN
   9140                 (soc_mem_write(unit, mem3, MEM_BLOCK_ALL, base + idx, entry0));
   9141 
   9142             rval = 0;
   9143             SOC_IF_ERROR_RETURN(
   9144                 WRITE_MMU_THDM_MCQE_QUEUE_RESUME_OFFSET_PROFILE_YELLOWr(unit, 0,
   9145                                                                         1));
   9146 
   9147             rval = 0;
   9148             SOC_IF_ERROR_RETURN(
   9149                 WRITE_MMU_THDM_MCQE_QUEUE_RESUME_OFFSET_PROFILE_REDr(unit, 0,
   9150                                                                      1));
   9151         }
   9152 
   9153         /* Per  port per pool */
   9154         for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   9155             buf_port_pool = &buf->ports[port].pools[idx];
   9156             if (buf_port_pool->pool_limit == 0) {
   9157                 continue;
   9158             }
   9159 
   9160             limit = buf_port_pool->pool_limit;
   9161             rlimit = limit - (default_mtu_cells * 2);
   9162 
   9163             mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_mc_mem[0])[pipe];
   9164             if (mem0 == INVALIDm) {
   9165                 continue;
   9166             }
   9167 
   9168             index1 = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port,
   9169                                                 mmu_thdo_port_mc_mem[0],
   9170                                                 idx);
   9171             sal_memset(entry0, 0, sizeof(mmu_thdm_db_portsp_config_entry_t));
   9172 
   9173             soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMITf, limit);
   9174             soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf,
   9175                                 limit/8);
   9176             soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf,
   9177                                 limit/8);
   9178 
   9179             soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMIT_ENABLEf,
   9180                                 !lossless);
   9181 
   9182             soc_mem_field32_set(unit, mem0, entry0, SHARED_RESUME_LIMITf,
   9183                                 rlimit/8);
   9184             soc_mem_field32_set(unit, mem0, entry0, YELLOW_RESUME_LIMITf,
   9185                                 rlimit/8);
   9186             soc_mem_field32_set(unit, mem0, entry0, RED_RESUME_LIMITf,
   9187                                 rlimit/8);
   9188 
   9189             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem0, MEM_BLOCK_ALL,
   9190                                 index1, entry0));
   9191 
   9192             mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_mc_mem[1])[pipe];
   9193             if (mem1 == INVALIDm) {
   9194                 continue;
   9195             }
   9196             buf_pool = &buf->pools[idx];
   9197             sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_portsp_config_entry_t));
   9198 
   9199             /* Use the Sky high value of MCQE, not the limit after reservation */
   9200             limit = _TH_MMU_TOTAL_MCQ_ENTRY(unit);
   9201             if (limit <= 0) {
   9202                 continue;
   9203             }
   9204 
   9205             soc_mem_field32_set(unit, mem1, entry0, SHARED_LIMITf, (limit/4) - 1);
   9206             soc_mem_field32_set(unit, mem1, entry0, YELLOW_SHARED_LIMITf,
   9207                                 (limit/8) - 1);
   9208             soc_mem_field32_set(unit, mem1, entry0, RED_SHARED_LIMITf,
   9209                                 (limit/8) - 1);
   9210 
   9211             soc_mem_field32_set(unit, mem1, entry0, SHARED_LIMIT_ENABLEf,
   9212                                 !lossless);
   9213 
   9214             soc_mem_field32_set(unit, mem1, entry0, SHARED_RESUME_LIMITf,
   9215                                 (limit/8) - 2);
   9216             soc_mem_field32_set(unit, mem1, entry0, YELLOW_RESUME_LIMITf,
   9217                                 (limit/8) - 2);
   9218             soc_mem_field32_set(unit, mem1, entry0, RED_RESUME_LIMITf,
   9219                                 (limit/8) - 2);
   9220 
   9221             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1, MEM_BLOCK_ALL,
   9222                                 index1, entry0));
   9223         }
   9224     }
   9225 
   9226     /* Output port per port per queue setting for regular unicast queue */
   9227     PBMP_ALL_ITER(unit, port) {
   9228         pipe = si->port_pipe[port];
   9229         /* Per  port per pool unicast */
   9230         for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   9231             buf_pool = &buf->pools[idx];
   9232 
   9233             if (buf_pool->total == 0) {
   9234                 continue;
   9235             }
   9236 
   9237             limit = buf_pool->total;
   9238 
   9239             mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_uc_mem[0])[pipe];
   9240             mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_uc_mem[1])[pipe];
   9241             if ((mem0 == INVALIDm) || (mem1 == INVALIDm)) {
   9242                 continue;
   9243             }
   9244             index1 = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port,
   9245                                                 mmu_thdo_port_uc_mem[0],
   9246                                                 idx);
   9247             sal_memset(entry0, 0, sizeof(mmu_thdu_config_port_entry_t));
   9248             sal_memset(entry1, 0, sizeof(mmu_thdu_resume_port_entry_t));
   9249 
   9250             soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMITf, limit);
   9251             soc_mem_field32_set(unit, mem1, entry1,
   9252                                 SHARED_RESUMEf,
   9253                                 (limit - (default_mtu_cells * 2))/8);
   9254 
   9255             soc_mem_field32_set(unit, mem0, entry0, YELLOW_LIMITf, limit/8);
   9256             soc_mem_field32_set(unit, mem1, entry1,
   9257                                 YELLOW_RESUMEf,
   9258                                 (limit - (default_mtu_cells*2))/8);
   9259 
   9260             soc_mem_field32_set(unit, mem0, entry0, RED_LIMITf, limit/8);
   9261             soc_mem_field32_set(unit, mem1, entry1,
   9262                                 RED_RESUMEf,
   9263                                 (limit - (default_mtu_cells * 2))/8);
   9264 
   9265             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem0, MEM_BLOCK_ALL,
   9266                                 index1, entry0));
   9267             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1, MEM_BLOCK_ALL,
   9268                                 index1, entry1));
   9269         }
   9270 
   9271         /* per port regular unicast queue */
   9272         numq = si->port_num_uc_cosq[port];
   9273         qbase = si->port_uc_cosq_base[port];
   9274 
   9275         if (numq == 0) {
   9276             continue;
   9277         }
   9278         base = qbase;
   9279 
   9280         mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[0])[pipe];
   9281         mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[1])[pipe];
   9282         mem2 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[2])[pipe];
   9283         if ((mem0 == INVALIDm) || (mem1 == INVALIDm) || (mem2 == INVALIDm)) {
   9284             continue;
   9285         }
   9286         for (idx = 0; idx < numq; idx++) {
   9287             buf_queue = &buf->ports[port].queues[si->port_num_cosq[port] + idx];
   9288 
   9289             sal_memset(entry0, 0, sizeof(mmu_thdu_config_queue_entry_t));
   9290             sal_memset(entry1, 0, sizeof(mmu_thdu_offset_queue_entry_t));
   9291 
   9292             soc_mem_field32_set(unit, mem0, entry0,
   9293                                 Q_MIN_LIMIT_CELLf, buf_queue->guarantee);
   9294             if (buf_queue->pool_scale != -1) {
   9295                 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_DYNAMIC_CELLf,
   9296                                     1);
   9297                 soc_mem_field32_set(unit, mem0, entry0,
   9298                                     Q_SHARED_ALPHA_CELLf,
   9299                                     buf_queue->pool_scale);
   9300             } else {
   9301                 /* Q_LIMIT_DYNAMIC_CELLf is 0 */
   9302                 soc_mem_field32_set(unit, mem0, entry0,
   9303                                     Q_SHARED_LIMIT_CELLf, egr_limit);
   9304             }
   9305             soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_CELLf,
   9306                                 buf_queue->pool_resume / 8);
   9307 
   9308             if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   9309                 (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   9310                 soc_mem_field32_set(unit, mem0, entry0,
   9311                                     Q_COLOR_LIMIT_DYNAMIC_CELLf, 1);
   9312                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_YELLOW_CELLf,
   9313                      buf_queue->yellow_limit
   9314                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   9315                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   9316                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_RED_CELLf,
   9317                      buf_queue->red_limit
   9318                               & ~_MMU_CFG_BUF_DYNAMIC_FLAG
   9319                               & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1);
   9320             } else {
   9321                 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */
   9322                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_YELLOW_CELLf,
   9323                                     sal_ceil_func(egr_limit, 8));
   9324                 soc_mem_field32_set(unit, mem0, entry0, LIMIT_RED_CELLf,
   9325                                     sal_ceil_func(egr_limit, 8));
   9326             }
   9327             soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_YELLOW_CELLf,
   9328                                 buf_queue->yellow_resume / 8);
   9329             soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_RED_CELLf,
   9330                                 buf_queue->red_resume / 8);
   9331             SOC_IF_ERROR_RETURN
   9332                 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, base + idx, entry0));
   9333 
   9334             SOC_IF_ERROR_RETURN
   9335                 (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, base + idx, entry1));
   9336 
   9337             sal_memset(entry0, 0, sizeof(mmu_thdo_q_to_qgrp_map_entry_t));
   9338             soc_mem_field32_set(unit, mem2, entry0,
   9339                                 Q_SPIDf, buf_queue->pool_idx);
   9340 
   9341             if (buf_queue->discard_enable) {
   9342                 soc_mem_field32_set(unit, mem2, entry0,
   9343                                     Q_LIMIT_ENABLEf, 1);
   9344             }
   9345             if (buf_queue->color_discard_enable) {
   9346                 soc_mem_field32_set(unit, mem2, entry0,
   9347                                     Q_COLOR_ENABLE_CELLf, 1);
   9348             }
   9349 
   9350 
   9351             if (buf_queue->qgroup_id >= 0) {
   9352                 soc_mem_field32_set(unit, mem2, entry0, QGROUP_VALIDf, 1);
   9353                 if (buf_queue->qgroup_min_enable) {
   9354                     soc_mem_field32_set(unit, mem2, entry0, USE_QGROUP_MINf, 1);
   9355                 }
   9356             }
   9357 
   9358             SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL,
   9359                                               base + idx, entry0));
   9360         }
   9361 
   9362     }
   9363 
   9364     /* configure Q-groups */
   9365     for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   9366         for (idx = 0; idx < SOC_TH_MMU_CFG_QGROUP_MAX; idx++) {
   9367             mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_qgrp_uc_mem[0])[pipe];
   9368             mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_qgrp_uc_mem[1])[pipe];
   9369             if ((mem0 == INVALIDm) || (mem1 == INVALIDm)) {
   9370                 continue;
   9371             }
   9372             queue_grp = &buf->qgroups[idx];
   9373 
   9374             sal_memset(&cfg_qgrp, 0, sizeof(cfg_qgrp));
   9375             sal_memset(&offset_qgrp, 0, sizeof(offset_qgrp));
   9376 
   9377             soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   9378                                 Q_MIN_LIMIT_CELLf, queue_grp->guarantee);
   9379 
   9380             if (queue_grp->pool_scale != -1) {
   9381                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   9382                                     Q_SHARED_ALPHA_CELLf,
   9383                                     queue_grp->pool_scale);
   9384                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   9385                                     Q_LIMIT_DYNAMIC_CELLf, 1);
   9386             } else {
   9387                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   9388                                     Q_SHARED_LIMIT_CELLf, egr_limit);
   9389             }
   9390 
   9391             if ((queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   9392                 (queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   9393                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   9394                                     Q_COLOR_LIMIT_DYNAMIC_CELLf, 1);
   9395             }
   9396 
   9397             if (queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) {
   9398                 pval = _soc_th_pool_scale_to_limit(queue_grp->pool_limit,
   9399                           queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG);
   9400                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   9401                                     LIMIT_RED_CELLf, pval/8);
   9402 
   9403             } else {
   9404                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   9405                                         LIMIT_RED_CELLf, egr_limit / 8);
   9406             }
   9407 
   9408             if (queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) {
   9409                 pval = _soc_th_pool_scale_to_limit(queue_grp->pool_limit,
   9410                           queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG);
   9411                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   9412                                     LIMIT_YELLOW_CELLf, pval/8);
   9413 
   9414             } else {
   9415                 soc_mem_field32_set(unit, mem0, &cfg_qgrp,
   9416                                     LIMIT_YELLOW_CELLf, egr_limit / 8);
   9417             }
   9418 
   9419             soc_mem_field32_set(unit, mem1, &offset_qgrp,
   9420                                 RESET_OFFSET_CELLf,
   9421                                 queue_grp->pool_resume / 8);
   9422             soc_mem_field32_set(unit, mem1, &offset_qgrp,
   9423                                 RESET_OFFSET_YELLOW_CELLf,
   9424                                 queue_grp->pool_resume / 8);
   9425             soc_mem_field32_set(unit, mem1, &offset_qgrp,
   9426                                 RESET_OFFSET_RED_CELLf,
   9427                                 queue_grp->pool_resume / 8);
   9428             SOC_IF_ERROR_RETURN
   9429                 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, idx, &cfg_qgrp));
   9430             SOC_IF_ERROR_RETURN
   9431                 (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, idx, &offset_qgrp));
   9432         }
   9433     }
   9434 
   9435 
   9436     /* RQE */
   9437     for (idx = 0; idx < _TH_MMU_NUM_RQE_QUEUES; idx++) {
   9438         buf_rqe_queue = &buf->rqe_queues[idx];
   9439 
   9440         rval = 0;
   9441         soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_MIN_PRIQr,
   9442                           &rval, MIN_LIMITf, buf_rqe_queue->guarantee);
   9443         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_LIMIT_MIN_PRIQr(unit, idx, rval));
   9444 
   9445         rval = 0;
   9446         rval2 = 0;
   9447         rval3 = 0;
   9448         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr,
   9449                             &rval, SPIDf, buf_rqe_queue->pool_idx);
   9450 
   9451         if ((buf_rqe_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) ||
   9452             (buf_rqe_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) {
   9453             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr,
   9454                               &rval, COLOR_LIMIT_DYNAMICf, 1);
   9455             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
   9456                 SHARED_RED_LIMITf,
   9457                 buf_rqe_queue->red_limit & ~_MMU_CFG_BUF_DYNAMIC_FLAG);
   9458             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
   9459                 SHARED_YELLOW_LIMITf,
   9460                 buf_rqe_queue->yellow_limit & ~_MMU_CFG_BUF_DYNAMIC_FLAG);
   9461         } else {
   9462             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
   9463                 SHARED_RED_LIMITf, buf_rqe_queue->red_limit / 8);
   9464 
   9465             soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3,
   9466                 SHARED_YELLOW_LIMITf, buf_rqe_queue->yellow_limit / 8);
   9467         }
   9468 
   9469         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr, &rval, LIMIT_ENABLEf,
   9470                           (buf_rqe_queue->discard_enable ? 1 : 0));
   9471 
   9472         if (buf_rqe_queue->pool_scale != -1) {
   9473             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr,
   9474                               &rval, DYNAMIC_ENABLEf, 1);
   9475             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
   9476                               SHARED_ALPHAf, buf_rqe_queue->pool_scale);
   9477         } else {
   9478             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
   9479                               SHARED_LIMITf, buf_rqe_queue->pool_limit);
   9480         }
   9481         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
   9482                           RESET_OFFSETf, 2);
   9483 
   9484         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIG1_PRIQr(unit, idx, rval));
   9485         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIG_PRIQr_REG32(unit, idx, rval2));
   9486         SOC_IF_ERROR_RETURN
   9487             (WRITE_MMU_THDR_DB_LIMIT_COLOR_PRIQr(unit, idx, rval3));
   9488 
   9489         rval = 0;
   9490         soc_reg_field_set(unit, MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr,
   9491                           &rval, RESET_OFFSET_REDf, 2);
   9492         soc_reg_field_set(unit, MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr,
   9493                           &rval, RESET_OFFSET_YELLOWf, 2);
   9494         SOC_IF_ERROR_RETURN
   9495             (WRITE_MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr(unit, idx, rval));
   9496 
   9497         /* queue entry */
   9498         buf_pool = &buf->pools[buf_rqe_queue->pool_idx];
   9499         fval = (buf_pool->total_rqe_entry + 8 * 11 - 1) / (8 * 11);
   9500         rval = 0;
   9501         soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_MIN_PRIQr,
   9502                           &rval, MIN_LIMITf, buf_rqe_queue->guarantee/8);
   9503         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_LIMIT_MIN_PRIQr(unit, idx, rval));
   9504 
   9505         rval = 0;
   9506         rval2 = 0;
   9507         rval3 = 0;
   9508         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr,
   9509                           &rval, SPIDf, buf_rqe_queue->pool_idx);
   9510 
   9511 
   9512         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr, &rval, LIMIT_ENABLEf,
   9513                           (buf_rqe_queue->discard_enable ? 1 : 0));
   9514 
   9515         if (buf_rqe_queue->pool_scale != -1) {
   9516             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr,
   9517                               &rval, DYNAMIC_ENABLEf, 1);
   9518             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
   9519                               SHARED_ALPHAf, buf_rqe_queue->pool_scale);
   9520             soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr,
   9521                               &rval3, SHARED_RED_LIMITf, 0);
   9522             soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr,
   9523                               &rval3, SHARED_YELLOW_LIMITf, 0);
   9524             soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr,
   9525                               &rval, COLOR_LIMIT_DYNAMICf, 1);
   9526         } else {
   9527             soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2,
   9528                               SHARED_LIMITf, fval);
   9529             soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr,
   9530                               &rval3, SHARED_RED_LIMITf, fval);
   9531             soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr,
   9532                               &rval3, SHARED_YELLOW_LIMITf, fval);
   9533             soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr,
   9534                               &rval, COLOR_LIMIT_DYNAMICf, 0);
   9535         }
   9536         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_PRIQr, &rval2,
   9537                           RESET_OFFSETf, 1);
   9538 
   9539         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG1_PRIQr(unit, idx, rval));
   9540         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG_PRIQr(unit, idx, rval2));
   9541         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_LIMIT_COLOR_PRIQr(unit, idx, rval3));
   9542 
   9543         rval = 0;
   9544         soc_reg_field_set(unit, MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr,
   9545                           &rval, RESET_OFFSET_REDf, default_mtu_cells/8);
   9546         soc_reg_field_set(unit, MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr,
   9547                           &rval, RESET_OFFSET_YELLOWf, default_mtu_cells/8);
   9548         SOC_IF_ERROR_RETURN
   9549             (WRITE_MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr(unit, idx, rval));
   9550     }
   9551 
   9552     /* per pool RQE settings */
   9553     for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
   9554         buf_pool = &buf->pools[idx];
   9555         if (((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) ||
   9556             (buf_pool->total == 0)) {
   9557             continue;
   9558         }
   9559 
   9560         limit = egr_limit;
   9561         if (!lossless) {
   9562             limit -= (buf->headroom + cpu_hdrm);
   9563         }
   9564 
   9565         rval = 0;
   9566         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_SPr,
   9567                           &rval, SHARED_LIMITf, limit);
   9568         soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_SPr, &rval, RESUME_LIMITf,
   9569                           (limit - (default_mtu_cells * 2) + 7)/8);
   9570         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   9571             MMU_THDR_DB_CONFIG_SPr, -1, -1, idx, rval));
   9572 
   9573         rval = 0;
   9574         soc_reg_field_set(unit, MMU_THDR_DB_SP_SHARED_LIMITr, &rval,
   9575                           SHARED_RED_LIMITf, (limit + 7)/8);
   9576         soc_reg_field_set(unit, MMU_THDR_DB_SP_SHARED_LIMITr, &rval,
   9577                           SHARED_YELLOW_LIMITf, (limit+7)/8);
   9578         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   9579             MMU_THDR_DB_SP_SHARED_LIMITr, -1, -1, idx, rval));
   9580 
   9581         rval = 0;
   9582         soc_reg_field_set(unit, MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, &rval,
   9583                           RESUME_RED_LIMITf,
   9584                           (limit - (default_mtu_cells * 2) + 7)/8);
   9585         soc_reg_field_set(unit, MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, &rval,
   9586                           RESUME_YELLOW_LIMITf,
   9587                           (limit - (default_mtu_cells * 2) + 7)/8);
   9588         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
   9589             MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, -1, -1, idx, rval));
   9590 
   9591         rqlen = buf_pool->total_rqe_entry/8;
   9592         if (rqlen <= 0) {
   9593             continue;
   9594         }
   9595 
   9596         rval = 0;
   9597         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_SPr, &rval,
   9598                           SHARED_LIMITf, rqlen);
   9599         soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_SPr, &rval,
   9600                           RESUME_LIMITf, rqlen - 1);
   9601         SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG_SPr(unit, idx, rval));
   9602 
   9603         rval = 0;
   9604         soc_reg_field_set(unit, MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr, &rval,
   9605                           SHARED_RED_LIMITf, rqlen);
   9606         soc_reg_field_set(unit, MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr, &rval,
   9607                           SHARED_YELLOW_LIMITf, rqlen);
   9608         SOC_IF_ERROR_RETURN
   9609             (WRITE_MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr(unit, idx, rval));
   9610 
   9611         rval = 0;
   9612         soc_reg_field_set(unit, MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr, &rval,
   9613                           RESUME_RED_LIMITf, rqlen - 1);
   9614         soc_reg_field_set(unit, MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr, &rval,
   9615                           RESUME_YELLOW_LIMITf, rqlen - 1);
   9616         SOC_IF_ERROR_RETURN
   9617             (WRITE_MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr(unit, idx, rval));
   9618     }
   9619 
   9620     /* Device level config setting */
   9621     if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0)) {
   9622         SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval));
   9623         soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval,
   9624                           UC_MC_PORTSP_COMB_ACCT_ENABLEf, 1);
   9625         SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval));
   9626     }
   9627 
   9628     rval = 0;
   9629     SOC_IF_ERROR_RETURN(READ_MMU_THDR_DB_CONFIGr(unit, &rval));
   9630     soc_reg_field_set(unit, MMU_THDR_DB_CONFIGr, &rval, MOP_POLICY_1Bf, 1);
   9631     SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIGr(unit, rval));
   9632 
   9633     return SOC_E_NONE;
   9634 }
   9635 
   9636 STATIC int
   9637 soc_th_mmu_config_init(int unit, int test_only)
   9638 {
   9639     int rv;
   9640     int lossless = 1;
   9641     _soc_mmu_cfg_buf_t *buf;
   9642     _soc_mmu_device_info_t devcfg;
   9643     soc_mmu_config_buf_default_f soc_mmu_config_buf_default = NULL;
   9644 
   9645     buf = soc_mmu_cfg_alloc(unit);
   9646     if (!buf) {
   9647         return SOC_E_MEMORY;
   9648     }
   9649 
   9650     soc_mmu_config_buf_default = _soc_th_mmu_config_buf_default_v5_0;
   9651 
   9652     if (SOC_IS_TOMAHAWKPLUS(unit)) {
   9653         lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 
   9654                                     SOC_TH_MMU_LOSSLESS_DEFAULT_DISABLE);
   9655     } else {
   9656         lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 
   9657                                     SOC_TH_MMU_LOSSLESS_DEFAULT_ENABLE);
   9658     }
   9659 
   9660     /* Update the soc_info mmu_lossless to the updated value */
   9661     SOC_INFO(unit).mmu_lossless = lossless;
   9662 
   9663     _soc_th_mmu_init_dev_config(unit, &devcfg, lossless);
   9664     soc_mmu_config_buf_default(unit, buf, &devcfg, lossless);
   9665 
   9666     if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) {
   9667         /* Override default config */
   9668         _soc_mmu_cfg_buf_read(unit, buf, &devcfg);
   9669     }
   9670     rv = _soc_mmu_cfg_buf_check(unit, buf, &devcfg);
   9671     if (!test_only) {
   9672         if (SOC_FAILURE(rv)) {
   9673             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   9674                         (BSL_META_U(unit,
   9675                                     "MMU config: Use default setting\n")));
   9676             soc_mmu_config_buf_default(unit, buf, &devcfg, lossless);
   9677             SOC_IF_ERROR_RETURN
   9678                 (_soc_mmu_cfg_buf_calculate(unit, buf, &devcfg));
   9679         }
   9680         rv = _soc_th_mmu_config_buf_set_hw(unit, buf, &devcfg, lossless);
   9681     }
   9682 
   9683     soc_mmu_cfg_free(unit, buf);
   9684 
   9685     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   9686                 (BSL_META_U(unit,
   9687                             "MMU THDI/THDO init done\n")));
   9688     return rv;
   9689 }
   9690 
   9691 STATIC int
   9692 _soc_tomahawk_mmu_init(int unit)
   9693 {
   9694     soc_info_t *si;
   9695     uint32 pipe_map;
   9696     int pipe, oversub_mode = FALSE;
   9697     uint32 rval = 0;
   9698     uint32 fval = 0;
   9699     int port, phy_port, mmu_port;
   9700     uint64 enable[_TH_PIPES_PER_DEV];
   9701     int test_only;
   9702 #ifdef BCM_TOMAHAWK2_SUPPORT
   9703     pbmp_t pbmp_mmu;
   9704 
   9705     SOC_PBMP_CLEAR(pbmp_mmu);
   9706 #endif
   9707 
   9708     si = &SOC_INFO(unit);
   9709 
   9710     soc_tomahawk_pipe_map_get(unit, &pipe_map);
   9711 
   9712     test_only = soc_property_get(unit, "simple_simulation_only", 
   9713                          (SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM)) ? TRUE : FALSE;
   9714 #ifdef BCM_TOMAHAWK2_SUPPORT
   9715     if (SOC_IS_TOMAHAWK2(unit)) {
   9716         SOC_IF_ERROR_RETURN(soc_th2_mmu_config_init(unit, test_only));
   9717     } else
   9718 #endif
   9719     {
   9720         SOC_IF_ERROR_RETURN(soc_th_mmu_config_init(unit, test_only));
   9721     }
   9722 
   9723     if (SOC_PBMP_NOT_NULL(si->oversub_pbm)) {
   9724         oversub_mode = TRUE;
   9725         SOC_IF_ERROR_RETURN
   9726             (soc_tomahawk_sc_reg32_get(unit, MMU_1DBG_Cr, -1, -1, 0, &rval));
   9727         soc_reg_field_set(unit, MMU_1DBG_Cr, &rval, FIELD_Af, 1);
   9728         SOC_IF_ERROR_RETURN
   9729             (soc_tomahawk_sc_reg32_set(unit, MMU_1DBG_Cr, -1, -1, 0, rval));
   9730         rval = 0xffffffff;
   9731         SOC_IF_ERROR_RETURN
   9732             (soc_tomahawk_sc_reg32_set(unit, MMU_1DBG_Ar, -1, -1, 0, rval));
   9733     }
   9734 
   9735     sal_memset(enable, 0, sizeof(enable));
   9736     PBMP_ALL_ITER(unit, port) {
   9737         pipe = si->port_pipe[port];
   9738         phy_port = si->port_l2p_mapping[port];
   9739         mmu_port = si->port_p2m_mapping[phy_port];
   9740 #ifdef BCM_TOMAHAWK2_SUPPORT
   9741         SOC_PBMP_PORT_ADD(pbmp_mmu, mmu_port);
   9742 #endif
   9743         if (mmu_port & 0x20) {
   9744             u64_H(enable[pipe]) |= 1 << (mmu_port & 0x1f);
   9745         } else {
   9746             u64_L(enable[pipe]) |= 1 << (mmu_port & 0x1f);
   9747         }
   9748         if (oversub_mode) {
   9749             rval = 0;
   9750             if (si->port_speed_max[port] >= 100000) {
   9751                 fval = 140;
   9752             } else if (si->port_speed_max[port] >= 40000) {
   9753                 fval = 60;
   9754             } else if (si->port_speed_max[port] >= 25000) {
   9755                 fval = 40;
   9756             } else if (si->port_speed_max[port] >= 20000) {
   9757                 fval = 30;
   9758             } else {
   9759                 fval = 15;
   9760             }
   9761             soc_reg_field_set(unit, MMU_3DBG_Cr, &rval, FIELD_Af,
   9762                               fval + sal_rand() % 20);
   9763             SOC_IF_ERROR_RETURN
   9764                 (soc_tomahawk_sc_reg32_set(unit, MMU_3DBG_Cr, -1, port, 0, rval));
   9765         }
   9766     }
   9767 
   9768 #ifdef BCM_TOMAHAWK2_SUPPORT
   9769     if (SOC_IS_TOMAHAWK2(unit)) {
   9770         /*
   9771          * THDU_OUTPUT_PORT_RX_ENABLE_64,
   9772          * MMU_THDM_DB_PORT_RX_ENABLE_64,
   9773          * MMU_THDM_MCQE_PORT_RX_ENABLE_64,
   9774          * THDI_INPUT_PORT_XON_ENABLES.INPUT_PORT_RX_ENABLE,
   9775          * MMU RX_ENABLE registers listed above shouldn't be changed during
   9776          * run-time. Enable RX for all MMU ports that flex eligible.
   9777          */
   9778         if (si->flex_eligible) {
   9779             for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   9780                 if (!(pipe_map & (1 << pipe))) {
   9781                     continue;
   9782                 }
   9783                 for (mmu_port = 0; mmu_port < _TH2_MMU_GPORTS_PER_PIPE;
   9784                      mmu_port++) {
   9785                     u64_L(enable[pipe]) |= 1 << mmu_port;
   9786                     SOC_PBMP_PORT_ADD(pbmp_mmu,
   9787                         (mmu_port + pipe * _TH2_MMU_PORTS_OFFSET_PER_PIPE));
   9788                 }
   9789             }
   9790         }
   9791 
   9792         SOC_PBMP_ITER(pbmp_mmu, mmu_port) {
   9793             SOC_IF_ERROR_RETURN
   9794                 (soc_reg32_rawport_get(unit, THDI_INPUT_PORT_XON_ENABLESr,
   9795                                        mmu_port,0, &rval));
   9796             soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval,
   9797                               INPUT_PORT_RX_ENABLEf, 1);
   9798             SOC_IF_ERROR_RETURN
   9799                 (soc_reg32_rawport_set(unit, THDI_INPUT_PORT_XON_ENABLESr,
   9800                                        mmu_port, 0, rval));
   9801         }
   9802 
   9803         /* enable WRED refresh */
   9804         SOC_IF_ERROR_RETURN(READ_WRED_REFRESH_CONTROLr(unit, &rval));
   9805         soc_reg_field_set(unit, WRED_REFRESH_CONTROLr, &rval,
   9806                                 REFRESH_DISABLEf, 0);
   9807         SOC_IF_ERROR_RETURN(WRITE_WRED_REFRESH_CONTROLr(unit, rval));
   9808 
   9809     }
   9810 #endif /* BCM_TOMAHAWK2_SUPPORT */
   9811 
   9812 #ifdef BCM_WARM_BOOT_SUPPORT
   9813     if (!SOC_WARM_BOOT(unit))
   9814 #endif
   9815     {
   9816         for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   9817             if (!(pipe_map & (1 << pipe))) {
   9818                 continue;
   9819             }
   9820             SOC_IF_ERROR_RETURN
   9821                 (soc_tomahawk_xpe_reg_set(unit, THDU_OUTPUT_PORT_RX_ENABLE_64r,
   9822                                           -1, pipe, 0, enable[pipe]));
   9823         }
   9824 
   9825         for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   9826             if (!(pipe_map & (1 << pipe))) {
   9827                 continue;
   9828             }
   9829             SOC_IF_ERROR_RETURN
   9830                 (soc_tomahawk_xpe_reg_set(unit, MMU_THDM_DB_PORT_RX_ENABLE_64r,
   9831                                           -1, pipe, 0, enable[pipe]));
   9832         }
   9833 
   9834         for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) {
   9835             if (!(pipe_map & (1 << pipe))) {
   9836                 continue;
   9837             }
   9838             SOC_IF_ERROR_RETURN
   9839                 (soc_tomahawk_xpe_reg_set(unit, MMU_THDM_MCQE_PORT_RX_ENABLE_64r,
   9840                                           -1, pipe, 0, enable[pipe]));
   9841         }
   9842     }
   9843     SOC_IF_ERROR_RETURN(_soc_th_post_mmu_init_update(unit));
   9844     return SOC_E_NONE;
   9845 }
   9846 
   9847 STATIC int
   9848 _soc_tomahawk_age_timer_get(int unit, int *age_seconds, int *enabled)
   9849 {
   9850     soc_control_t *soc = SOC_CONTROL(unit);
   9851 
   9852     *enabled = soc->l2x_age_pid != SAL_THREAD_ERROR &&
   9853                soc->l2x_age_enable ?
   9854                1 : 0;
   9855     *age_seconds = soc->l2x_age_pid != SAL_THREAD_ERROR &&
   9856                    soc->l2x_age_enable ?
   9857                    soc->l2x_age_interval : 0;
   9858     
   9859     return SOC_E_NONE;
   9860 }
   9861 
   9862 STATIC int
   9863 _soc_tomahawk_age_timer_max_get(int unit, int *max_seconds)
   9864 {
   9865     *max_seconds = 0x7fffffff;
   9866     return SOC_E_NONE;
   9867 }
   9868 
   9869 STATIC int
   9870 _soc_tomahawk_age_timer_set(int unit, int age_seconds, int enable)
   9871 {
   9872     soc_control_t *soc = SOC_CONTROL(unit);
   9873     sal_usecs_t interval = soc->l2x_age_interval;
   9874 
   9875     if (soc->l2x_age_interval) {
   9876         if (!enable) {
   9877             soc->l2x_age_enable = 0;
   9878         } else {
   9879             if (age_seconds) {
   9880                 SOC_CONTROL_LOCK(unit);
   9881                 soc->l2x_age_interval = age_seconds;
   9882                 SOC_CONTROL_UNLOCK(unit);
   9883             }
   9884             soc->l2x_age_enable = 1;
   9885             if (interval != age_seconds) {
   9886                 sal_sem_give(soc->l2x_age_notify);
   9887             }
   9888         }
   9889     } else {
   9890         if (enable) {
   9891             soc->l2x_age_enable = 1;
   9892             SOC_IF_ERROR_RETURN
   9893                 (soc_th_l2_bulk_age_start(unit, age_seconds));
   9894         }
   9895     }
   9896 
   9897     return SOC_E_NONE;
   9898 }
   9899 
   9900 STATIC int
   9901 _soc_tomahawk_bond_info_init(int unit)
   9902 {
   9903     soc_chip_types type = SOC_DRIVER(unit)->type;
   9904 
   9905     switch (type) {
   9906 #ifdef BCM_TOMAHAWK2_SUPPORT
   9907     case SOC_CHIP_BCM56970_A0:
   9908         return soc_tomahawk2_bond_info_init(unit);
   9909 #endif
   9910     default:
   9911         return SOC_E_NONE;
   9912     }
   9913 }
   9914 
   9915 soc_error_t
   9916 soc_th_port_speed_supported(int unit, soc_port_t port, int speed)
   9917 {
   9918     uint8 rev_id;
   9919     uint16 dev_id;
   9920     int num_lanes;
   9921     soc_info_t *si = &SOC_INFO(unit);
   9922     int phy_port;
   9923 
   9924 #ifdef BCM_TOMAHAWK2_SUPPORT
   9925     if (SOC_IS_TOMAHAWK2(unit)) {
   9926         return soc_th2_port_speed_supported(unit, port, speed);
   9927     }
   9928 #endif
   9929 
   9930     /*
   9931      * If Universal calendar was not selected at init time then
   9932      * disallow speed change to HG2 speeds.
   9933      */
   9934     if (FALSE == si->fabric_port_enable) {
   9935         if (IS_HG2_SPEED(speed)) {
   9936             /*
   9937              * Intentionally returning SOC_E_CONFIG as this is a case
   9938              * of incorrect configuration
   9939              */
   9940             return SOC_E_CONFIG;
   9941         }
   9942     }
   9943 
   9944     /*
   9945      * Management ports only support 1G, 2.5G and 10G. Flexport
   9946      * on management ports is not supported. Management ports
   9947      * are guaranteed 10G bandwidth.
   9948      */
   9949     if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
   9950         if ((1000 == speed) || (2500 == speed) || (10000 == speed)) {
   9951             return SOC_E_NONE;
   9952         } else {
   9953             return SOC_E_PARAM;
   9954         }
   9955     }
   9956 
   9957     soc_cm_get_id(unit, &dev_id, &rev_id);
   9958     num_lanes = si->port_num_lanes[port];
   9959     phy_port = si->port_l2p_mapping[port];
   9960     
   9961     /*
   9962      * Check if Core Clock Frequency supports Port Speed
   9963      */
   9964 
   9965     switch (speed) {
   9966     /* 1G, 10G, 20G, 40G, HG11, HG21, HG 42 */
   9967     case 1000:
   9968     case 10000:
   9969     case 20000:
   9970     case 40000:
   9971     case 11000:
   9972     case 21000:
   9973     case 42000:
   9974         break;
   9975 
   9976     /* 25G, 50G, 100G */
   9977     case 25000:
   9978     case 50000:
   9979     case 100000:
   9980     /* HG27, HG 53, HG 106 */
   9981     case 27000:
   9982     case 53000:
   9983     case 106000:
   9984         /* Universal Calendar */
   9985         if (si->fabric_port_enable) {
   9986             if (si->frequency < 672) {
   9987                 return SOC_E_PARAM;
   9988             }
   9989         /* Ethernet Optimized Calendar */
   9990         } else {
   9991             if (si->frequency < 645) {
   9992                 return SOC_E_PARAM;
   9993             }
   9994         }
   9995         break;
   9996 
   9997     default:
   9998        return SOC_E_PARAM; 
   9999     }
  10000 
  10001     /*
  10002      * Laying down the framework to handle SKU differences. This is
  10003      * needed because some SKUs have speed caps on certain PMs.
  10004      */
  10005     switch (dev_id) {
  10006     case BCM56168_DEVICE_ID:
  10007         /*
  10008          * The specification of FC Max lanes speed on BCM56168 as below
  10009          *     FC[0:2] FC[3:7] FC[8:9] FC[10:15] FC[16:21] FC[22:23] FC[24:29]  FC[30:31]
  10010          *      4x25    4x10    4x25     4x10      4x10      4x25      4x10       4x25
  10011          */
  10012         if (((phy_port >= 13) && (phy_port <= 32)) || \
  10013             ((phy_port >= 41) && (phy_port <= 88)) || \
  10014             ((phy_port >= 97) && (phy_port <= 120))) {
  10015             if ((10000 != speed) && (11000 != speed) && \
  10016                 (20000 != speed) && (21000 != speed) && \
  10017                 (40000 != speed) && (42000 != speed))
  10018                 return SOC_E_PARAM;
  10019         }
  10020         break;
  10021 
  10022     case BCM56961_DEVICE_ID:
  10023     case BCM56969_DEVICE_ID:
  10024         /* SERDES VCO capped at 21.875Ghz */
  10025         if ((25000 == speed) || (27000 == speed) || (speed >= 50000)) {
  10026             return SOC_E_PARAM;
  10027         }
  10028         /* Fall through to default case */
  10029 
  10030     default:
  10031         if (speed >= 100000) { /* 100G, HG106 */
  10032             if (4 != num_lanes) {
  10033                 return SOC_E_PARAM;
  10034             }
  10035         } else if (speed >= 50000) { /* 50G, HG53 */
  10036             if (2 != num_lanes) {
  10037                 return SOC_E_PARAM;
  10038             }
  10039         } else if (speed >= 40000) { /* 40G, HG42 */
  10040             if ((2 != num_lanes) && (4 != num_lanes)) {
  10041                 return SOC_E_PARAM;
  10042             }
  10043         } else if ((speed == 20000) || ( speed == 21000)) { /* 20G, HG21 */
  10044             if (2 != num_lanes) {
  10045                 return SOC_E_PARAM;
  10046             }
  10047         } else { /* 10G, HG11, 25G, HG27 */
  10048             if (1 != num_lanes) {
  10049                 return SOC_E_PARAM;
  10050             }
  10051         }
  10052     }
  10053     return SOC_E_NONE;
  10054 }
  10055 
  10056 STATIC int
  10057 soc_th_port_lanes_ctrl_info_diag(int unit, soc_th_port_lanes_t *lanes_ctrl)
  10058 {
  10059     soc_info_t *si = &SOC_INFO(unit);
  10060     int port_base, phy_port_base;
  10061     int pipe, i;
  10062 
  10063     static char *mode_name[] = {
  10064         "QUAD", "TRI_012", "TRI_023", "DUAL", "SINGLE"
  10065     };
  10066 
  10067     port_base = lanes_ctrl->port_base;
  10068     phy_port_base = si->port_l2p_mapping[port_base];
  10069     if (phy_port_base == -1) {
  10070         return SOC_E_PORT;
  10071     }
  10072 
  10073     pipe = si->port_pipe[port_base];
  10074 
  10075     LOG_CLI((BSL_META_U(unit,
  10076                         ">>>> The current port lanes control info\n")));
  10077     LOG_CLI((BSL_META_U(unit,
  10078                         "oversub mode:%s mixed sister mode:%s mixed sister port mode:%d\n"),
  10079              lanes_ctrl->oversub ? "enable" : "disable",
  10080              lanes_ctrl->os_mixed_sister ? "enable" : "disable",
  10081              lanes_ctrl->mixed_port_mode));
  10082     LOG_CLI((BSL_META_U(unit,
  10083                         "pipe:%d logical port:%d physical port:%d bindex:%d\n"),
  10084              pipe, port_base, phy_port_base, lanes_ctrl->bindex));
  10085     LOG_CLI((BSL_META_U(unit,
  10086                         "  mode(cur:%s ==>> new:%s) lanes(cur:%d ==>> new:%d)\n"),
  10087              mode_name[lanes_ctrl->cur_mode],
  10088              mode_name[lanes_ctrl->mode],
  10089              lanes_ctrl->cur_lanes, lanes_ctrl->lanes));
  10090     LOG_CLI((BSL_META_U(unit,
  10091                         "  speed class(cur:%d ==>> new:%d)\n"),
  10092              lanes_ctrl->cur_class, lanes_ctrl->class));
  10093     for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  10094         LOG_CLI((BSL_META_U(unit,
  10095                             "  %s physical port:%d (logical port:%d)\n"),
  10096                  lanes_ctrl->lanes > lanes_ctrl->cur_lanes ?
  10097                  "del" : "add",
  10098                  lanes_ctrl->phy_ports[i],
  10099                  si->port_p2l_mapping[lanes_ctrl->phy_ports[i]]));
  10100     }
  10101     if (lanes_ctrl->idb_group != -1) {
  10102         LOG_CLI((BSL_META_U(unit,
  10103                             "new idb group:%d slot:%d"),
  10104                  lanes_ctrl->idb_group, lanes_ctrl->idb_slots[0]));
  10105         if (lanes_ctrl->lanes < lanes_ctrl->cur_lanes &&
  10106             lanes_ctrl->idb_slots[0] != -1) {
  10107             LOG_CLI((BSL_META_U(unit,
  10108                                 " add:")));
  10109             for (i = 1; i < lanes_ctrl->phy_ports_len; i++) {
  10110                 LOG_CLI((BSL_META_U(unit,
  10111                                     " slot:%d"), lanes_ctrl->idb_slots[i]));
  10112             }
  10113         }
  10114         LOG_CLI((BSL_META_U(unit,
  10115                             "\n")));
  10116     }
  10117     LOG_CLI((BSL_META_U(unit,
  10118                         "cur idb group:%d slot:%d"),
  10119              lanes_ctrl->cur_idb_group, lanes_ctrl->cur_idb_slots[0]));
  10120     if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  10121         LOG_CLI((BSL_META_U(unit,
  10122                             " del:")));
  10123         /* port(s) to be removed */
  10124         for (i = 1; i < lanes_ctrl->phy_ports_len; i++) {
  10125             LOG_CLI((BSL_META_U(unit,
  10126                                 " slot:%d"), lanes_ctrl->cur_idb_slots[i]));
  10127         }
  10128     }
  10129     LOG_CLI((BSL_META_U(unit,
  10130                         "\n")));
  10131 
  10132     if (lanes_ctrl->mmu_group != -1) {
  10133         LOG_CLI((BSL_META_U(unit,
  10134                             "new mmu group:%d slot:%d"),
  10135                  lanes_ctrl->mmu_group, lanes_ctrl->mmu_slots[0]));
  10136         if (lanes_ctrl->lanes < lanes_ctrl->cur_lanes &&
  10137             lanes_ctrl->mmu_slots[0] != -1) {
  10138             LOG_CLI((BSL_META_U(unit,
  10139                                 " add:")));
  10140             /* port(s) to be added */
  10141             for (i = 1; i < lanes_ctrl->phy_ports_len; i++) {
  10142                 LOG_CLI((BSL_META_U(unit,
  10143                                     " slot:%d"), lanes_ctrl->mmu_slots[i]));
  10144             }
  10145         }
  10146         LOG_CLI((BSL_META_U(unit,
  10147                             "\n")));
  10148     }
  10149     LOG_CLI((BSL_META_U(unit,
  10150                         "cur mmu group:%d slot:%d"),
  10151              lanes_ctrl->cur_mmu_group, lanes_ctrl->cur_mmu_slots[0]));
  10152     if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  10153             LOG_CLI((BSL_META_U(unit,
  10154                                 " del:")));
  10155         /* port(s) to be removed */
  10156         for (i = 1; i < lanes_ctrl->phy_ports_len; i++) {
  10157             LOG_CLI((BSL_META_U(unit,
  10158                                 " slot:%d"), lanes_ctrl->mmu_slots[i]));
  10159         }
  10160     }
  10161     LOG_CLI((BSL_META_U(unit,
  10162                         "\n")));
  10163     return SOC_E_NONE;
  10164 }
  10165 
  10166 STATIC int
  10167 soc_th_port_lanes_migrate(int unit, soc_th_port_lanes_t *lanes_ctrl)
  10168 {
  10169     soc_info_t *si;
  10170     int port_base, phy_port, idb_port, mmu_port;
  10171     int group, pipe, slot, id;
  10172     soc_reg_t reg;
  10173     uint32 rval;
  10174     uint32 inst;
  10175 
  10176     si = &SOC_INFO(unit);
  10177     port_base = lanes_ctrl->port_base;
  10178     phy_port = si->port_l2p_mapping[port_base];
  10179     pipe = si->port_pipe[port_base];
  10180     id = si->port_serdes[port_base] & 7;
  10181 
  10182     /* Migrate only one group/slot to the destination */
  10183     if ((-1 != lanes_ctrl->cur_idb_group) &&
  10184         (-1 != lanes_ctrl->cur_mmu_group) &&
  10185         (-1 != lanes_ctrl->idb_group) &&
  10186         (-1 != lanes_ctrl->mmu_group)) {
  10187         /* Remove idb port(s) from current group */
  10188         group = lanes_ctrl->cur_idb_group;
  10189         reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe];
  10190         rval = 0;
  10191         soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 0x3f);
  10192         slot = lanes_ctrl->cur_idb_slots[0];
  10193         if (slot < 0) {
  10194             return SOC_E_INTERNAL;
  10195         }
  10196         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
  10197 
  10198         /* Add idb port(s) to new group */
  10199         group = lanes_ctrl->idb_group;
  10200         reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe];
  10201         rval = 0;
  10202         soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id);
  10203         idb_port = si->port_l2i_mapping[port_base];
  10204         soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port);
  10205         slot = lanes_ctrl->idb_slots[0];
  10206         if (slot < 0) {
  10207             return SOC_E_INTERNAL;
  10208         }
  10209         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
  10210 
  10211         /* Remove mmu port(s) from current group */
  10212         group = lanes_ctrl->cur_mmu_group;
  10213         reg = mmu_grp_tbl_regs[group];
  10214         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  10215         rval = 0;
  10216         soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 0x3f);
  10217         slot = lanes_ctrl->cur_mmu_slots[0];
  10218         if (slot < 0) {
  10219             return SOC_E_INTERNAL;
  10220         }
  10221         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
  10222 
  10223         /* Add mmu port(s) to new group */
  10224         group = lanes_ctrl->mmu_group;
  10225         reg = mmu_grp_tbl_regs[group];
  10226         rval = 0;
  10227         soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id);
  10228         mmu_port = si->port_p2m_mapping[phy_port];
  10229         soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f);
  10230         slot = lanes_ctrl->mmu_slots[0];
  10231         if (slot < 0) {
  10232             return SOC_E_INTERNAL;
  10233         }
  10234         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
  10235 
  10236     } else {
  10237         return SOC_E_INTERNAL;
  10238     }
  10239 
  10240     return SOC_E_NONE;
  10241 }
  10242 
  10243 STATIC int
  10244 soc_tomahawk_oversub_group_find(int unit, soc_th_port_lanes_t *lanes_ctrl)
  10245 {
  10246     soc_info_t *si = &SOC_INFO(unit);
  10247     soc_th_port_lanes_t re_lanes_ctrl;
  10248     soc_reg_t reg;
  10249     int port_base, phy_port_base, idb_port_base, mmu_port_base;
  10250     int port, mmu_port, id, inst;
  10251     uint32 rval, fval;
  10252     int pipe, group, slot, i;
  10253     int cur_ids[4], cur_ids_len;
  10254     int ids_len;
  10255     int cur_mmu_ids[4];
  10256     int slots[4], slots_len;
  10257     uint32 speed_max = 0, cur_speed_max;
  10258     int sp_group1 = -1, sp_group2 = -1;
  10259     int cnt_idb[_OVS_GROUP_COUNT] = {0,0,0,0,0,0};
  10260     int cnt_mmu[_OVS_GROUP_COUNT] = {0,0,0,0,0,0};
  10261     typedef struct {
  10262         int group;
  10263         int slot;
  10264         int port;
  10265         int free_slot;
  10266     } cur_group_info_t;
  10267     cur_group_info_t cur_idb[_OVS_GROUP_COUNT];
  10268     cur_group_info_t cur_mmu[_OVS_GROUP_COUNT];
  10269 
  10270     port_base = lanes_ctrl->port_base;
  10271     phy_port_base = si->port_l2p_mapping[port_base];
  10272     idb_port_base = si->port_l2i_mapping[port_base];
  10273     mmu_port_base = si->port_p2m_mapping[phy_port_base];
  10274     pipe = si->port_pipe[port_base];
  10275     sal_memset(cur_idb, -1, sizeof(cur_idb));
  10276     sal_memset(cur_mmu, -1, sizeof(cur_mmu));
  10277 
  10278     /* Figure out the new speed group */
  10279     _soc_tomahawk_flexed_port_speed_get(unit, lanes_ctrl, &speed_max);
  10280     _soc_tomahawk_speed_to_ovs_class_mapping(unit, speed_max,
  10281                                              &lanes_ctrl->class);
  10282 
  10283     /* Figure out the current speed group */
  10284     cur_speed_max = si->port_init_speed[port_base];
  10285     _soc_tomahawk_speed_to_ovs_class_mapping(unit, cur_speed_max,
  10286                                              &lanes_ctrl->cur_class);
  10287 
  10288     /* Construct new and old idb port list for oversub group replacement */
  10289     cur_idb[0].port = cur_ids[0] = idb_port_base;
  10290     ids_len = cur_ids_len = 1;
  10291 
  10292     if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) {
  10293         if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  10294             /* idb port(s) to be removed */
  10295             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  10296                 port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]];
  10297                 cur_idb[1 + i].port = cur_ids[1 + i] = si->port_l2i_mapping[port];
  10298             }
  10299             cur_ids_len += lanes_ctrl->phy_ports_len;
  10300         } else { /* idb port(s) to be added */
  10301             ids_len += lanes_ctrl->phy_ports_len;
  10302         }
  10303     }
  10304 
  10305     lanes_ctrl->idb_group = -1;
  10306     lanes_ctrl->idb_slots[0] = -1;
  10307     lanes_ctrl->cur_idb_slots[0] = -1;
  10308     for (group = 0; group < _OVS_GROUP_COUNT; group++) {
  10309         reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe];
  10310         SOC_IF_ERROR_RETURN
  10311             (soc_reg32_get(unit, reg, REG_PORT_ANY, group, &rval));
  10312         fval = soc_reg_field_get(unit, reg, rval, SPEEDf);
  10313         if (fval == 0) { /* unused idb port oversub group */
  10314             if (lanes_ctrl->idb_group == -1) {
  10315                 lanes_ctrl->idb_group = group;
  10316             }
  10317             continue;
  10318         } else {
  10319             if (fval == lanes_ctrl->class) {
  10320                 if (lanes_ctrl->idb_slots[0] == -1) { /* hasn't found the group */
  10321                     /* Find slot(s) for new idb port oversub group */
  10322                     reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe];
  10323                     slots_len = 0;
  10324                     for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
  10325                         SOC_IF_ERROR_RETURN
  10326                             (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval));
  10327                         if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) {
  10328                             continue;
  10329                         }
  10330                         slots[slots_len] = slot;
  10331                         slots_len++;
  10332                         if (slots_len == ids_len) {
  10333                             /* Enough free slots in an existing group */
  10334                             lanes_ctrl->idb_group = group;
  10335                             for (i = 0; i < slots_len; i++) {
  10336                                 lanes_ctrl->idb_slots[i] = slots[i];
  10337                             }
  10338                             break;
  10339                         }
  10340                     }
  10341                 }
  10342             }
  10343             if (fval == lanes_ctrl->cur_class) {
  10344                 if (lanes_ctrl->cur_idb_slots[0] == -1) {
  10345                     /* Find slot(s) used by the current idb port oversub group */
  10346                     reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe];
  10347                     slots_len = 0;
  10348                     lanes_ctrl->cur_idb_empty = TRUE;
  10349                     for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
  10350                         SOC_IF_ERROR_RETURN
  10351                             (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval));
  10352                         id = soc_reg_field_get(unit, reg, rval, PORT_NUMf);
  10353                         if (id == 0x3f) {
  10354                             continue;
  10355                         }
  10356                         for (i = 0; i < cur_ids_len; i++) {
  10357                             if (id == cur_idb[i].port) {
  10358                                 cur_idb[i].group  = group;
  10359                                 cur_idb[i].slot = slot;
  10360                             }
  10361                             if (id == cur_ids[i]) {
  10362                                 slots[slots_len] = slot;
  10363                                 slots_len++;
  10364                                 break;
  10365                             }
  10366                         }
  10367                         if (i == cur_ids_len) {
  10368                             lanes_ctrl->cur_idb_empty = FALSE;
  10369                         } else if (slots_len == cur_ids_len) {
  10370                             lanes_ctrl->cur_idb_group = group;
  10371                             for (i = 0; i < slots_len; i++) {
  10372                                 lanes_ctrl->cur_idb_slots[i] = slots[i];
  10373                             }
  10374                         }
  10375                         if (lanes_ctrl->cur_idb_slots[0] != -1 &&
  10376                             !lanes_ctrl->cur_idb_empty) {
  10377                             break;
  10378                         }
  10379                     }
  10380                 }
  10381             }
  10382         }
  10383         if (lanes_ctrl->idb_slots[0] != -1 &&
  10384             lanes_ctrl->cur_idb_slots[0] != -1) {
  10385             break;
  10386         }
  10387     }
  10388 
  10389     if (lanes_ctrl->idb_group == -1) {
  10390         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10391                     (BSL_META_U(unit,
  10392                                 "IDB Speed Group is Full\n")));
  10393         return SOC_E_FULL;
  10394     }
  10395 
  10396     /* Construct new and old mmu port list for oversub group replacement */
  10397     cur_mmu[0].port = cur_mmu_ids[0] = mmu_port_base & 0x3f;
  10398     ids_len = cur_ids_len = 1;
  10399     if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) {
  10400         if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  10401             /* mmu port(s) to be removed */
  10402             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  10403                 mmu_port = si->port_p2m_mapping[lanes_ctrl->phy_ports[i]];
  10404                 cur_mmu[1 + i].port = cur_mmu_ids[1 + i] = mmu_port & 0x3f;
  10405             }
  10406             cur_ids_len += lanes_ctrl->phy_ports_len;
  10407         } else { /* mmu port(s) to be added */
  10408             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  10409                 mmu_port = si->port_p2m_mapping[lanes_ctrl->phy_ports[i]];
  10410             }
  10411             ids_len += lanes_ctrl->phy_ports_len;
  10412         }
  10413     }
  10414 
  10415     lanes_ctrl->mmu_group = -1;
  10416     lanes_ctrl->mmu_slots[0] = -1;
  10417     lanes_ctrl->cur_mmu_slots[0] = -1;
  10418     for (group = 0; group < _OVS_GROUP_COUNT; group++) {
  10419         reg = OVR_SUB_GRP_CFGr;
  10420         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  10421         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, group, &rval));
  10422         fval = soc_reg_field_get(unit, reg, rval, SPEEDf);
  10423         if (fval == 0) { /* unused mmu port oversub group */
  10424             if (lanes_ctrl->mmu_group == -1) {
  10425                 lanes_ctrl->mmu_group = group;
  10426             }
  10427             continue;
  10428         } else {
  10429             if (fval == lanes_ctrl->class) {
  10430                 if (lanes_ctrl->mmu_slots[0] == -1) { /* hasn't found the group */
  10431                     /* Find slot(s) for new mmu port oversub group */
  10432                     inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  10433                     reg = mmu_grp_tbl_regs[group];
  10434                     slots_len = 0;
  10435                     for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
  10436                         SOC_IF_ERROR_RETURN
  10437                             (soc_reg32_get(unit, reg, inst, slot, &rval));
  10438                         if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) {
  10439                             continue;
  10440                         }
  10441                         slots[slots_len] = slot;
  10442                         slots_len++;
  10443                         if (slots_len == ids_len) {
  10444                             /* Enough free slots in an existing group */
  10445                             lanes_ctrl->mmu_group = group;
  10446                             for (i = 0; i < slots_len; i++) {
  10447                                 lanes_ctrl->mmu_slots[i] = slots[i];
  10448                             }
  10449                             break;
  10450                         }
  10451                     }
  10452                 }
  10453             }
  10454             if (fval == lanes_ctrl->cur_class) {
  10455                 if (lanes_ctrl->cur_mmu_slots[0] == -1) {
  10456                     /* Find slot(s) used by the currnet mmu port oversub group */
  10457                     reg = mmu_grp_tbl_regs[group];
  10458                     inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  10459                     slots_len = 0;
  10460                     lanes_ctrl->cur_mmu_empty = TRUE;
  10461                     for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
  10462                         SOC_IF_ERROR_RETURN
  10463                             (soc_reg32_get(unit, reg, inst, slot, &rval));
  10464                         id = soc_reg_field_get(unit, reg, rval, PORT_NUMf);
  10465                         if (id == 0x3f) {
  10466                             continue;
  10467                         }
  10468                         for (i = 0; i < cur_ids_len; i++) {
  10469                             if (id == cur_mmu[i].port) {
  10470                                 cur_mmu[i].group = group;
  10471                                 cur_mmu[i].slot = slot;
  10472                             }
  10473                             if (id == cur_mmu_ids[i]) {
  10474                                 slots[slots_len] = slot;
  10475                                 slots_len++;
  10476                                 break;
  10477                             }
  10478                         }
  10479                         if (i == cur_ids_len) {
  10480                             lanes_ctrl->cur_mmu_empty = FALSE;
  10481                         } else if (slots_len == cur_ids_len) {
  10482                             lanes_ctrl->cur_mmu_group = group;
  10483                             for (i = 0; i < slots_len; i++) {
  10484                                 lanes_ctrl->cur_mmu_slots[i] = slots[i];
  10485                             }
  10486                         }
  10487                         if (lanes_ctrl->cur_mmu_slots[0] != -1 &&
  10488                             !lanes_ctrl->cur_mmu_empty) {
  10489                             break;
  10490                         }
  10491                     }
  10492                 }
  10493             }
  10494         }
  10495         if (lanes_ctrl->mmu_slots[0] != -1 &&
  10496             lanes_ctrl->cur_mmu_slots[0] != -1) {
  10497             break;
  10498         }
  10499     }
  10500 
  10501     if (lanes_ctrl->mmu_group == -1) {
  10502         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10503                     (BSL_META_U(unit,
  10504                                 "MMU Speed Group is Full\n")));
  10505         return SOC_E_FULL;
  10506     }
  10507 
  10508     /* Peform validation of OS group/slots */
  10509     if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) {
  10510         if ((-1 == lanes_ctrl->cur_idb_group) ||
  10511             (-1 == lanes_ctrl->cur_mmu_group) ||
  10512             (-1 == lanes_ctrl->idb_group) ||
  10513             (-1 == lanes_ctrl->mmu_group)) {
  10514             if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  10515                 SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl));
  10516 
  10517                 for (i = 0; i < _OVS_GROUP_COUNT; i++) {
  10518                     LOG_CLI((BSL_META_U(unit,
  10519                                        "cur_idb[%d]: %d %d %d %d\n"),
  10520                              i, cur_idb[i].group, cur_idb[i].slot, cur_idb[i].port, cur_idb[i].free_slot));
  10521                     LOG_CLI((BSL_META_U(unit,
  10522                                        "cur_mmu[%d]: %d %d %d %d\n"),
  10523                              i, cur_mmu[i].group, cur_mmu[i].slot, cur_mmu[i].port, cur_mmu[i].free_slot));
  10524                 }
  10525             }
  10526 
  10527             /* Peform adjusting the group/slots which is splitted into different groups */
  10528             if (lanes_ctrl->lanes == 4 && lanes_ctrl->cur_lanes == 1 &&
  10529                 lanes_ctrl->class == 4 && lanes_ctrl->cur_class == 1) {
  10530                 /* figure out the number of same group id */
  10531                 for (i = 0; i < _OVS_GROUP_COUNT; i++) {
  10532                     cnt_idb[cur_idb[i].group]++;
  10533                     cnt_mmu[cur_mmu[i].group]++;
  10534                 }
  10535                 /* figure out one group is different with the others */
  10536                 for (i = 0; i < _OVS_GROUP_COUNT; i++) {
  10537                     if (cnt_idb[i] == 1) {
  10538                         sp_group1 = i;
  10539                     }
  10540                     if (cnt_idb[i] == 3) {
  10541                         sp_group2 = i;
  10542                     }
  10543                     if ((sp_group1 > 0) && (sp_group2 > 0))
  10544                         break;
  10545                 }
  10546                 if (sp_group1 < 0 || sp_group2 < 0) {
  10547                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10548                                 (BSL_META_U(unit,
  10549                                             "FAILED in search the number of speed group\n")));
  10550                     return SOC_E_INTERNAL;
  10551                 }
  10552 
  10553                 if (lanes_ctrl->idb_slots[0] == -1) {
  10554                     reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[sp_group2])[pipe];
  10555                     for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
  10556                         SOC_IF_ERROR_RETURN
  10557                             (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval));
  10558                         if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) {
  10559                             continue;
  10560                         }
  10561                         lanes_ctrl->idb_group = sp_group2;
  10562                         lanes_ctrl->idb_slots[0] = slot;
  10563                         break;
  10564                     }
  10565                     if (slot == _OVS_GROUP_TDM_LENGTH) {
  10566                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10567                                     (BSL_META_U(unit,
  10568                                                 "FAILED in search the empty speed group slot\n")));
  10569                         return SOC_E_INTERNAL;
  10570                     }
  10571                 }
  10572                 if (lanes_ctrl->cur_idb_slots[0] == -1) {
  10573                     for (i = 0; i < _OVS_GROUP_COUNT; i++) {
  10574                         if(cur_idb[i].group == sp_group1) {
  10575                             lanes_ctrl->cur_idb_group = cur_idb[i].group;
  10576                             lanes_ctrl->cur_idb_slots[0] = cur_idb[i].slot;
  10577                         }
  10578                     }
  10579                 }
  10580 
  10581                 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  10582                     SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl));
  10583                 }
  10584 
  10585                 for (i = 0; i < _OVS_GROUP_COUNT; i++) {
  10586                     if (cnt_mmu[i] == 1)
  10587                         sp_group1 = i;
  10588                     if (cnt_mmu[i] == 3)
  10589                         sp_group2 = i;
  10590                     if ((sp_group1 > 0) && (sp_group2 > 0))
  10591                         break;
  10592                 }
  10593                 if (sp_group1 < 0 || sp_group2 < 0) {
  10594                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10595                                 (BSL_META_U(unit,
  10596                                             "FAILED in search the number of mmu\n")));
  10597                     return SOC_E_INTERNAL;
  10598                 }
  10599                 if (lanes_ctrl->mmu_slots[0] == -1) {
  10600                     inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  10601                     reg = mmu_grp_tbl_regs[sp_group2];
  10602                     for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
  10603                         SOC_IF_ERROR_RETURN
  10604                             (soc_reg32_get(unit, reg, inst, slot, &rval));
  10605                         if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) {
  10606                             continue;
  10607                         }
  10608                         lanes_ctrl->mmu_group = sp_group2;
  10609                         lanes_ctrl->mmu_slots[0] = slot;
  10610                         break;
  10611                     }
  10612                     if (slot == _OVS_GROUP_TDM_LENGTH) {
  10613                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10614                                     (BSL_META_U(unit,
  10615                                                 "FAILED in search the empty mmu slot\n")));
  10616                         return SOC_E_INTERNAL;
  10617                     }
  10618                 }
  10619                 if (lanes_ctrl->cur_mmu_slots[0] == -1) {
  10620                     for (i = 0; i < _OVS_GROUP_COUNT; i++) {
  10621                         if(cur_mmu[i].group == sp_group1) {
  10622                             lanes_ctrl->cur_mmu_group = cur_mmu[i].group;
  10623                             lanes_ctrl->cur_mmu_slots[0] = cur_mmu[i].slot;
  10624                         }
  10625                     }
  10626                 }
  10627 
  10628                 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  10629                     SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl));
  10630                 }
  10631 
  10632                 /* Perform migrating to new group/slot */
  10633                 SOC_IF_ERROR_RETURN(soc_th_port_lanes_migrate(unit, lanes_ctrl));
  10634 
  10635                 /* Re-structure the lanes control */
  10636                 sal_memset(&re_lanes_ctrl, 0, sizeof(re_lanes_ctrl));
  10637                 re_lanes_ctrl.port_base = lanes_ctrl->port_base;
  10638                 re_lanes_ctrl.lanes = lanes_ctrl->lanes;
  10639                 SOC_IF_ERROR_RETURN
  10640                     (soc_tomahawk_port_lanes_validate(unit, &re_lanes_ctrl));
  10641                 sal_memcpy(lanes_ctrl, &re_lanes_ctrl, sizeof(re_lanes_ctrl));
  10642                 return SOC_E_NONE;
  10643             } else {
  10644                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10645                             (BSL_META_U(unit,
  10646                                         "FAILED in search lanes group\n")));
  10647                 return SOC_E_INTERNAL;
  10648             }
  10649         }
  10650 
  10651         if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  10652             /* ports being removed */
  10653             for (i = 0; i <= lanes_ctrl->phy_ports_len; i++) {
  10654                 if ((-1 == lanes_ctrl->cur_idb_slots[i]) ||
  10655                     (-1 == lanes_ctrl->cur_mmu_slots[i])) {
  10656                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10657                                 (BSL_META_U(unit,
  10658                                             "FAILED in search ports slots remove\n")));
  10659                     if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  10660                         SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl));
  10661                     }
  10662                     return SOC_E_INTERNAL;
  10663                 }
  10664             }
  10665         } else {
  10666             /* ports being added */
  10667             if ((-1 == lanes_ctrl->cur_idb_slots[0]) ||
  10668                 (-1 == lanes_ctrl->cur_mmu_slots[0])) {
  10669                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10670                             (BSL_META_U(unit,
  10671                                         "FAILED in search ports slots added\n")));
  10672                 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  10673                     SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl));
  10674                 }
  10675                 return SOC_E_INTERNAL;
  10676             }
  10677         }
  10678     }
  10679     return SOC_E_NONE;
  10680 }
  10681 
  10682 soc_error_t
  10683 soc_th_speed_set_init_ctrl(int unit, soc_th_port_lanes_t *lanes_ctrl)
  10684 {
  10685     soc_info_t *si = &SOC_INFO(unit);
  10686     soc_port_t port_base = lanes_ctrl->port_base;
  10687 
  10688     lanes_ctrl->oversub = SOC_PBMP_MEMBER(si->oversub_pbm, port_base);
  10689     if (lanes_ctrl->oversub) {
  10690         SOC_IF_ERROR_RETURN(
  10691             soc_tomahawk_oversub_group_find(unit, lanes_ctrl));
  10692     }
  10693 
  10694     return SOC_E_NONE;
  10695 }
  10696 
  10697 STATIC soc_error_t
  10698 soc_th_os_mixed_sister_port_mode_get(int unit, int initTime, soc_th_port_lanes_t *lanes_ctrl)
  10699 {
  10700     soc_info_t *si = &SOC_INFO(unit);
  10701     soc_port_t phy_port_base, phy_port;
  10702     soc_port_t port_sub, port_sis;
  10703     int port_sub_speed, port_sis_speed;
  10704     soc_port_t port_base = lanes_ctrl->port_base;
  10705 
  10706     if (lanes_ctrl->os_mixed_sister == 0) {
  10707         return SOC_E_FAIL;
  10708     }
  10709 
  10710     phy_port = si->port_l2p_mapping[port_base];
  10711     if (-1 == phy_port) {
  10712         return SOC_E_PORT;
  10713     }
  10714     phy_port_base = PORT_BLOCK_BASE_PORT(port_base);
  10715     if ((phy_port_base != phy_port) && ((phy_port_base + 2) != phy_port)) {
  10716         /* Not a controlling port */
  10717         return SOC_E_PORT;
  10718     }
  10719 
  10720     /* check mixed sister port mode */
  10721     port_sub = si->port_p2l_mapping[phy_port_base];
  10722     port_sis = si->port_p2l_mapping[phy_port_base + 2];
  10723     port_sub_speed = initTime ? si->port_speed_max[port_sub] : si->port_init_speed[port_sub];
  10724     port_sis_speed = initTime ? si->port_speed_max[port_sis] : si->port_init_speed[port_sis];
  10725 
  10726     if (!SOC_PBMP_MEMBER(si->all.disabled_bitmap, si->port_p2l_mapping[phy_port_base + 1]) ||
  10727         !SOC_PBMP_MEMBER(si->all.disabled_bitmap, si->port_p2l_mapping[phy_port_base + 3])) {
  10728         return SOC_E_PORT;
  10729     }
  10730 
  10731     if (((port_sub_speed == 50000) && (port_sis_speed == 50000)) ||
  10732         ((port_sub_speed == 53000) && (port_sis_speed == 53000))) {
  10733         lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_50_0_50_0;
  10734     } else if (((port_sub_speed == 50000) && (port_sis_speed == 25000)) ||
  10735                ((port_sub_speed == 53000) && (port_sis_speed == 27000))) {
  10736                lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_50_0_25_0;
  10737     } else if (((port_sub_speed == 25000) && (port_sis_speed == 50000)) ||
  10738                ((port_sub_speed == 27000) && (port_sis_speed == 53000))) {
  10739                lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_25_0_50_0;
  10740     } else if (((port_sub_speed == 25000) && (port_sis_speed == 25000)) ||
  10741                ((port_sub_speed == 27000) && (port_sis_speed == 27000))) {
  10742                lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_25_0_25_0;
  10743     } else if (((port_sub_speed == 40000) && (port_sis_speed == 40000)) ||
  10744                ((port_sub_speed == 43000) && (port_sis_speed == 43000))) {
  10745                lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_40_0_40_0;
  10746     } else if (((port_sub_speed == 20000) && (port_sis_speed == 20000)) ||
  10747                ((port_sub_speed == 21000) && (port_sis_speed == 21000))) {
  10748                lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_20_0_20_0;
  10749     } else {
  10750         lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_0;
  10751     }
  10752     if (initTime == FALSE) {
  10753         if ((si->port_init_speed[port_base] == 25000) ||
  10754             (si->port_init_speed[port_base] == 27000)) {
  10755             lanes_ctrl->cur_lanes = 1;
  10756         } else if ((si->port_init_speed[port_base] == 50000) ||
  10757                    (si->port_init_speed[port_base] == 40000) ||
  10758                    (si->port_init_speed[port_base] == 53000) ||
  10759                    (si->port_init_speed[port_base] == 42000) ||
  10760                    (si->port_init_speed[port_base] == 20000) ||
  10761                    (si->port_init_speed[port_base] == 21000)) {
  10762                    lanes_ctrl->cur_lanes = 2;
  10763         } else {
  10764             return SOC_E_PORT;
  10765         }
  10766     }
  10767 
  10768     return SOC_E_NONE;
  10769 }
  10770 
  10771 /*
  10772  * Function:
  10773  *      soc_tomahawk_port_lanes_validate
  10774  * Description:
  10775  *      Validate if the specified number of lanes can be configured on a port,
  10776  *      If the request can be done, fill in the control structure which will
  10777  *      be used by the routines programming the hardware.
  10778  * Parameters:
  10779  *      unit          - Device number
  10780  *      lanes_ctrl    - Control structure
  10781  *
  10782  * Each TSC can be configured into following 5 mode:
  10783  *   Lane number    0              1         2              3
  10784  *   ------------   -----------    --------  ------------   --------
  10785  *    single port   100G/40G       x         x              x
  10786  *      dual port   50G/d40G/20G   x         50G/d40G/20G   x
  10787  *   tri_023 port   50G/d40g/20G   x         25G/10G        25G/10G
  10788  *   tri_012 port   25G/10G        25G/10G   50G/d40G/20G   x
  10789  *      quad port   25G/10G        25G/10G   25G/10G        25G/10G
  10790  *
  10791  * (Note: All of the above apply to equivalent HG line rate speeds as well)
  10792  *
  10793  *          lanes                mode         valid lane index
  10794  *       ------------      ----------------   ----------------
  10795  *       new  current        new    current
  10796  *       ---  -------      -------  -------
  10797  * #1     4      1         single    quad            0
  10798  * #2     4      1         single   tri_012          0
  10799  * #3     4      2         single   tri_023          0
  10800  * #4     4      2         single    dual            0
  10801  * #5     2      1         tri_023   quad            0
  10802  * #6     2      1         tri_012   quad            2
  10803  * #7     2      1          dual    tri_023          2
  10804  * #8     2      1          dual    tri_012          0
  10805  * #9     2      4          dual    single           0
  10806  * #10    1      2         tri_023   dual            2
  10807  * #11    1      2         tri_012   dual            0
  10808  * #12    1      2          quad    tri_023          0
  10809  * #13    1      2          quad    tri_012          2
  10810  * #14    1      4          quad    single           0
  10811  * Following mode change requires 2 transition
  10812  *   - from single to tri_023: #9 + #10
  10813  *   - from single to tri_012: #9 + #11
  10814  * Following mode change are the result of lane change on multiple ports
  10815  *   - from quad to dual: #12 + #7 or #13 + #8
  10816  *   - from dual to quad: #10 + #12 or #11 + # 13
  10817  *   - from tri_023 to tri_012: #7 + #11 or #12 + #6
  10818  *   - from tri_012 to tri_023: #8 + #10 or #13 + #5
  10819  *
  10820  * Logical port number will stay the same after conversion, for example
  10821  *     converting single port to dual port, the logical port number of lane 0
  10822  *     will be changed.
  10823  */
  10824 int
  10825 soc_tomahawk_port_lanes_validate(int unit, soc_th_port_lanes_t *lanes_ctrl)
  10826 {
  10827     soc_info_t *si = &SOC_INFO(unit);
  10828     int port_base, phy_port_base;
  10829     uint32 rval;
  10830     int i;
  10831     int chk_mixed_sister = 0;
  10832 
  10833     lanes_ctrl->os_mixed_sister = si->os_mixed_sister_25_50_enable;
  10834 
  10835     /* Find physical and mmu port number for the specified port */
  10836     port_base = lanes_ctrl->port_base;
  10837     phy_port_base = si->port_l2p_mapping[port_base];
  10838     if (phy_port_base == -1) {
  10839         return SOC_E_PORT;
  10840     }
  10841     lanes_ctrl->oversub = SOC_PBMP_MEMBER(si->oversub_pbm, port_base);
  10842 
  10843     /* Find lane index for the specified port (base port) */
  10844     lanes_ctrl->bindex = SOC_PORT_BINDEX(unit, phy_port_base);
  10845 
  10846     /* Get the current mode */
  10847     SOC_IF_ERROR_RETURN(READ_CLPORT_MODE_REGr(unit, port_base, &rval));
  10848     lanes_ctrl->cur_mode = soc_reg_field_get(unit, CLPORT_MODE_REGr, rval,
  10849                                              XPORT0_CORE_PORT_MODEf);
  10850 
  10851     /* Figure out the current number of lanes */
  10852     switch (lanes_ctrl->cur_mode) {
  10853     case SOC_TH_PORT_MODE_QUAD:
  10854         lanes_ctrl->cur_lanes = 1;
  10855         break;
  10856     case SOC_TH_PORT_MODE_TRI_012:
  10857         lanes_ctrl->cur_lanes = lanes_ctrl->bindex == 0 ? 1 : 2;
  10858         break;
  10859     case SOC_TH_PORT_MODE_TRI_023:
  10860         lanes_ctrl->cur_lanes = lanes_ctrl->bindex == 0 ? 2 : 1;
  10861         break;
  10862     case SOC_TH_PORT_MODE_DUAL:
  10863         if (lanes_ctrl->os_mixed_sister == 0) {
  10864             lanes_ctrl->cur_lanes = 2;
  10865         } else {
  10866             chk_mixed_sister = 1;
  10867         }
  10868         break;
  10869     case SOC_TH_PORT_MODE_SINGLE:
  10870         lanes_ctrl->cur_lanes = 4;
  10871         break;
  10872     default:
  10873         return SOC_E_FAIL;
  10874     }
  10875 
  10876     /* check the mixed sister port mode */
  10877     if (chk_mixed_sister) {
  10878         SOC_IF_ERROR_RETURN(soc_th_os_mixed_sister_port_mode_get(unit, FALSE, lanes_ctrl));
  10879     }
  10880 
  10881     /* Validate new number of lanes */
  10882     if (lanes_ctrl->lanes == 4 || lanes_ctrl->cur_lanes == 4) {
  10883         if (lanes_ctrl->bindex & 0x3) {
  10884             return SOC_E_PARAM;
  10885         }
  10886     } else if (lanes_ctrl->lanes == 2 || lanes_ctrl->cur_lanes == 2) {
  10887         if (lanes_ctrl->bindex & 0x1) {
  10888             return SOC_E_PARAM;
  10889         }
  10890     } else if (lanes_ctrl->lanes != 1) {
  10891         return SOC_E_PARAM;
  10892     }
  10893 
  10894     /* No change to number of lanes */
  10895     if (lanes_ctrl->lanes == lanes_ctrl->cur_lanes) {
  10896         return SOC_E_NONE;
  10897     }
  10898 
  10899     /* Figure out new mode */
  10900     if (lanes_ctrl->lanes == 4) {
  10901         lanes_ctrl->mode = SOC_TH_PORT_MODE_SINGLE;
  10902     } else if (lanes_ctrl->lanes == 2) {
  10903         if (lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_QUAD) {
  10904             lanes_ctrl->mode = lanes_ctrl->bindex == 0 ?
  10905                 SOC_TH_PORT_MODE_TRI_023 : SOC_TH_PORT_MODE_TRI_012;
  10906         } else {
  10907             lanes_ctrl->mode = SOC_TH_PORT_MODE_DUAL;
  10908         }
  10909     } else{
  10910         if (lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_DUAL) {
  10911             if (lanes_ctrl->os_mixed_sister &&
  10912                 (lanes_ctrl->mixed_port_mode != MIXED_DUAL_MODE_40_0_40_0)) {
  10913                 lanes_ctrl->mode = SOC_TH_PORT_MODE_DUAL;
  10914             } else {
  10915                 lanes_ctrl->mode = lanes_ctrl->bindex == 0 ?
  10916                     SOC_TH_PORT_MODE_TRI_012 : SOC_TH_PORT_MODE_TRI_023;
  10917             }
  10918         } else {
  10919             lanes_ctrl->mode = SOC_TH_PORT_MODE_QUAD;
  10920         }
  10921     }
  10922     if (lanes_ctrl->oversub) {
  10923         if (SOC_TH_PORT_MODE_TRI_012 == lanes_ctrl->mode ||
  10924             SOC_TH_PORT_MODE_TRI_023 == lanes_ctrl->mode) {
  10925             return SOC_E_PARAM;
  10926         }
  10927     }
  10928     if (lanes_ctrl->os_mixed_sister) {
  10929         if ((lanes_ctrl->mixed_port_mode == MIXED_DUAL_MODE_50_0_25_0) &&
  10930             (SOC_TH_PORT_MODE_SINGLE == lanes_ctrl->mode) &&
  10931             (SOC_TH_PORT_MODE_DUAL == lanes_ctrl->cur_mode)) {
  10932                 return SOC_E_PARAM;
  10933         }
  10934     }
  10935 
  10936     lanes_ctrl->phy_ports_len = 0;
  10937     if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  10938         /* Figure out which port(s) to be removed */
  10939         if (lanes_ctrl->lanes == 4) {
  10940             if (lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_TRI_012 ||
  10941                 lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_QUAD) {
  10942                 if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
  10943                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  10944                         phy_port_base + 1;
  10945                 }
  10946             }
  10947             if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
  10948                 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  10949                                       phy_port_base + 2;
  10950             }
  10951             if (lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_TRI_023 ||
  10952                 lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_QUAD) {
  10953                 if (si->port_p2l_mapping[phy_port_base + 3] != -1) {
  10954                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  10955                         phy_port_base + 3;
  10956                 }
  10957             }
  10958         } else {
  10959             if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
  10960                 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  10961                                       phy_port_base + 1;
  10962             }
  10963         }
  10964     } else { /* Figure out which port(s) to be added */
  10965         if (lanes_ctrl->lanes == 2) {
  10966             if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
  10967                 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  10968                                       phy_port_base + 2;
  10969             }
  10970         } else {
  10971             if (lanes_ctrl->os_mixed_sister == 0) {
  10972                 if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
  10973                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  10974                         phy_port_base + 1;
  10975                 }
  10976             } else {
  10977                 if (((lanes_ctrl->lanes != 2) && (lanes_ctrl->cur_lanes != 1)) &&
  10978                     ((lanes_ctrl->lanes != 1) && (lanes_ctrl->cur_lanes != 2))) {
  10979                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  10980                         phy_port_base + 1;
  10981                 } /* 1x25G+1x50G,1x50G+1x25G,2x25G don't need to change number of port */
  10982                 if ((lanes_ctrl->lanes == 1) && (lanes_ctrl->cur_lanes == 4)) {
  10983                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  10984                         phy_port_base + 1;
  10985                 } /* 1x100G --> 4x25G */
  10986             }
  10987 
  10988             if (lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_SINGLE) {
  10989                 if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
  10990                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  10991                         phy_port_base + 2;
  10992                 }
  10993                 if (si->port_p2l_mapping[phy_port_base + 3] != -1) {
  10994                     lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] =
  10995                         phy_port_base + 3;
  10996                 }
  10997             }
  10998         }
  10999     }
  11000 
  11001     /* Initialize all OS group/slot info to -1 */
  11002     lanes_ctrl->cur_idb_group = lanes_ctrl->idb_group = -1;
  11003     lanes_ctrl->cur_mmu_group = lanes_ctrl->mmu_group = -1;
  11004     for (i = 0; i <= lanes_ctrl->phy_ports_len; i++) {
  11005         lanes_ctrl->idb_slots[i] = -1;
  11006         lanes_ctrl->mmu_slots[i] = -1;
  11007         lanes_ctrl->cur_idb_slots[i] = -1;
  11008         lanes_ctrl->cur_mmu_slots[i] = -1;
  11009     }
  11010 
  11011     if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  11012         SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl));
  11013     }
  11014     if (lanes_ctrl->os_mixed_sister == 0) {
  11015         if (lanes_ctrl->oversub) {
  11016             SOC_IF_ERROR_RETURN(soc_tomahawk_oversub_group_find(unit, lanes_ctrl));
  11017         }
  11018     } else {
  11019         if (((lanes_ctrl->lanes == 1) && (lanes_ctrl->cur_lanes == 4)) ||
  11020             ((lanes_ctrl->lanes == 4) && (lanes_ctrl->cur_lanes == 1)) ||
  11021             ((lanes_ctrl->lanes == 4) && (lanes_ctrl->cur_lanes == 2)) ||
  11022             ((lanes_ctrl->lanes == 2) && (lanes_ctrl->cur_lanes == 4)) ||
  11023             (((lanes_ctrl->lanes != 2) && (lanes_ctrl->cur_lanes != 1)) &&
  11024             ((lanes_ctrl->lanes != 1) && (lanes_ctrl->cur_lanes != 2)))) {
  11025             SOC_IF_ERROR_RETURN(soc_tomahawk_oversub_group_find(unit, lanes_ctrl));
  11026         }
  11027     }
  11028 
  11029     if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  11030         SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl));
  11031     }
  11032 
  11033     return SOC_E_NONE;
  11034 }
  11035 
  11036 STATIC soc_error_t
  11037 _soc_tomahawk_flexed_port_speed_get(int unit, soc_th_port_lanes_t *lanes_ctrl,
  11038                                      uint32 *port_speed)
  11039 {
  11040     uint32 vco;
  11041     soc_error_t rc;
  11042     int port = lanes_ctrl->port_base;
  11043     int higigPort = IS_HG_PORT(unit, port);
  11044     soc_info_t *si = &SOC_INFO(unit);
  11045 
  11046     if (TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) {
  11047         if (((lanes_ctrl->speed >= 100000) && (si->port_speed_max[port] < 100000)) ||
  11048             ((lanes_ctrl->speed >= 50000) && (si->port_speed_max[port] < 50000)) ||
  11049             ((lanes_ctrl->speed >= 40000) && (si->port_speed_max[port] < 40000)) ||
  11050             ((lanes_ctrl->speed >= 25000) && (si->port_speed_max[port] < 25000)) ||
  11051             ((lanes_ctrl->speed >= 20000) && (si->port_speed_max[port] < 20000)) ||
  11052             ((lanes_ctrl->speed >= 10000) && (si->port_speed_max[port] < 10000))) {
  11053             return SOC_E_CONFIG;
  11054         } else {
  11055             *port_speed = lanes_ctrl->speed;
  11056             return SOC_E_NONE;
  11057         }
  11058     }
  11059     /* Determine new port speed based on vco frequency of the PM and number of
  11060      * lanes in the flexed port.
  11061      */
  11062     rc = soc_phyctrl_redirect_control_get(unit, port, 0, 0, 0, SOC_PHY_CONTROL_VCO_FREQ, &vco);
  11063     rc = soc_phyctrl_control_get(unit, port,
  11064                                  SOC_PHY_CONTROL_VCO_FREQ,
  11065                                  &vco);
  11066     if (SOC_E_NONE != rc) {
  11067         /* Set default vco, phyctrl may not exist, for e.x. ext phy */
  11068         if (si->port_init_speed[port] >= 50000) {
  11069             vco = 25781;
  11070         } else if (si->port_init_speed[port] >= 40000) {
  11071             vco = 20625;
  11072         } else if (si->port_init_speed[port] >= 25000) {
  11073             vco = 25781;
  11074         } else {
  11075             vco = 20625;
  11076         }
  11077     }
  11078     if (lanes_ctrl->lanes == 1) {
  11079         /* Possibilities are 25G/10G */
  11080         if (vco >= 25781) {
  11081             *port_speed = higigPort ? 27000 : 25000;
  11082         } else {
  11083             *port_speed = higigPort ? 11000 : 10000;
  11084         }
  11085     } else if (lanes_ctrl->lanes == 2) {
  11086         if (vco >= 25781) {
  11087             *port_speed = higigPort ? 53000 : 50000;
  11088         } else {
  11089             *port_speed = higigPort ? 42000 : 40000;
  11090         }
  11091     } else {
  11092         /* Possibilities are 100G/40G */
  11093         if (vco >= 25781) {
  11094             *port_speed = higigPort ? 106000 : 100000;
  11095         } else {
  11096             *port_speed = higigPort ? 42000 : 40000;
  11097         }
  11098     }
  11099     if (*port_speed > SOC_INFO(unit).port_speed_max[port]) {
  11100         return SOC_E_CONFIG;
  11101     }
  11102     return SOC_E_NONE;
  11103 }
  11104 
  11105 STATIC int
  11106 _soc_tomahawk_xmt_start_cnt_update(int unit, int extra_delay)
  11107 {
  11108     int                 port;
  11109     int                 port_speed;
  11110     soc_th_asf_mode_e   mode = _SOC_TH_ASF_MODE_SAF;
  11111     soc_info_t *si;
  11112 
  11113     si = &SOC_INFO(unit);
  11114     PBMP_ALL_ITER(unit, port) {
  11115         if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) {
  11116             continue;
  11117         }
  11118         port_speed = si->port_init_speed[port];
  11119         if (!SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
  11120             SOC_IF_ERROR_RETURN(
  11121                 soc_th_port_asf_mode_get(unit, port, port_speed, &mode));
  11122         }
  11123         SOC_IF_ERROR_RETURN(
  11124             soc_th_port_asf_xmit_start_count_set(unit, port, port_speed,
  11125                                                  mode, extra_delay));
  11126     }
  11127 
  11128     return SOC_E_NONE;
  11129 }
  11130 
  11131 STATIC int
  11132 _soc_tomahawk_port_lanes_update_tdm(int unit, soc_th_port_lanes_t *lanes_ctrl)
  11133 {
  11134     soc_control_t *soc;
  11135     soc_info_t *si;
  11136     _soc_tomahawk_tdm_t *tdm;
  11137     int port_base, port, phy_port, idb_port, mmu_port;
  11138     int group, pipe, slot, id, i, clport, mode, lane, port_block_base;
  11139     int rv;
  11140     soc_reg_t reg;
  11141     uint32 rval;
  11142     uint32 inst;
  11143 
  11144     static const soc_reg_t pblk_calendar_regs[] ={
  11145         IS_PBLK0_CALENDARr, IS_PBLK1_CALENDARr,
  11146         IS_PBLK2_CALENDARr, IS_PBLK3_CALENDARr,
  11147         IS_PBLK4_CALENDARr, IS_PBLK5_CALENDARr,
  11148         IS_PBLK6_CALENDARr, IS_PBLK7_CALENDARr
  11149     };
  11150     static const soc_reg_t mmu_pblk_calendar_regs[] = {
  11151         PBLK0_CALENDARr, PBLK1_CALENDARr, PBLK2_CALENDARr, PBLK3_CALENDARr,
  11152         PBLK4_CALENDARr, PBLK5_CALENDARr, PBLK6_CALENDARr, PBLK7_CALENDARr
  11153     };
  11154     static int pblk_slots[SOC_TH_PORT_RATIO_COUNT][7] = {
  11155         { 0, -1,  0,  0, -1,  0, -1 }, /* SOC_TH_PORT_RATIO_SINGLE */
  11156         { 0, -1,  2,  0, -1,  2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_1 */
  11157         { 0,  0,  2,  0,  0,  2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_2_1 */
  11158         { 0,  2,  2,  0,  2,  2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_2 */
  11159         { 0, -1,  2,  0, -1,  3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_2_1_1 */
  11160         { 0,  0,  2,  0,  0,  3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_4_1_1 */
  11161         { 0, -1,  2,  1, -1,  2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_2 */
  11162         { 0,  2,  2,  1,  2,  2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_4 */
  11163         { 0, -1,  2,  1, -1,  3, -1 }  /* SOC_TH_PORT_RATIO_QUAD */
  11164     };
  11165 
  11166     soc = SOC_CONTROL(unit);
  11167     si = &SOC_INFO(unit);
  11168     tdm = soc->tdm_info;
  11169     port_base = lanes_ctrl->port_base;
  11170     phy_port = si->port_l2p_mapping[port_base];
  11171     pipe = si->port_pipe[port_base];
  11172     id = si->port_serdes[port_base] & 7;
  11173     clport = si->port_serdes[port_base];
  11174 
  11175     if (!SOC_PBMP_MEMBER(si->oversub_pbm, port_base)) {
  11176         rv = _soc_tomahawk_xmt_start_cnt_update(unit, 9);
  11177         if (SOC_FAILURE(rv)){
  11178             LOG_ERROR(BSL_LS_SOC_COMMON,
  11179                       (BSL_META_U(unit,
  11180                                   "FAILED in"
  11181                                   "_soc_tomahawk_xmt_start_cnt_update\n")));
  11182             return rv;
  11183         }
  11184 
  11185         rv = _soc_tomahawk_tdm_calculation(unit, FALSE, tdm);
  11186         if (SOC_FAILURE(rv)){
  11187             LOG_ERROR(BSL_LS_SOC_COMMON,
  11188                       (BSL_META_U(unit,
  11189                                   "FAILED in"
  11190                                   "_soc_tomahawk_tdm_calculation\n")));
  11191             SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
  11192             return rv;
  11193         }
  11194 
  11195         rv = _soc_tomahawk_tdm_idb_calendar_set(unit, -1, pipe);
  11196         if (SOC_FAILURE(rv)){
  11197             LOG_ERROR(BSL_LS_SOC_COMMON,
  11198                       (BSL_META_U(unit,
  11199                                   "FAILED in"
  11200                                   "_soc_tomahawk_tdm_idb_calendar_set\n")));
  11201             SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
  11202             return rv;
  11203         }
  11204 
  11205         rv = _soc_tomahawk_tdm_mmu_calendar_set(unit, -1, pipe);
  11206         if (SOC_FAILURE(rv)){
  11207             LOG_ERROR(BSL_LS_SOC_COMMON,
  11208                       (BSL_META_U(unit,
  11209                                   "FAILED in"
  11210                                   "_soc_tomahawk_tdm_mmu_calendar_set\n")));
  11211             SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
  11212             return rv;
  11213         }
  11214 
  11215         SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit));
  11216 
  11217         rv = _soc_tomahawk_xmt_start_cnt_update(unit, 0);
  11218         if (SOC_FAILURE(rv)){
  11219             LOG_ERROR(BSL_LS_SOC_COMMON,
  11220                       (BSL_META_U(unit,
  11221                                   "FAILED in"
  11222                                   "_soc_tomahawk_xmt_start_cnt_update\n")));
  11223             return rv;
  11224         }
  11225     } else if ((lanes_ctrl->class != lanes_ctrl->cur_class) ||
  11226                ((SOC_TH_SPEED_CLASS_40G == lanes_ctrl->class) &&
  11227                 (-1 != lanes_ctrl->cur_idb_group) &&
  11228                 (-1 != lanes_ctrl->cur_mmu_group) &&
  11229                 (-1 != lanes_ctrl->idb_group) &&
  11230                 (-1 != lanes_ctrl->mmu_group))) {
  11231         /* Update CLPORT details in tdm structure*/
  11232         soc_tomahawk_port_ratio_get(unit, 0 /*initTime*/, clport, &tdm->port_ratio[clport]);
  11233 
  11234         /* Remove idb port(s) from current group */
  11235         group = lanes_ctrl->cur_idb_group;
  11236         reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe];
  11237         rval = 0;
  11238         soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 0x3f);
  11239         soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, 0);
  11240         slot = lanes_ctrl->cur_idb_slots[0];
  11241         if (slot < 0) {
  11242             return SOC_E_INTERNAL;
  11243         }
  11244         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
  11245         if ((lanes_ctrl->lanes > lanes_ctrl->cur_lanes) &&
  11246             (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes)) {
  11247             /* port(s) to be removed */
  11248             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11249                 slot = lanes_ctrl->cur_idb_slots[i + 1];
  11250                 if (slot < 0) {
  11251                     return SOC_E_INTERNAL;
  11252                 }
  11253                 SOC_IF_ERROR_RETURN
  11254                     (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
  11255             }
  11256         }
  11257         if (lanes_ctrl->cur_idb_empty &&
  11258             (lanes_ctrl->idb_group != lanes_ctrl->cur_idb_group)) { /* old group become empty */
  11259             reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe];
  11260             SOC_IF_ERROR_RETURN
  11261                 (soc_reg32_set(unit, reg, REG_PORT_ANY, group, 0));
  11262         }
  11263 
  11264         /* Add idb port(s) to new group */
  11265         group = lanes_ctrl->idb_group;
  11266         reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe];
  11267         rval = 0;
  11268         soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id & 0x7);
  11269         idb_port = si->port_l2i_mapping[port_base];
  11270         soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port);
  11271         slot = lanes_ctrl->idb_slots[0] != -1 ? lanes_ctrl->idb_slots[0] : 0;
  11272         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
  11273         if ((lanes_ctrl->lanes < lanes_ctrl->cur_lanes) &&
  11274             (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes)) {
  11275             /* port(s) to be added */
  11276             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11277                 port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]];
  11278                 idb_port = si->port_l2i_mapping[port];
  11279                 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port);
  11280                 slot = lanes_ctrl->idb_slots[0] != -1 ?
  11281                     lanes_ctrl->idb_slots[i + 1] : i + 1;
  11282                 SOC_IF_ERROR_RETURN
  11283                     (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
  11284             }
  11285         }
  11286         if (lanes_ctrl->idb_slots[0] == -1) { /* new group */
  11287             reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe];
  11288             rval = 0;
  11289             soc_reg_field_set(unit, reg, &rval, SAME_SPACINGf, 4);
  11290             soc_reg_field_set(unit, reg, &rval, SISTER_SPACINGf, 4);
  11291             soc_reg_field_set(unit, reg, &rval, SPEEDf, lanes_ctrl->class);
  11292             SOC_IF_ERROR_RETURN
  11293                 (soc_reg32_set(unit, reg, REG_PORT_ANY, group, rval));
  11294         }
  11295 
  11296         /* Remove mmu port(s) from current group */
  11297         group = lanes_ctrl->cur_mmu_group;
  11298         reg = mmu_grp_tbl_regs[group];
  11299         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  11300         rval = 0;
  11301         soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 0x3f);
  11302         soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, 0);
  11303         slot = lanes_ctrl->cur_mmu_slots[0];
  11304         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
  11305         if ((lanes_ctrl->lanes > lanes_ctrl->cur_lanes) &&
  11306             (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes)) {
  11307             /* port(s) to be removed */
  11308             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11309                 slot = lanes_ctrl->cur_mmu_slots[i + 1];
  11310                 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
  11311             }
  11312         }
  11313         if (lanes_ctrl->cur_idb_empty &&
  11314             (lanes_ctrl->idb_group != lanes_ctrl->cur_idb_group)) { /* old group became empty */
  11315             reg = OVR_SUB_GRP_CFGr;
  11316             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, group, 0));
  11317         }
  11318 
  11319         /* Add mmu port(s) to new group */
  11320         group = lanes_ctrl->mmu_group;
  11321         reg = mmu_grp_tbl_regs[group];
  11322         rval = 0;
  11323         soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id & 0x7);
  11324         mmu_port = si->port_p2m_mapping[phy_port];
  11325         soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f);
  11326         slot = lanes_ctrl->mmu_slots[0] != -1 ? lanes_ctrl->mmu_slots[0] : 0;
  11327         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
  11328         if ((lanes_ctrl->lanes < lanes_ctrl->cur_lanes) &&
  11329             (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes)) {
  11330             /* port(s) to be added */
  11331             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11332                 mmu_port = si->port_p2m_mapping[lanes_ctrl->phy_ports[i]];
  11333                 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f);
  11334                 slot = lanes_ctrl->mmu_slots[0] != -1 ?
  11335                     lanes_ctrl->mmu_slots[i + 1] : i + 1;
  11336                 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
  11337             }
  11338         }
  11339         if (lanes_ctrl->mmu_slots[0] == -1) { /* new group */
  11340             reg = OVR_SUB_GRP_CFGr;
  11341             rval = 0;
  11342             soc_reg_field_set(unit, reg, &rval, SAME_SPACINGf,
  11343                               lanes_ctrl->class >= 4 ? 4 : 8);
  11344             soc_reg_field_set(unit, reg, &rval, SISTER_SPACINGf, 4);
  11345             soc_reg_field_set(unit, reg, &rval, SPEEDf, lanes_ctrl->class);
  11346             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, group, rval));
  11347         }
  11348     }
  11349 
  11350     if ((TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) ||
  11351         ((TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) &&
  11352          ((lanes_ctrl->class < 4 && lanes_ctrl->cur_class >= 4) ||
  11353          (lanes_ctrl->class >= 4 && lanes_ctrl->cur_class < 4)))) {
  11354         mode = tdm->port_ratio[clport];
  11355         port_block_base = PORT_BLOCK_BASE_PORT(port_base);
  11356         /* Reprogram IS port block calendar */
  11357         reg = SOC_REG_UNIQUE_ACC(unit, pblk_calendar_regs[id])[pipe];
  11358         rval = 0;
  11359         soc_reg_field_set(unit, reg, &rval, VALIDf, 1);
  11360         soc_reg_field_set(unit, reg, &rval, SPACINGf, 4);
  11361         for (slot = 0; slot < 7; slot++) {
  11362             lane = pblk_slots[mode][slot];
  11363             if (lane == -1) {
  11364                 SOC_IF_ERROR_RETURN
  11365                     (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, 0));
  11366                 continue;
  11367             }
  11368             port = si->port_p2l_mapping[port_block_base + lane];
  11369             idb_port = si->port_l2i_mapping[port];
  11370             soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port);
  11371             SOC_IF_ERROR_RETURN
  11372                 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval));
  11373         }
  11374 
  11375         /* Reprogram MMU port block calendar */
  11376         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  11377         reg = mmu_pblk_calendar_regs[id];
  11378         rval = 0;
  11379         soc_reg_field_set(unit, reg, &rval, VALIDf, 1);
  11380         soc_reg_field_set(unit, reg, &rval, SPACINGf,
  11381                           lanes_ctrl->class >= 4 ? 4 : 8);
  11382         for (slot = 0; slot < 7; slot++) {
  11383             lane = pblk_slots[mode][slot];
  11384             if (lane == -1) {
  11385                 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, 0));
  11386                 continue;
  11387             }
  11388             mmu_port = si->port_p2m_mapping[port_block_base + lane];
  11389             soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f);
  11390             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval));
  11391         }
  11392     }
  11393 
  11394     return SOC_E_NONE;
  11395 }
  11396 
  11397 STATIC soc_error_t
  11398 _soc_tomahawk_obm_counters_reset(int unit, soc_port_t port)
  11399 {
  11400     int idx = 0;
  11401     soc_ctr_control_info_t ctrl_info;
  11402     soc_reg_t obm_counter_regs[] = {
  11403         SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO,
  11404         SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO,
  11405         SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI,
  11406         SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI,
  11407         SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0,
  11408         SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0,
  11409         SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1,
  11410         SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1
  11411     };
  11412     uint64 my_zero;
  11413 
  11414     ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  11415     ctrl_info.instance = port;
  11416     COMPILER_64_ZERO(my_zero);
  11417     for (idx = 0; idx < COUNTOF(obm_counter_regs); idx++) {
  11418         SOC_IF_ERROR_RETURN
  11419             (soc_counter_generic_set(unit, obm_counter_regs[idx], ctrl_info, 0,
  11420                                      0, my_zero));
  11421     }
  11422 
  11423     return SOC_E_NONE;
  11424 }
  11425 
  11426 soc_error_t
  11427 soc_tomahawk_edb_buf_reset(int unit, soc_port_t port, int reset)
  11428 {
  11429     uint32 entry[SOC_MAX_MEM_WORDS];
  11430     soc_info_t *si = &SOC_INFO(unit);
  11431     int phy_port, index;
  11432 
  11433     phy_port = si->port_l2p_mapping[port];
  11434 
  11435     /* In Tomahawk2, EGR_PER_PORT_BUFFER_SFT_RESETm, EGR_ENABLEm are indexed
  11436      * by physical port num */
  11437     index = SOC_IS_TOMAHAWK2(unit) ? phy_port : port;
  11438 
  11439     if (reset) {
  11440         soc_reg_t reg;
  11441         soc_timeout_t to;
  11442         int pipe;
  11443         uint32 rval, level;
  11444 
  11445         pipe = si->port_pipe[port];
  11446         reg = SOC_REG_UNIQUE_ACC(unit, EGR_EDB_MISC_CTRLr)[pipe];
  11447         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
  11448         soc_reg_field_set(unit, reg, &rval, SELECT_CURRENT_USED_ENTRIESf, 1);
  11449         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
  11450 
  11451         soc_timeout_init(&to, 250000, 0);
  11452         /* Poll until EDB buffer is empty */
  11453         for (;;) {
  11454             SOC_IF_ERROR_RETURN
  11455                 (READ_EGR_MAX_USED_ENTRIESm(unit, MEM_BLOCK_ALL,
  11456                                             phy_port, entry));
  11457             level = soc_mem_field32_get(unit, EGR_MAX_USED_ENTRIESm,
  11458                                         entry, LEVELf);
  11459             if (!level) {
  11460                 break;
  11461             }
  11462             if (soc_timeout_check(&to)) {
  11463                 LOG_ERROR(BSL_LS_SOC_COMMON,
  11464                           (BSL_META_U(unit,
  11465                                       "EDBBufferDrainTimeOut:port %d,%s, timeout"
  11466                                       "(pending: %d)\n"),
  11467                            unit, SOC_PORT_NAME(unit, port), level));
  11468                 return SOC_E_INTERNAL;
  11469             }
  11470         }
  11471         SOC_IF_ERROR_RETURN(READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, index, entry));
  11472         soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, !reset);
  11473         SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, index, entry));
  11474         SOC_IF_ERROR_RETURN
  11475             (READ_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
  11476                                                  index, entry));
  11477         soc_mem_field32_set(unit, EGR_PER_PORT_BUFFER_SFT_RESETm,
  11478                             entry, ENABLEf, reset);
  11479         SOC_IF_ERROR_RETURN
  11480             (WRITE_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
  11481                                                   index, entry));
  11482     } else {
  11483         uint32 rval = 0;
  11484         /*
  11485          * Initialize EP credits in MMU so EP is in charge of distributing
  11486          * the correct number of credits
  11487          */
  11488         soc_reg_field_set(unit, MMU_PORT_CREDITr, &rval, INITIALIZEf, 1);
  11489         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_PORT_CREDITr, port, 0, rval));
  11490         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_PORT_CREDITr, port, 0, 0));
  11491 
  11492         /* Release EDB port buffer reset and enable cell request generation in EP */
  11493         SOC_IF_ERROR_RETURN
  11494             (READ_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
  11495                                                  index, entry));
  11496         soc_mem_field32_set(unit, EGR_PER_PORT_BUFFER_SFT_RESETm,
  11497                             entry, ENABLEf, reset);
  11498         SOC_IF_ERROR_RETURN
  11499             (WRITE_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL,
  11500                                                   index, entry));
  11501         SOC_IF_ERROR_RETURN(READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, index, entry));
  11502         soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, !reset);
  11503         SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, index, entry));
  11504     }
  11505     return SOC_E_NONE;
  11506 }
  11507 
  11508 soc_error_t
  11509 soc_tomahawk_idb_buf_reset(int unit, soc_port_t port, int reset)
  11510 {
  11511     soc_reg_t reg, reg1;
  11512     int port_block_base, phy_port, lane;
  11513     int pipe, obm, clport, obm_usage_count = ~0, ca_empty = 0;
  11514     uint32 rval;
  11515     uint64 rval1, rval2;
  11516     soc_info_t *si = &SOC_INFO(unit);
  11517 
  11518     static const soc_reg_t idb_obm_usage_regs[] = {
  11519         IDB_OBM0_USAGEr, IDB_OBM1_USAGEr,
  11520         IDB_OBM2_USAGEr, IDB_OBM3_USAGEr,
  11521         IDB_OBM4_USAGEr, IDB_OBM5_USAGEr,
  11522         IDB_OBM6_USAGEr, IDB_OBM7_USAGEr
  11523     };
  11524     static const soc_reg_t idb_obm_ca_status_regs[] = {
  11525         IDB_OBM0_CA_HW_STATUSr, IDB_OBM1_CA_HW_STATUSr,
  11526         IDB_OBM2_CA_HW_STATUSr, IDB_OBM3_CA_HW_STATUSr,
  11527         IDB_OBM4_CA_HW_STATUSr, IDB_OBM5_CA_HW_STATUSr,
  11528         IDB_OBM6_CA_HW_STATUSr, IDB_OBM7_CA_HW_STATUSr
  11529     };
  11530     static const soc_reg_t obm_ctrl_regs[] = {
  11531         IDB_OBM0_CONTROLr, IDB_OBM1_CONTROLr,
  11532         IDB_OBM2_CONTROLr, IDB_OBM3_CONTROLr,
  11533         IDB_OBM4_CONTROLr, IDB_OBM5_CONTROLr,
  11534         IDB_OBM6_CONTROLr, IDB_OBM7_CONTROLr
  11535     };
  11536     static const soc_reg_t obm_ca_ctrl_regs[] = {
  11537         IDB_OBM0_CA_CONTROLr, IDB_OBM1_CA_CONTROLr,
  11538         IDB_OBM2_CA_CONTROLr, IDB_OBM3_CA_CONTROLr,
  11539         IDB_OBM4_CA_CONTROLr, IDB_OBM5_CA_CONTROLr,
  11540         IDB_OBM6_CA_CONTROLr, IDB_OBM7_CA_CONTROLr
  11541     };
  11542     static const soc_field_t fifo_empty_port_fields[] = {
  11543         FIFO_EMPTY_PORT0f, FIFO_EMPTY_PORT1f, FIFO_EMPTY_PORT2f,
  11544         FIFO_EMPTY_PORT3f
  11545     };
  11546     static const soc_field_t port_reset_fields[] = {
  11547         PORT0_RESETf, PORT1_RESETf, PORT2_RESETf, PORT3_RESETf
  11548     };
  11549 
  11550     phy_port = si->port_l2p_mapping[port];
  11551     port_block_base = PORT_BLOCK_BASE_PORT(port);
  11552     lane = phy_port - port_block_base;
  11553     pipe = si->port_pipe[port];
  11554     clport = si->port_serdes[port];
  11555     /* obm number is reversed (mirrored) in odd pipe */
  11556     obm = pipe & 1 ? 7 - (clport & 0x7) : clport & 0x7;
  11557 
  11558     if (reset && !SAL_BOOT_SIMULATION) {
  11559         soc_timeout_t to;
  11560 
  11561         reg = SOC_REG_UNIQUE_ACC(unit, idb_obm_usage_regs[obm])[pipe];
  11562         reg1 = SOC_REG_UNIQUE_ACC(unit, idb_obm_ca_status_regs[obm])[pipe];
  11563 
  11564         soc_timeout_init(&to, 250000, 0);
  11565         /* Poll until IDB buffer is empty */
  11566         for (;;) {
  11567             if (0 != obm_usage_count) {
  11568                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, lane,
  11569                                                 &rval1));
  11570                 obm_usage_count = soc_reg64_field32_get(unit, reg, rval1,
  11571                                                         TOTAL_COUNTf);
  11572             }
  11573             if (0 == ca_empty) {
  11574                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg1, REG_PORT_ANY, 0,
  11575                                                 &rval2));
  11576                 ca_empty = soc_reg64_field32_get(unit, reg1, rval2,
  11577                                                  fifo_empty_port_fields[lane]);
  11578             }
  11579             if ((0 == obm_usage_count) && (1 == ca_empty)) {
  11580                 break;
  11581             }
  11582             if (soc_timeout_check(&to)) {
  11583                 LOG_ERROR(BSL_LS_SOC_COMMON,
  11584                           (BSL_META_U(unit,
  11585                                       "IDBBufferDrainTimeOut:port %d,%s, timeout"
  11586                                       "(idb_obm_usage: %d) "
  11587                                       "(ca_fifo_empty: %d)\n"),
  11588                            unit, SOC_PORT_NAME(unit, port), obm_usage_count,
  11589                            ca_empty));
  11590                 return SOC_E_INTERNAL;
  11591             }
  11592         }
  11593     }
  11594 
  11595     if (reset) {
  11596         /* OBM counters will be cleared by IDB reset.
  11597          * Clear in counter thread accordingly.
  11598          */
  11599         SOC_IF_ERROR_RETURN(_soc_tomahawk_obm_counters_reset(unit, port));
  11600     }
  11601 
  11602     reg = SOC_REG_UNIQUE_ACC(unit, obm_ctrl_regs[obm])[pipe];
  11603     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
  11604     soc_reg_field_set(unit, reg, &rval, port_reset_fields[lane], reset);
  11605     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
  11606 
  11607     reg = SOC_REG_UNIQUE_ACC(unit, obm_ca_ctrl_regs[obm])[pipe];
  11608     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
  11609     soc_reg_field_set(unit, reg, &rval, port_reset_fields[lane], reset);
  11610     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
  11611 
  11612     return SOC_E_NONE;
  11613 }
  11614 
  11615 STATIC int
  11616 _soc_tomahawk_obm_thresholds_reconfigure(int unit, soc_port_t port_conf)
  11617 {
  11618 #define _TH_BYTES_PER_OBM_CELL    16
  11619 #define _TH_CELLS_PER_OBM         1012
  11620     soc_info_t *si;
  11621     _soc_tomahawk_tdm_t *tdm;
  11622     soc_reg_t reg;
  11623     int block_info_idx, pipe, clport, obm, lane;
  11624     int port, phy_port_base;
  11625     int lossless;
  11626     uint32 fval;
  11627     uint64 rval64;
  11628     int num_lanes, oversub_ratio_idx;
  11629     static const struct _obm_setting_s {
  11630         int discard_limit;
  11631         int lossless_xoff;
  11632         int lossy_only_lossy_low_pri;
  11633         int port_xoff[3];          /* for oversub ratio 1.5, 1.8, and above */
  11634         int lossy_low_pri[3];      /* for oversub ratio 1.5, 1.8, and above */
  11635         int lossy_discard[3];      /* for oversub ratio 1.5, 1.8, and above */
  11636     } obm_settings[2][5] = {
  11637         /* LOSSY Settings */
  11638         { /* indexed by number of lanes used in the port */
  11639             { /* 0 - invalid  */ 0 },
  11640             { /* 1 lane */
  11641                 _TH_CELLS_PER_OBM / 4, 1023, 157,
  11642                 { 1023, 1023, 1023 }, /* port_xoff */
  11643                 { 157, 157, 157 }, /* lossy_low_pri */
  11644                 { 253, 253, 253 }  /* lossy_discard */
  11645             },
  11646             { /* 2 lanes */
  11647                 _TH_CELLS_PER_OBM / 2, 1023, 410,
  11648                 { 1023, 1023, 1023 }, /* port_xoff */
  11649                 { 410, 410, 410 }, /* lossy_low_pri */
  11650                 { 506, 506, 506 }  /* lossy_discard */
  11651             },
  11652             { /* 3 - invalid  */ 0 },
  11653             { /* 4 lanes */
  11654                 _TH_CELLS_PER_OBM, 1023, 916,
  11655                 { 1023, 1023, 1023 }, /* port_xoff */
  11656                 { 916, 916, 916 }, /* lossy_low_pri */
  11657                 { 1012, 1012, 1012 }  /* lossy_discard */
  11658             }
  11659         },
  11660         /* LOSSLESS Settings*/
  11661         { /* indexed by number of lanes used in the port */
  11662             { /* 0 - invalid  */ 0 },
  11663             { /* 1 lane */
  11664                 _TH_CELLS_PER_OBM / 4, 45, 157,
  11665                 { 129, 87, 67 }, /* port_xoff */
  11666                 { 100, 76, 56 }, /* lossy_low_pri */
  11667                 { 196, 152, 112 }  /* lossy_discard */
  11668             },
  11669             { /* 2 lanes */
  11670                 _TH_CELLS_PER_OBM / 2, 108, 410,
  11671                 { 312, 248, 215 }, /* port_xoff */
  11672                 { 100, 100, 100 }, /* lossy_low_pri */
  11673                 { 196, 196, 196 }  /* lossy_discard */
  11674             },
  11675             { /* 3 - invalid  */ 0 },
  11676             { /* 4 lanes */
  11677                 _TH_CELLS_PER_OBM, 258, 916,
  11678                 { 682, 572, 517 }, /* port_xoff */
  11679                 { 100, 100, 100 }, /* lossy_low_pri */
  11680                 { 196, 196, 196 }  /* lossy_discard */
  11681             }
  11682         }
  11683     };
  11684     static const soc_reg_t obm_thresh_regs[] = {
  11685         IDB_OBM0_THRESHOLDr, IDB_OBM1_THRESHOLDr,
  11686         IDB_OBM2_THRESHOLDr, IDB_OBM3_THRESHOLDr,
  11687         IDB_OBM4_THRESHOLDr, IDB_OBM5_THRESHOLDr,
  11688         IDB_OBM6_THRESHOLDr, IDB_OBM7_THRESHOLDr
  11689     };
  11690     static const soc_reg_t obm_fc_thresh_regs[] = {
  11691         IDB_OBM0_FC_THRESHOLDr, IDB_OBM1_FC_THRESHOLDr,
  11692         IDB_OBM2_FC_THRESHOLDr, IDB_OBM3_FC_THRESHOLDr,
  11693         IDB_OBM4_FC_THRESHOLDr, IDB_OBM5_FC_THRESHOLDr,
  11694         IDB_OBM6_FC_THRESHOLDr, IDB_OBM7_FC_THRESHOLDr
  11695     };
  11696 
  11697     si = &SOC_INFO(unit);
  11698     tdm = SOC_CONTROL(unit)->tdm_info;
  11699 
  11700     if (SOC_IS_TOMAHAWKPLUS(unit)) {
  11701         lossless = soc_property_get(unit, spn_MMU_LOSSLESS,
  11702                                     SOC_TH_MMU_LOSSLESS_DEFAULT_DISABLE);
  11703     } else {
  11704         lossless = soc_property_get(unit, spn_MMU_LOSSLESS,
  11705                                     SOC_TH_MMU_LOSSLESS_DEFAULT_ENABLE);
  11706     }
  11707 
  11708     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) {
  11709         port = SOC_BLOCK_PORT(unit, block_info_idx);
  11710         if (port != port_conf) {
  11711             continue;
  11712         }
  11713 
  11714         phy_port_base = PORT_BLOCK_BASE_PORT(port);
  11715         pipe = si->port_pipe[port];
  11716         clport = SOC_BLOCK_NUMBER(unit, block_info_idx);
  11717         /* obm number is reversed (mirrored) in odd pipe */
  11718         obm = pipe & 1 ? 7 - (clport & 0x7) : clport & 0x7;
  11719 
  11720         if (!SOC_PBMP_MEMBER(si->oversub_pbm, port)) {
  11721             continue;
  11722         }
  11723 
  11724         if (lossless) {
  11725             if (tdm->ovs_ratio_x1000[pipe] >= 1800) { /* ratio >= 1.8 */
  11726                 oversub_ratio_idx = 2;
  11727             } else if (tdm->ovs_ratio_x1000[pipe] >= 1500) { /* ratio >= 1.5 */
  11728                 oversub_ratio_idx = 1;
  11729             } else {
  11730                 oversub_ratio_idx = 0;
  11731             }
  11732 
  11733             for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) {
  11734                 port = si->port_p2l_mapping[phy_port_base + lane];
  11735                 if (port == -1) {
  11736                     continue;
  11737                 }
  11738                 num_lanes = si->port_num_lanes[port];
  11739 
  11740                 /* Configure threshold */
  11741                 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe];
  11742                 SOC_IF_ERROR_RETURN
  11743                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
  11744                 fval = obm_settings[1][num_lanes].discard_limit;
  11745                 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf, fval);
  11746                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf,
  11747                                       1023);
  11748                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf,
  11749                                       1023);
  11750                 fval = obm_settings[1][num_lanes].lossy_low_pri[oversub_ratio_idx];
  11751                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf, fval);
  11752                 fval = obm_settings[1][num_lanes].lossy_discard[oversub_ratio_idx];
  11753                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf, fval);
  11754                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_MINf, 0);
  11755                 SOC_IF_ERROR_RETURN
  11756                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
  11757 
  11758                 /* Configure flow control threshold */
  11759                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe];
  11760                 SOC_IF_ERROR_RETURN
  11761                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
  11762                 fval = obm_settings[1][num_lanes].port_xoff[oversub_ratio_idx];
  11763                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf, fval);
  11764                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf, fval - 10);
  11765                 fval = obm_settings[1][num_lanes].lossless_xoff;
  11766                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf,
  11767                                       fval);
  11768                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf,
  11769                                       fval);
  11770                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf,
  11771                                       fval - 10);
  11772                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf,
  11773                                       fval - 10);
  11774                 SOC_IF_ERROR_RETURN
  11775                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
  11776             }
  11777         } else { /* lossy */
  11778             for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) {
  11779                 port = si->port_p2l_mapping[phy_port_base + lane];
  11780                 if (port == -1) {
  11781                     continue;
  11782                 }
  11783                 num_lanes = si->port_num_lanes[port];
  11784 
  11785                 /* Configure threshold */
  11786                 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe];
  11787                 SOC_IF_ERROR_RETURN
  11788                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
  11789                 fval = obm_settings[0][num_lanes].discard_limit;
  11790                 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf, fval);
  11791                 /* same as DISCARD_LIMIT setting */
  11792                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf, fval);
  11793                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf,
  11794                                       1023);
  11795                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf,
  11796                                       1023);
  11797                 fval = obm_settings[0][num_lanes].lossy_only_lossy_low_pri;
  11798                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf, fval);
  11799                 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_MINf, 0);
  11800                 SOC_IF_ERROR_RETURN
  11801                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
  11802 
  11803                 /* Configure flow control threshold */
  11804                 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe];
  11805                 SOC_IF_ERROR_RETURN
  11806                     (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64));
  11807                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf, 1023);
  11808                 soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf, 1023);
  11809                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf,
  11810                                       1023);
  11811                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf,
  11812                                       1023);
  11813                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf, 1023);
  11814                 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf, 1023);
  11815                 SOC_IF_ERROR_RETURN
  11816                     (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64));
  11817             }
  11818         }
  11819     }
  11820 
  11821     return SOC_E_NONE;
  11822 }
  11823 
  11824 /*
  11825  * Function:
  11826  *      soc_tomahawk_port_lanes_set
  11827  * Description:
  11828  *      Configure number of lanes used by a port
  11829  * Parameters:
  11830  *      unit          - Device number
  11831  *      lanes_ctrl    - Control structure
  11832  * Notes: Caller needs to call soc_tomahawk_port_lanes_validate to fill
  11833  *        in the control structure.
  11834  */
  11835 int
  11836 soc_tomahawk_port_lanes_set(int unit, soc_th_port_lanes_t *lanes_ctrl)
  11837 {
  11838     uint32 rval;
  11839     soc_reg_t reg;
  11840     uint32 values[2];
  11841     soc_port_t it_port;
  11842     soc_field_t fields[2];
  11843     soc_info_t *si = &SOC_INFO(unit);
  11844     int i, pipe, port_base, phy_port_base, port, port_rename = 0;
  11845     int clport, obm;
  11846     uint32 port_speed = 0, cur_port_speed = 0;
  11847     int save_port_speed = 0;
  11848     _soc_tomahawk_tdm_t *tdm;
  11849     static const soc_reg_t obm_ca_ctrl_regs[] = {
  11850         IDB_OBM0_CA_CONTROLr, IDB_OBM1_CA_CONTROLr,
  11851         IDB_OBM2_CA_CONTROLr, IDB_OBM3_CA_CONTROLr,
  11852         IDB_OBM4_CA_CONTROLr, IDB_OBM5_CA_CONTROLr,
  11853         IDB_OBM6_CA_CONTROLr, IDB_OBM7_CA_CONTROLr
  11854     };
  11855     static const int hw_mode_values[SOC_TH_PORT_RATIO_COUNT] = {
  11856         0, 1, 1, 1, 3, 5, 4, 6, 2
  11857     };
  11858 
  11859     /* Find physical port number and lane index of the specified port */
  11860     port_base = lanes_ctrl->port_base;
  11861     phy_port_base = si->port_l2p_mapping[port_base];
  11862     if (phy_port_base == -1) {
  11863         return SOC_E_PORT;
  11864     }
  11865     pipe = si->port_pipe[port_base];
  11866 
  11867     /* Update port_init_max info which is used by SerDes driver */
  11868     SOC_IF_ERROR_RETURN
  11869         (_soc_tomahawk_flexed_port_speed_get(unit, lanes_ctrl, &port_speed));
  11870 
  11871     /* Update soc_control information */
  11872     SOC_CONTROL_LOCK(unit);
  11873     /* No need to update lanes information during speed change */
  11874     if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) {
  11875         if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  11876             /* port(s) to be removed */
  11877             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11878                 port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]];
  11879                 SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port);
  11880             }
  11881         } else { /* port(s) to be added */
  11882             for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11883                 port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]];
  11884                 SOC_PBMP_PORT_REMOVE(si->all.disabled_bitmap, port);
  11885             }
  11886         }
  11887 
  11888         /* Update num of lanes info which is used by SerDes driver */
  11889         si->port_num_lanes[port_base] = lanes_ctrl->lanes;
  11890         for (i = 0; i < lanes_ctrl->phy_ports_len; i++) {
  11891             port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]];
  11892             si->port_num_lanes[port] =
  11893                 lanes_ctrl->lanes > lanes_ctrl->cur_lanes ? 
  11894                 (si->port_speed_max[port] == 50000 ? 2 :
  11895                 (si->port_speed_max[port] == 25000 ? 1 : 0)) :
  11896                 lanes_ctrl->lanes;
  11897         }
  11898     }
  11899 
  11900     si->port_init_speed[port_base] = port_speed;
  11901     if (si->port_init_speed[port_base] >= 40000) {
  11902         SOC_PBMP_PORT_ADD(si->eq_pbm, port_base);
  11903         /* Update HSP port multicast T2OQ setting */
  11904         SOC_IF_ERROR_RETURN(_soc_tomahawk_mc_toq_cfg(unit, port_base, TRUE));
  11905     } else {
  11906         SOC_PBMP_PORT_REMOVE(si->eq_pbm, port_base);
  11907         /* Update HSP port multicast T2OQ setting */
  11908         SOC_IF_ERROR_RETURN(_soc_tomahawk_mc_toq_cfg(unit, port_base, FALSE));
  11909     }
  11910     if (lanes_ctrl->os_mixed_sister) {
  11911             cur_port_speed = port_speed;
  11912         /* figure out 25G/50G mixed sister port mode */
  11913         if ((lanes_ctrl->mixed_port_mode > MIXED_DUAL_MODE_40_0_40_0) &&
  11914             ((lanes_ctrl->lanes == 1) ||
  11915              (lanes_ctrl->lanes == 2))) {
  11916             port_speed = 50000;
  11917             save_port_speed = 1;
  11918         }
  11919     }
  11920     SOC_IF_ERROR_RETURN
  11921         (soc_tomahawk_update_icc(unit, port_base, port_speed));
  11922     if (lanes_ctrl->os_mixed_sister) {
  11923         port_speed = cur_port_speed;
  11924     }
  11925     for (i = 0; i < lanes_ctrl->phy_ports_len; i += 1) {
  11926         port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]];
  11927         if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) {
  11928             /* port(s) to be removed */
  11929             /* Update pbm of HSP */
  11930             if (si->port_init_speed[port] >= 40000) {
  11931                 SOC_PBMP_PORT_REMOVE(si->eq_pbm, port);
  11932                 /* Update HSP port multicast T2OQ setting */
  11933                 SOC_IF_ERROR_RETURN(_soc_tomahawk_mc_toq_cfg(unit, port,
  11934                                                              FALSE));
  11935             }
  11936         } else { /* port(s) to be added */
  11937             si->port_init_speed[port] = port_speed;
  11938             /* Update pbm of HSP */
  11939             if (si->port_init_speed[port] >= 40000) {
  11940                 SOC_PBMP_PORT_ADD(si->eq_pbm, port);
  11941                 /* Update HSP port multicast T2OQ setting */
  11942                 SOC_IF_ERROR_RETURN(_soc_tomahawk_mc_toq_cfg(unit, port, TRUE));
  11943             }
  11944             if (lanes_ctrl->os_mixed_sister && save_port_speed) {
  11945                 port_speed = 50000;
  11946             }
  11947             SOC_IF_ERROR_RETURN
  11948                 (soc_tomahawk_update_icc(unit, port, port_speed));
  11949             if (lanes_ctrl->os_mixed_sister && save_port_speed) {
  11950                 port_speed = cur_port_speed;
  11951             }
  11952          }
  11953      }
  11954 
  11955     /* Update TDM config for HSP */
  11956     SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_idb_hsp_set(unit, pipe));
  11957     SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_mmu_hsp_set(unit, pipe));
  11958 
  11959     /* OBM setting reconfigure */
  11960     if (TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) {
  11961         SOC_IF_ERROR_RETURN(_soc_tomahawk_obm_thresholds_reconfigure(unit, port_base));
  11962     }
  11963 
  11964     /*
  11965      * Update bitmaps and port names when switching b/w CE <=> XE ports.
  11966      * Or b/w XE <=> GE ports.
  11967      * Conditions tested include :
  11968      * - Port is a CE port and we are flexing to a port with < 4 lanes
  11969      * - Port is a CE port and we are setting speed to < 100G
  11970      * - Port is a XE port and we are setting speed to 1G
  11971      */
  11972     if (((lanes_ctrl->cur_lanes == 4) && IS_CE_PORT(unit, port_base)) ||
  11973         ((TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) &&
  11974          IS_CE_PORT(unit, port_base) && (port_speed < 100000))) {
  11975 
  11976         /* Convert to XE ports */
  11977         SOC_PBMP_PORT_REMOVE(si->ce.bitmap, port_base);
  11978         SOC_PBMP_PORT_ADD(si->xe.bitmap,
  11979                           si->port_p2l_mapping[phy_port_base]);
  11980         port_rename = 1;
  11981     } else if (((lanes_ctrl->lanes == 4) && IS_XE_PORT(unit, port_base) &&
  11982                (port_speed == 100000)) ||
  11983                ((TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) &&
  11984                 (IS_XE_PORT(unit, port_base) && (port_speed == 100000)))) {
  11985 
  11986         /* Convert to CE ports */
  11987         SOC_PBMP_PORT_ADD(si->ce.bitmap, port_base);
  11988         SOC_PBMP_PORT_REMOVE(si->xe.bitmap,
  11989                              si->port_p2l_mapping[phy_port_base]);
  11990         port_rename = 1;
  11991     } else if ((TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) &&
  11992                (IS_XE_PORT(unit, port_base) && (port_speed == 1000))) {
  11993         SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port_base);
  11994         SOC_PBMP_PORT_ADD(si->ge.bitmap, port_base);
  11995         port_rename = 1;
  11996     } else if ((TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) &&
  11997                (IS_GE_PORT(unit, port_base) && ((port_speed == 10000) || 
  11998                                                 (port_speed == 25000)))) {
  11999         SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port_base);
  12000         SOC_PBMP_PORT_ADD(si->xe.bitmap, port_base);
  12001         port_rename = 1;
  12002     }
  12003 
  12004     if (port_rename) {
  12005         _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(xe);
  12006         _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ce);
  12007         _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ge);
  12008         soc_dport_map_update(unit);
  12009     }
  12010     SOC_CONTROL_UNLOCK(unit);
  12011 
  12012     /* No need to change CLPORT mode during speed set */
  12013     if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) {
  12014         /* Change CLPORT mode */
  12015         fields[0] = XPORT0_CORE_PORT_MODEf;
  12016         values[0] = lanes_ctrl->mode;
  12017         fields[1] = XPORT0_PHY_PORT_MODEf;
  12018         values[1] = lanes_ctrl->mode;
  12019         SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, CLPORT_MODE_REGr,
  12020                                                     port_base, 2, fields,
  12021                                                     values));
  12022     }
  12023 
  12024     /* Update TDM */
  12025     SOC_IF_ERROR_RETURN
  12026         (_soc_tomahawk_port_lanes_update_tdm(unit, lanes_ctrl));
  12027 
  12028     SOC_IF_ERROR_RETURN
  12029         (soc_tomahawk_port_pg_headroom_update(unit, port_base));
  12030     /* No need to change CA mode during speed set */
  12031     if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) {
  12032         /* Reconfigure cell assembly port mode */
  12033         tdm = SOC_CONTROL(unit)->tdm_info;
  12034         pipe = si->port_pipe[port_base];
  12035         clport = si->port_serdes[port_base];
  12036         /* obm number is reversed (mirrored) in odd pipe */
  12037         obm = pipe & 1 ? 7 - (clport & 0x7) : clport & 0x7;
  12038         reg = SOC_REG_UNIQUE_ACC(unit, obm_ca_ctrl_regs[obm])[pipe];
  12039         rval = 0;
  12040         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
  12041         soc_reg_field_set(unit, reg, &rval, PORT_MODEf,
  12042                           hw_mode_values[tdm->port_ratio[clport]]);
  12043         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
  12044     }
  12045 
  12046     return SOC_E_NONE;
  12047 }
  12048 
  12049 STATIC int
  12050 _soc_th_speed_group_sort(soc_th_speed_group_count_t *min_group_array, int len)
  12051 {
  12052     int i, j;
  12053     soc_th_speed_group_count_t tmp;
  12054 
  12055     sal_memset(&tmp, 0, sizeof(soc_th_speed_group_count_t));
  12056 
  12057     for (i = 1; i < len; i ++) {
  12058         sal_memcpy(&tmp, &min_group_array[i], sizeof(soc_th_speed_group_count_t));
  12059         for (j = i - 1 ; j >= 0 && min_group_array[j].count_ports > tmp.count_ports; j --) {
  12060             sal_memcpy(&min_group_array[j + 1], &min_group_array[j], sizeof(soc_th_speed_group_count_t));
  12061         }
  12062         sal_memcpy(&min_group_array[j + 1], &tmp, sizeof(soc_th_speed_group_count_t));
  12063     }
  12064     return SOC_E_NONE;
  12065 }
  12066 
  12067 STATIC int
  12068 soc_th_speed_group_consolidate_check(int unit, soc_th_port_lanes_t *lanes_ctrl, int flag)
  12069 {
  12070     soc_info_t *si = &SOC_INFO(unit);
  12071     soc_reg_t reg;
  12072     int port_base;
  12073     int inst;
  12074     uint32 rval, fval;
  12075     int pipe, group, slot, i;
  12076     int speed_id, port_mode;
  12077     int count_ports = 0;
  12078     int idb_sum_count_ports = 0, mmu_sum_count_ports = 0;
  12079     int idb_count_group = 0, mmu_count_group = 0;
  12080     int idb_speed_group_ratio, mmu_speed_group_ratio;
  12081     int tmp, pass1 = 0, pass2 = 0;
  12082 
  12083     soc_th_speed_group_count_t idb_min_group[_OVS_GROUP_COUNT];
  12084     soc_th_speed_group_count_t mmu_min_group[_OVS_GROUP_COUNT];
  12085 
  12086     speed_id = flag ? lanes_ctrl->cur_class : lanes_ctrl->class;
  12087     port_mode = flag ? lanes_ctrl->cur_mode : lanes_ctrl->mode;
  12088     port_base = lanes_ctrl->port_base;
  12089     pipe = si->port_pipe[port_base];
  12090 
  12091     for (group = 0; group < _OVS_GROUP_COUNT; group++) {
  12092         reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe];
  12093         SOC_IF_ERROR_RETURN
  12094             (soc_reg32_get(unit, reg, REG_PORT_ANY, group, &rval));
  12095         fval = soc_reg_field_get(unit, reg, rval, SPEEDf);
  12096         if (speed_id == fval) {
  12097             reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe];
  12098             for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
  12099                 SOC_IF_ERROR_RETURN
  12100                     (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval));
  12101                 if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) {
  12102                     count_ports ++;
  12103                 }
  12104             }
  12105 
  12106             idb_min_group[idb_count_group].group_id = group;
  12107             idb_min_group[idb_count_group].count_ports = count_ports;
  12108             idb_sum_count_ports += count_ports;
  12109             idb_count_group ++;
  12110         }
  12111         count_ports = 0;
  12112     }
  12113 
  12114     /* Sort the element of speed group and calculate the ratio of speed group */
  12115     _soc_th_speed_group_sort(idb_min_group, idb_count_group);
  12116     idb_speed_group_ratio = (idb_sum_count_ports - 1) / _OVS_GROUP_TDM_LENGTH + 1;
  12117     tmp = idb_min_group[0].count_ports + idb_min_group[1].count_ports;
  12118 
  12119     if ((idb_speed_group_ratio < idb_count_group) &&
  12120         (tmp <= _OVS_GROUP_TDM_LENGTH)) {
  12121         /* Determine the source and destination of group for migration */
  12122         lanes_ctrl->pipe = pipe;
  12123         lanes_ctrl->speed_id = speed_id;
  12124         lanes_ctrl->port_mode = port_mode;
  12125         lanes_ctrl->src_idb_group = idb_min_group[0].group_id;
  12126         lanes_ctrl->dst_idb_group = idb_min_group[1].group_id;
  12127         pass1 = 1;
  12128     }
  12129 
  12130     count_ports = 0;
  12131     for (group = 0; group < _OVS_GROUP_COUNT; group++) {
  12132         reg = OVR_SUB_GRP_CFGr;
  12133         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  12134         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, group, &rval));
  12135         fval = soc_reg_field_get(unit, reg, rval, SPEEDf);
  12136         if (speed_id == fval) {
  12137             reg = mmu_grp_tbl_regs[group];
  12138             for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
  12139                 SOC_IF_ERROR_RETURN
  12140                     (soc_reg32_get(unit, reg, inst, slot, &rval));
  12141                 if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) {
  12142                     count_ports ++;
  12143                 }
  12144             }
  12145 
  12146             mmu_min_group[mmu_count_group].group_id = group;
  12147             mmu_min_group[mmu_count_group].count_ports = count_ports;
  12148             mmu_sum_count_ports += count_ports;
  12149             mmu_count_group ++;
  12150         }
  12151         count_ports = 0;
  12152     }
  12153 
  12154     _soc_th_speed_group_sort(mmu_min_group, mmu_count_group);
  12155     mmu_speed_group_ratio = (mmu_sum_count_ports - 1) / _OVS_GROUP_TDM_LENGTH + 1;
  12156     tmp = mmu_min_group[0].count_ports + mmu_min_group[1].count_ports;
  12157 
  12158     if ((mmu_speed_group_ratio < mmu_count_group) &&
  12159         (tmp <= _OVS_GROUP_TDM_LENGTH)) {
  12160        lanes_ctrl->src_mmu_group = mmu_min_group[0].group_id;
  12161        lanes_ctrl->dst_mmu_group = mmu_min_group[1].group_id;
  12162        pass2 = 1;
  12163     }
  12164 
  12165     if (pass1 && pass2) {
  12166         lanes_ctrl->action_id = ACT_MIGRATE;
  12167     }
  12168 
  12169     if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  12170         LOG_CLI((BSL_META_U(unit,
  12171                         ">>>> The idb min group info in pipe %d\n"), pipe));
  12172         for (i=0; i < idb_count_group; i++) {
  12173             LOG_CLI((BSL_META_U(unit,
  12174                             "idb_min_group[%d]: g_id=%d c_ports=%d\n"),
  12175                         i, idb_min_group[i].group_id, idb_min_group[i].count_ports));
  12176         }
  12177         LOG_CLI((BSL_META_U(unit, "min ratio: %d, cur ratio: %d\n"),
  12178                     idb_speed_group_ratio, idb_count_group));
  12179         if (idb_speed_group_ratio < idb_count_group) {
  12180             LOG_CLI((BSL_META_U(unit, "speed group %d should consolidate\n"), speed_id));
  12181             if (pass1) {
  12182                 LOG_CLI((BSL_META_U(unit, "speed group %d has sufficient empty slots\n"), speed_id));
  12183             }
  12184         } else {
  12185             LOG_CLI((BSL_META_U(unit, "speed group %d need not consolidate\n"), speed_id));
  12186         }
  12187 
  12188         LOG_CLI((BSL_META_U(unit,
  12189                         ">>>> The mmu min group info in pipe %d\n"), pipe));
  12190         for (i=0; i < mmu_count_group; i++) {
  12191             LOG_CLI((BSL_META_U(unit,
  12192                             "mmu_min_group[%d]: g_id=%d c_ports=%d\n"),
  12193                         i, mmu_min_group[i].group_id, mmu_min_group[i].count_ports));
  12194         }
  12195         LOG_CLI((BSL_META_U(unit, "min ratio: %d, cur ratio: %d\n"),
  12196                     mmu_speed_group_ratio, mmu_count_group));
  12197         if (mmu_speed_group_ratio < mmu_count_group) {
  12198             LOG_CLI((BSL_META_U(unit, "speed group %d should consolidate\n"), speed_id));
  12199             if (pass2) {
  12200                 LOG_CLI((BSL_META_U(unit, "speed group %d has sufficient empty slots\n"), speed_id));
  12201             }
  12202         } else {
  12203             LOG_CLI((BSL_META_U(unit, "speed group %d need not consolidate\n"), speed_id));
  12204         }
  12205     }
  12206 
  12207     return SOC_E_NONE;
  12208 }
  12209 
  12210 STATIC int
  12211 soc_th_speed_group_migrate(int unit, soc_th_port_lanes_t *lanes_ctrl, int flag)
  12212 {
  12213     int i;
  12214     int p_pm = 0, speed_id, port_mode, pm_id = -1;
  12215     int src_g, dst_g;
  12216     int slot, src_slot, dst_slot;
  12217     int pipe, inst;
  12218     soc_reg_t src_reg, dst_reg;
  12219     uint32 rval;
  12220     int no_empty;
  12221     soc_th_speed_group_slot_t entry[4];
  12222     static char *flag_name[] = {"MMU", "IDB"};
  12223 
  12224     pipe = lanes_ctrl->pipe;
  12225     inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  12226     speed_id = lanes_ctrl->speed_id;
  12227     port_mode = lanes_ctrl->port_mode;
  12228 
  12229     src_g = flag ? lanes_ctrl->src_idb_group : lanes_ctrl->src_mmu_group;
  12230     dst_g = flag ? lanes_ctrl->dst_idb_group : lanes_ctrl->dst_mmu_group;
  12231 
  12232     for (i = 0; i < soc_speed_group_info_size; i++) {
  12233         if ((soc_speed_group_info[i].speed_id == speed_id) &&
  12234             (soc_speed_group_info[i].port_mode == port_mode)) {
  12235             p_pm = soc_speed_group_info[i].p_pm;
  12236         }
  12237     }
  12238 
  12239     /* Figure out each port in the PM */
  12240     src_reg = flag ? SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[src_g])[pipe] : mmu_grp_tbl_regs[src_g];
  12241     for (slot = 0, src_slot = 0; src_slot < _OVS_GROUP_TDM_LENGTH; src_slot ++) {
  12242         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, src_reg, flag ? REG_PORT_ANY : inst, src_slot, &rval));
  12243         if (soc_reg_field_get(unit, src_reg, rval, PORT_NUMf) != 0x3f) {
  12244             entry[slot].slot = src_slot;
  12245             entry[slot].pm_id = soc_reg_field_get(unit, src_reg, rval, PHY_PORT_IDf);
  12246             entry[slot].port_id = soc_reg_field_get(unit, src_reg, rval, PORT_NUMf);
  12247 
  12248             /* Checking all ports belonging to a PM */
  12249             if (slot == 0) {
  12250                 pm_id = entry[0].pm_id;
  12251             }
  12252             if ((slot > 0) && (pm_id != entry[slot].pm_id)) {
  12253                 slot --;
  12254                 continue;
  12255             }
  12256             slot ++;
  12257         }
  12258         if (slot >= p_pm) {
  12259             break;
  12260         }
  12261     }
  12262 
  12263     if (slot < p_pm) {
  12264         lanes_ctrl->action_id = ACT_NONE;
  12265         return SOC_E_NONE;
  12266     }
  12267 
  12268     /* Configure the destination of group to contain all ports */
  12269     rval = 0;
  12270     slot = 0;
  12271     dst_reg = flag ? SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[dst_g])[pipe] : mmu_grp_tbl_regs[dst_g];
  12272     for (dst_slot = 0; dst_slot < _OVS_GROUP_TDM_LENGTH; dst_slot ++) {
  12273         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, dst_reg, flag ? REG_PORT_ANY : inst, dst_slot, &rval));
  12274         if (soc_reg_field_get(unit, dst_reg, rval, PORT_NUMf) == 0x3f) {
  12275             soc_reg_field_set(unit, dst_reg, &rval, PORT_NUMf, entry[slot].port_id);
  12276             soc_reg_field_set(unit, dst_reg, &rval, PHY_PORT_IDf, entry[slot].pm_id);
  12277             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dst_reg, flag ? REG_PORT_ANY : inst, dst_slot, rval));
  12278             slot ++;
  12279         }
  12280         if (slot >= p_pm) {
  12281             break;
  12282         }
  12283     }
  12284 
  12285     /* Remove all ports from source group and reset the resource of slot */
  12286     rval = 0;
  12287     for (i = 0; i < p_pm; i++) {
  12288         soc_reg_field_set(unit, src_reg, &rval, PORT_NUMf, 0x3f);
  12289         soc_reg_field_set(unit, src_reg, &rval, PHY_PORT_IDf, 0);
  12290         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, src_reg, flag ? REG_PORT_ANY : inst, entry[i].slot, rval));
  12291     }
  12292 
  12293     /* Reset the resource of speed group */
  12294     rval = 0;
  12295     no_empty = 0;
  12296     for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot ++) {
  12297         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, src_reg, flag ? REG_PORT_ANY : inst, slot, &rval));
  12298         if (soc_reg_field_get(unit, src_reg, rval, PORT_NUMf) != 0x3f) {
  12299             no_empty = 1;
  12300         }
  12301     }
  12302     if (!no_empty) {
  12303         src_reg = flag ? SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe] : OVR_SUB_GRP_CFGr;
  12304         rval = 0;
  12305         soc_reg_field_set(unit, src_reg, &rval, SAME_SPACINGf, 8);
  12306         soc_reg_field_set(unit, src_reg, &rval, SISTER_SPACINGf, 4);
  12307         soc_reg_field_set(unit, src_reg, &rval, SPEEDf, 0);
  12308         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, src_reg, flag ? REG_PORT_ANY : inst, src_g, rval));
  12309     }
  12310 
  12311     if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  12312         LOG_CLI((BSL_META_U(unit,
  12313                         "Migration on %s sp_id=%d port_mode=%d src_g=%d dst_g=%d DONE.\n"),
  12314                     flag_name[flag], speed_id, port_mode, src_g, dst_g));
  12315         for (i=0; i < p_pm; i++) {
  12316             LOG_CLI((BSL_META_U(unit,
  12317                             "slot[%d] {%d, %d} \n"),
  12318                         entry[i].slot, entry[i].pm_id, entry[i].port_id));
  12319         }
  12320     }
  12321 
  12322     return SOC_E_NONE;
  12323 }
  12324 
  12325 int
  12326 soc_tomahawk_port_lanes_consolidation(int unit, soc_th_port_lanes_t *lanes_ctrl)
  12327 {
  12328 #define _TH_IDB_GROUP    1
  12329 #define _TH_MMU_GROUP    0
  12330 #define _TH_CUR_GROUP    1
  12331 #define _TH_NEW_GROUP    0
  12332     int speed_id, port_mode, lanes;
  12333     int co_enable;
  12334     int oversub_mode;
  12335 
  12336     if (SOC_IS_TOMAHAWK(unit)) {
  12337         oversub_mode = lanes_ctrl->oversub;
  12338         speed_id = lanes_ctrl->cur_class;
  12339         port_mode = lanes_ctrl->cur_mode;
  12340         lanes = lanes_ctrl->lanes;
  12341 
  12342         if (speed_id == -1 || port_mode == -1 || lanes == -1) {
  12343             return SOC_E_PARAM;
  12344         }
  12345 
  12346         co_enable = soc_property_get(unit,
  12347                                      spn_OVERSUB_SPEED_GROUP_CONSOLIDATION_ENABLE,
  12348                                      0);
  12349         if (!oversub_mode) {
  12350             co_enable = 0;
  12351         }
  12352 
  12353         if(co_enable) {
  12354             /* Check whether the speed group requires consolidation */
  12355             lanes_ctrl->action_id = ACT_CONSOLIDATE;
  12356             SOC_IF_ERROR_RETURN
  12357                 (soc_th_speed_group_consolidate_check(unit,
  12358                                                       lanes_ctrl,
  12359                                                       _TH_CUR_GROUP));
  12360 
  12361             /* Migrate all ports to different OS group */
  12362             if (lanes_ctrl->action_id == ACT_MIGRATE) {
  12363                 SOC_IF_ERROR_RETURN
  12364                     (soc_th_speed_group_migrate(unit,
  12365                                                 lanes_ctrl,
  12366                                                 _TH_IDB_GROUP));
  12367                 SOC_IF_ERROR_RETURN
  12368                     (soc_th_speed_group_migrate(unit,
  12369                                                 lanes_ctrl,
  12370                                                 _TH_MMU_GROUP));
  12371             }
  12372         } else {
  12373             lanes_ctrl->action_id = ACT_NONE;
  12374         }
  12375     }
  12376 
  12377     return SOC_E_NONE;
  12378 }
  12379 
  12380 soc_error_t
  12381 soc_th_port_speed_recover(int unit, soc_port_t port)
  12382 {
  12383     soc_info_t *si = &SOC_INFO(unit);
  12384     mac_driver_t *macdp;
  12385     int port_speed = 0;
  12386     int port_rename = 0;
  12387     soc_port_t it_port;
  12388 
  12389     if (!IS_HG_PORT(unit, port) && !IS_CE_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
  12390         return SOC_E_NONE;
  12391     }
  12392 
  12393     SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &macdp));
  12394     SOC_IF_ERROR_RETURN(MAC_SPEED_GET(macdp, unit, port, &port_speed));
  12395     SOC_CONTROL_LOCK(unit);
  12396 
  12397     si->port_init_speed[port] = port_speed;
  12398     /* Update bitmap of high speed ports */
  12399     if (port_speed >= 40000) {
  12400         SOC_PBMP_PORT_ADD(si->eq_pbm, port);
  12401     } else {
  12402         SOC_PBMP_PORT_REMOVE(si->eq_pbm, port);
  12403     }
  12404     /* Adjust XE/CE port name */
  12405     if (IS_E_PORT(unit, port)) {
  12406         if(port_speed < 100000) {
  12407             SOC_PBMP_PORT_REMOVE(si->ce.bitmap, port);
  12408             SOC_PBMP_PORT_ADD(si->xe.bitmap, port);
  12409         } else {
  12410             SOC_PBMP_PORT_ADD(si->ce.bitmap, port);
  12411             SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port);
  12412         }
  12413         port_rename = 1;
  12414     }
  12415     if (port_rename) {
  12416         _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(xe);
  12417         _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ce);
  12418         soc_dport_map_update(unit);
  12419     }
  12420 
  12421     SOC_CONTROL_UNLOCK(unit);
  12422     return SOC_E_NONE;
  12423 }
  12424 
  12425 /*
  12426  * Function:
  12427  *      soc_th_flexport_recover
  12428  * Description:
  12429  *      Add port to xe/ce and high speed port bitmap by reading
  12430  *      port speed.
  12431  * Parameters:
  12432  *      unit      - Device number
  12433  *      port      - logical port number
  12434  */
  12435 soc_error_t
  12436 soc_th_flexport_recover(int unit, soc_port_t port)
  12437 {
  12438     soc_info_t *si = &SOC_INFO(unit);
  12439     soc_port_t it_port;
  12440     mac_driver_t *macdp;
  12441     int port_speed = 0, port_rename = 0;
  12442 
  12443     SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &macdp));
  12444     SOC_IF_ERROR_RETURN(MAC_SPEED_GET(macdp, unit, port, &port_speed));
  12445     SOC_CONTROL_LOCK(unit);
  12446     si->port_init_speed[port] = port_speed;
  12447     /* Update bitmap of high speed ports */
  12448     if (port_speed >= 40000) {
  12449         SOC_PBMP_PORT_ADD(si->eq_pbm, port);
  12450     } else {
  12451         SOC_PBMP_PORT_REMOVE(si->eq_pbm, port);
  12452     }
  12453     /* Adjust XE/CE port bitmaps */
  12454     if (IS_E_PORT(unit, port)) {
  12455         if (port_speed < 100000) {
  12456             SOC_PBMP_PORT_REMOVE(si->ce.bitmap, port);
  12457             SOC_PBMP_PORT_ADD(si->xe.bitmap, port);
  12458             port_rename = 1;
  12459         } else {
  12460             SOC_PBMP_PORT_ADD(si->ce.bitmap, port);
  12461             SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port);
  12462             port_rename = 1;
  12463         }
  12464     }
  12465     if (port_rename) {
  12466         _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(xe);
  12467         _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ce);
  12468         soc_dport_map_update(unit);
  12469     }
  12470     SOC_CONTROL_UNLOCK(unit);
  12471 
  12472     return SOC_E_NONE;
  12473 }
  12474 
  12475 soc_error_t
  12476 soc_th_granular_speed_get(int unit, soc_port_t port, int *speed)
  12477 {
  12478     uint32 fval, rval;
  12479 
  12480 #if defined(BCM_TOMAHAWK2_SUPPORT)
  12481     egr_mmu_cell_credit_entry_t credit_entry;
  12482     if (soc_feature(unit, soc_feature_egr_mmu_cell_credit_is_memory)) {
  12483         SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ANY,
  12484                             SOC_INFO(unit).port_l2p_mapping[port], &credit_entry));
  12485         fval = soc_EGR_MMU_CELL_CREDITm_field32_get(unit, &credit_entry, CREDITf);
  12486     } else
  12487 #endif
  12488     {
  12489         SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITr(unit, port, &rval));
  12490         fval = soc_reg_field_get(unit, EGR_MMU_CELL_CREDITr, rval, CREDITf);
  12491     }
  12492     SOC_IF_ERROR_RETURN(soc_th_port_asf_mmu_cell_credit_to_speed
  12493                            (unit, port, (uint8) fval, speed));
  12494     return SOC_E_NONE;
  12495 }
  12496 
  12497 void
  12498 soc_tomahawk_temperature_intr(void *unit_vp, void *d1, void *d2,
  12499                               void *d3, void *d4)
  12500 {
  12501     uint32 rval, trval;
  12502     int i, rv, unit = PTR_TO_INT(unit_vp);
  12503     soc_port_t port;
  12504     soc_block_t blk;
  12505 
  12506     if ((rv = READ_TOP_PVTMON_INTR_STATUSr(unit, &rval)) != SOC_E_NONE) {
  12507         LOG_ERROR(BSL_LS_SOC_COMMON,
  12508                   (BSL_META_U(unit,
  12509                               "TH Temp Intr, Reg access error.\n")));
  12510     }
  12511     LOG_ERROR(BSL_LS_SOC_COMMON,
  12512               (BSL_META_U(unit,
  12513                           "High temp interrupt: 0x%08x\n"), rval));
  12514     /* Raise event to app for it to take further graceful actions */
  12515     for (i = 0; i < COUNTOF(pvtmon_result_reg); i++) {
  12516         if ((0x1 << i)  & _soc_th_temp_mon_mask[unit]) {
  12517             if ((rv = soc_reg32_get(unit, pvtmon_result_reg[i], REG_PORT_ANY, 0,
  12518                                     &trval)) != SOC_E_NONE) {
  12519                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12520                           (BSL_META_U(unit,
  12521                                       "TH Temp Intr, Reg access error.\n")));
  12522             }
  12523             trval = soc_reg_field_get(unit, pvtmon_result_reg[i], trval,
  12524                                       PVT_DATAf);
  12525 #ifdef BCM_TOMAHAWK2_SUPPORT
  12526             if (SOC_IS_TOMAHAWK2(unit)) {
  12527                 /* Temp = 434.10 - o_ADC_data * 0.53504
  12528                  * data = (434.10 - temp)/0.53504 = (434100-(temp*1000))/535
  12529                  * Note: Since this is a high temp value we can safely assume it to
  12530                  * always be a +ive number. This is in degrees celcius.
  12531                  */
  12532                 trval = (434100-(trval*535))/1000;
  12533             } else
  12534 #endif /* BCM_TOMAHAWK2_SUPPORT */
  12535             {
  12536                 /* Convert data to temperature.
  12537                  * temp = 410.04-(data*0.48705) = (410040-(data*487))/1000
  12538                  * Note: Since this is a high temp interrupt we can safely assume
  12539                  * that this will end up being a +ive value.
  12540                  */
  12541                 trval = (410040-(trval*487))/1000;
  12542             }
  12543             LOG_ERROR(BSL_LS_SOC_COMMON,
  12544                       (BSL_META_U(unit,
  12545                                   "TempMon %d: %d deg C.\n"), i, trval));
  12546             (void)soc_event_generate(unit, SOC_SWITCH_EVENT_ALARM,
  12547                                      SOC_SWITCH_EVENT_ALARM_HIGH_TEMP, i, trval);
  12548         }
  12549     }
  12550     /* Optionally hold system in reset. TH2 will skip as it has HW overtemp protection.
  12551      * Note: The main intention is to stop the chip from getting fried and halt
  12552      *       all schan accesses as the h/w will not respond anymore.
  12553      *       We are not implementing a gracefull recovery, the unit needs to be
  12554      *       rebooted after this.
  12555      */
  12556     if ((!SOC_IS_TOMAHAWK2(unit))&&
  12557         (soc_property_get(unit, "temp_monitor_shutdown", 1))) {
  12558         if ((rv = WRITE_TOP_PVTMON_INTR_MASKr(unit, 0)) != SOC_E_NONE) {
  12559             LOG_ERROR(BSL_LS_SOC_COMMON,
  12560                       (BSL_META_U(unit,
  12561                                   "TH Temp Intr, Reg access error.\n")));
  12562         }
  12563 
  12564         /* Stop all schan transactions on this unit */
  12565 #ifdef  INCLUDE_I2C
  12566         if ((rv = soc_i2c_detach(unit)) != SOC_E_NONE) {
  12567             LOG_ERROR(BSL_LS_SOC_COMMON,
  12568                       (BSL_META_U(unit,
  12569                                   "TH Temp Intr, i2c detach error.\n")));
  12570         }
  12571 #endif
  12572         if (!SOC_IS_RCPU_ONLY(unit)) {
  12573             /* Free up DMA memory */
  12574             if ((rv = soc_dma_detach(unit)) != SOC_E_NONE) {
  12575                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12576                           (BSL_META_U(unit,
  12577                                       "TH Temp Intr, dma detach error.\n")));
  12578             }
  12579         }
  12580 #ifdef INCLUDE_MEM_SCAN        
  12581         if ((rv = soc_mem_scan_stop(unit)) != SOC_E_NONE) {
  12582             LOG_ERROR(BSL_LS_SOC_COMMON,
  12583                       (BSL_META_U(unit,
  12584                                   "TH Temp Intr, mem scan stop error.\n")));
  12585         }
  12586 #endif /* INCLUDE_MEM_SCAN */      
  12587         /* Terminate counter module */
  12588         if ((rv = soc_counter_stop(unit)) != SOC_E_NONE) {
  12589             LOG_ERROR(BSL_LS_SOC_COMMON,
  12590                       (BSL_META_U(unit,
  12591                                   "TH Temp Intr, counter stop error.\n")));
  12592         }
  12593         if (SOC_SBUSDMA_DM_INFO(unit)) {
  12594             if ((rv = soc_sbusdma_desc_detach(unit)) != SOC_E_NONE) {
  12595                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12596                           (BSL_META_U(unit,
  12597                                       "TH Temp Intr, sbusdma stop error.\n")));
  12598             }
  12599         }
  12600         if (soc_feature(unit, soc_feature_arl_hashed)) {
  12601             /* Stop L2X thread */
  12602             if ((rv = soc_l2x_stop(unit)) != SOC_E_NONE) {
  12603                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12604                           (BSL_META_U(unit,
  12605                                       "TH Temp Intr, L2x stop error.\n")));
  12606             }
  12607 
  12608         }
  12609         if ((rv = soc_th_l2_bulk_age_stop(unit)) != SOC_E_NONE) {
  12610             LOG_ERROR(BSL_LS_SOC_COMMON,
  12611                       (BSL_META_U(unit,
  12612                                   "TH Temp Intr, L2 age stop error.\n")));
  12613         }
  12614 
  12615         rv = READ_TOP_SOFT_RESET_REGr(unit, &rval);
  12616         if (SOC_E_NONE != rv) {
  12617             LOG_ERROR(BSL_LS_SOC_COMMON,
  12618                       (BSL_META_U(unit,
  12619                                   "TH Temp Intr, Reg access error.\n")));
  12620         }
  12621         soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_TS_RST_Lf, 0);
  12622         soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_MMU_RST_Lf, 0);
  12623         soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_EP_RST_Lf, 0);
  12624         soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_IP_RST_Lf, 0);
  12625         rv = WRITE_TOP_SOFT_RESET_REGr(unit, rval);
  12626         if (SOC_E_NONE != rv) {
  12627             LOG_ERROR(BSL_LS_SOC_COMMON,
  12628                       (BSL_META_U(unit,
  12629                                   "TH Temp Intr, Reg access error.\n")));
  12630         }
  12631 
  12632         if ((rv = READ_TOP_SOFT_RESET_REG_2r(unit, &rval)) != SOC_E_NONE) {
  12633             LOG_ERROR(BSL_LS_SOC_COMMON,
  12634                       (BSL_META_U(unit,
  12635                                   "TH Temp Intr, Reg access error.\n")));
  12636         }
  12637 
  12638 #ifdef BCM_TOMAHAWK2_SUPPORT
  12639         if (SOC_IS_TOMAHAWK2(unit)) {
  12640             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL0_RST_Lf,
  12641                               0);
  12642             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_TS_PLL_RST_Lf,
  12643                               1);
  12644             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL0_RST_Lf,
  12645                               0);
  12646             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL1_RST_Lf,
  12647                               0);
  12648             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf, 1);
  12649         } else
  12650 #endif /* BCM_TOMAHAWK2_SUPPORT */
  12651         {
  12652             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL0_RST_Lf,
  12653                               0);
  12654             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL1_RST_Lf,
  12655                               0);
  12656             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL2_RST_Lf,
  12657                               0);
  12658             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL3_RST_Lf,
  12659                               0);
  12660             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_TS_PLL_RST_Lf,
  12661                               1);
  12662             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL0_RST_Lf,
  12663                               0);
  12664             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL1_RST_Lf,
  12665                               0);
  12666             soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf, 1);
  12667         }
  12668 
  12669         if ((rv = WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)) != SOC_E_NONE) {
  12670             LOG_ERROR(BSL_LS_SOC_COMMON,
  12671                       (BSL_META_U(unit,
  12672                                   "TH Temp Intr, Reg access error.\n")));
  12673         }
  12674         /* Powerdown Falcon analog cores */
  12675         SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
  12676             port = SOC_BLOCK_PORT(unit, blk);
  12677             rv = READ_CLPORT_XGXS0_CTRL_REGr(unit, port, &rval);
  12678             if (SOC_E_NONE != rv) {
  12679                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12680                           (BSL_META_U(unit,
  12681                                       "TH Temp Intr, Reg access error.\n")));
  12682             }
  12683             soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, &rval, IDDQf, 1);
  12684             soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, &rval, PWRDWNf, 1);
  12685             soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, &rval, RSTB_HWf, 0);
  12686             rv = WRITE_CLPORT_XGXS0_CTRL_REGr(unit, port, rval);
  12687             if (SOC_E_NONE != rv) {
  12688                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12689                           (BSL_META_U(unit,
  12690                                       "TH Temp Intr, Reg access error.\n")));
  12691             }
  12692         }
  12693         /* Powerdown Eagle analog cores */
  12694         SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
  12695             port = SOC_BLOCK_PORT(unit, blk);
  12696             rv = READ_XLPORT_XGXS0_CTRL_REGr(unit, port, &rval);
  12697             if (SOC_E_NONE != rv) {
  12698                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12699                           (BSL_META_U(unit,
  12700                                       "TH Temp Intr, Reg access error.\n")));
  12701             }
  12702             soc_reg_field_set(unit, XLPORT_XGXS0_CTRL_REGr, &rval, IDDQf, 1);
  12703             soc_reg_field_set(unit, XLPORT_XGXS0_CTRL_REGr, &rval, PWRDWNf, 1);
  12704             soc_reg_field_set(unit, XLPORT_XGXS0_CTRL_REGr, &rval, RSTB_HWf, 0);
  12705             rv = WRITE_XLPORT_XGXS0_CTRL_REGr(unit, port, rval);
  12706             if (SOC_E_NONE != rv) {
  12707                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12708                           (BSL_META_U(unit,
  12709                                       "TH Temp Intr, Reg access error.\n")));
  12710             }
  12711         }
  12712 
  12713         /* Disable all interrupts */
  12714 #ifdef BCM_CMICM_SUPPORT
  12715         if (soc_feature(unit, soc_feature_cmicm)) {
  12716             soc_cmicm_intr0_disable(unit, ~0);
  12717             soc_cmicm_intr1_disable(unit, ~0);
  12718             soc_cmicm_intr2_disable(unit, ~0);
  12719             soc_cmicm_intr3_disable(unit, ~0);
  12720             soc_cmicm_intr4_disable(unit, ~0);
  12721             soc_cmicm_intr5_disable(unit, ~0);
  12722         }
  12723 #endif
  12724 
  12725 #ifdef BCM_CMICDV4_SUPPORT
  12726         if (soc_feature(unit, soc_feature_cmicd_v4)) {
  12727             soc_cmicm_intr6_disable(unit, ~0);
  12728         }
  12729 #endif /* BCM_CMICDV4_SUPPORT */
  12730 
  12731         /* Power down core PLL, once this is done all SCHAN accesses
  12732          * will fail.
  12733          */
  12734 #ifdef BCM_TOMAHAWK2_SUPPORT
  12735         if (SOC_IS_TOMAHAWK2(unit)) {
  12736             rv = READ_TOP_CORE_PLL0_CTRL_6r(unit, &rval);
  12737             if (SOC_E_NONE != rv) {
  12738                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12739                           (BSL_META_U(unit,
  12740                                       "TH2 Temp Intr, Reg access error.\n")));
  12741             }
  12742             soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_6r, &rval, ISO_INANDOUT_AONf, 1);
  12743             soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_6r, &rval, PWRON_PLL_AONf, 0);
  12744             soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_6r, &rval, PWRON_LDO_ANALOG_AONf, 0);
  12745             WRITE_TOP_CORE_PLL0_CTRL_6r(unit, rval);
  12746         } else
  12747 #endif /* BCM_TOMAHAWK2_SUPPORT */
  12748         {
  12749             rv = READ_TOP_CORE_PLL0_CTRL_1r(unit, &rval);
  12750             if (SOC_E_NONE != rv) {
  12751                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12752                           (BSL_META_U(unit,
  12753                                       "TH Temp Intr, Reg access error.\n")));
  12754             }
  12755             soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_1r, &rval, ISO_INf, 1);
  12756             soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_1r, &rval, PWRONf, 0);
  12757             soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_1r, &rval, PWRON_LDOf, 0);
  12758             WRITE_TOP_CORE_PLL0_CTRL_1r(unit, rval);
  12759         }
  12760         SCHAN_LOCK(unit);
  12761 
  12762         /* Clear all outstanding DPCs owned by this unit */
  12763         sal_dpc_cancel(INT_TO_PTR(unit));
  12764         LOG_ERROR(BSL_LS_SOC_COMMON,
  12765                   (BSL_META_U(unit,
  12766                               "\nReboot the system..")));
  12767     }
  12768 }
  12769 
  12770 int
  12771 soc_tomahawk_temperature_monitor_get(int unit, int temperature_max,
  12772     soc_switch_temperature_monitor_t *temperature_array, int *temperature_count)
  12773 {
  12774     soc_reg_t reg;
  12775     int index;
  12776     uint32 rval;
  12777     int fval, cur, peak;
  12778     int num_entries_out;
  12779 
  12780     if (temperature_count) {
  12781         *temperature_count = 0;
  12782     }
  12783     if (COUNTOF(pvtmon_result_reg) > temperature_max) {
  12784         num_entries_out = temperature_max;
  12785     } else {
  12786         num_entries_out = COUNTOF(pvtmon_result_reg);
  12787     }
  12788     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_1r(unit, &rval));
  12789     if ((soc_reg_field_get(unit, TOP_PVTMON_CTRL_1r, rval, PVTMON_RESET_Nf) == 0) ||
  12790         (soc_reg_field_get(unit, TOP_PVTMON_CTRL_1r, rval, PVTMON_SELECTf) != 0)) {
  12791         soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_RESET_Nf, 0);
  12792         SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval));
  12793         soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_RESET_Nf, 1);
  12794         soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_SELECTf, 0);
  12795         SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval));
  12796         sal_usleep(1000);
  12797     }
  12798 
  12799     for (index = 0; index < num_entries_out; index++) {
  12800         reg = pvtmon_result_reg[index];
  12801         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
  12802         fval = soc_reg_field_get(unit, reg, rval, PVT_DATAf);
  12803 #if defined(BCM_TOMAHAWK2_SUPPORT)
  12804         if (SOC_IS_TOMAHAWK2(unit)) {
  12805             cur = (4341000-(fval*5350))/1000;
  12806         } else
  12807 #endif /* BCM_TOMAHAWK2_SUPPORT */
  12808         {
  12809             cur = (4100400-(fval*4870))/1000;
  12810         }
  12811         fval = soc_reg_field_get(unit, reg, rval, MIN_PVT_DATAf);
  12812 #if defined(BCM_TOMAHAWK2_SUPPORT)
  12813         if (SOC_IS_TOMAHAWK2(unit)) {
  12814             peak = (4341000-(fval*5350))/1000;
  12815         } else
  12816 #endif /* BCM_TOMAHAWK2_SUPPORT */
  12817         {
  12818             peak = (4100400-(fval*4870))/1000;
  12819         }
  12820         if (temperature_array) {
  12821             (temperature_array + index)->curr = cur;
  12822             (temperature_array + index)->peak = peak;
  12823         }
  12824     }
  12825     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
  12826     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
  12827                       TOP_PVT_MON_MIN_RST_Lf, 0);
  12828     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
  12829     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
  12830                       TOP_PVT_MON_MIN_RST_Lf, 1);
  12831     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
  12832 
  12833     if (temperature_count) {
  12834         *temperature_count = num_entries_out;
  12835     }
  12836     return SOC_E_NONE;
  12837 }
  12838 
  12839 int
  12840 soc_tomahawk_show_voltage(int unit)
  12841 {
  12842     soc_reg_t reg;
  12843     int index;
  12844     uint32 rval, fval, avg;
  12845 
  12846     if (!SOC_IS_TOMAHAWK3(unit)) {
  12847         SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_1r(unit, &rval));
  12848         if ((soc_reg_field_get(unit, TOP_PVTMON_CTRL_1r, rval, PVTMON_RESET_Nf) == 0) ||
  12849             (soc_reg_field_get(unit, TOP_PVTMON_CTRL_1r, rval, PVTMON_SELECTf) != 4)) {
  12850             soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_RESET_Nf, 0);
  12851             SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval));
  12852             soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_RESET_Nf, 1);
  12853             soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_SELECTf, 4);
  12854             SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval));
  12855             sal_usleep(1000);
  12856         }
  12857     }
  12858 
  12859     avg = 0;
  12860 
  12861     /* Read Voltages. */
  12862     for (index = 0; index < COUNTOF(pvtmon_result_reg); index++) {
  12863         reg = pvtmon_result_reg[index];
  12864         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
  12865         fval = soc_reg_field_get(unit, reg, rval, PVT_DATAf);
  12866 #ifdef BCM_TOMAHAWK2_SUPPORT
  12867         if (SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit)) {
  12868             /* (PVT_DATA * 950) / (1024 * 0.8) */
  12869             fval = (fval * 950 * 10) / (1024 * 8);
  12870         } else
  12871 #endif /* BCM_TOMAHAWK2_SUPPORT */
  12872         {
  12873             LOG_CLI((BSL_META_U(unit,
  12874                                 "Voltage monitor fail: Need to add formula for current device.\n")));
  12875             return SOC_E_UNAVAIL;
  12876         }
  12877         avg += fval;
  12878         LOG_CLI((BSL_META_U(unit,
  12879                             "Voltage monitor %d: voltage = %d.%03dV\n"),
  12880                  index, (fval/1000), (fval %1000)));
  12881     }
  12882 
  12883     avg /= (COUNTOF(pvtmon_result_reg));
  12884     LOG_CLI((BSL_META_U(unit,
  12885                         "Average voltage is = %d.%03dV\n"),
  12886              (avg/1000), (avg %1000)));
  12887 
  12888     return SOC_E_NONE;
  12889 }
  12890 
  12891 int
  12892 soc_tomahawk_show_ring_osc(int unit)
  12893 {
  12894     static const struct {
  12895         int osc_sel;
  12896         soc_field_t field0;
  12897         int value0;
  12898         soc_field_t field1;
  12899         int value1;
  12900         char *name;
  12901     } osc_tbl[] = {
  12902         { 2, IROSC_SELf, 0, INVALIDf, -1, "Core ring 0 five stages" },
  12903         { 2, IROSC_SELf, 1, INVALIDf, -1, "Core ring 0 nine stages" },
  12904         { 3, IROSC_SELf, 0, INVALIDf, -1, "Core ring 1 five stages" },
  12905         { 3, IROSC_SELf, 1, INVALIDf, -1, "Core ring 1 nine stages" },
  12906         { 4, SRAM_OSC_0_PENf, 0, SRAM_OSC_0_NENf, 1, "SRAM ring 0 NMOS" },
  12907         { 5, SRAM_OSC_0_PENf, 1, SRAM_OSC_0_NENf, 0, "SRAM ring 0 PMOS" },
  12908         { 6, SRAM_OSC_1_PENf, 0, SRAM_OSC_1_NENf, 1, "SRAM ring 1 NMOS" },
  12909         { 7, SRAM_OSC_1_PENf, 1, SRAM_OSC_1_NENf, 0, "SRAM ring 1 PMOS" },
  12910         { 8, SRAM_OSC_2_PENf, 0, SRAM_OSC_2_NENf, 1, "SRAM ring 2 NMOS" },
  12911         { 9, SRAM_OSC_2_PENf, 1, SRAM_OSC_2_NENf, 0, "SRAM ring 2 PMOS" },
  12912         { 10, SRAM_OSC_3_PENf, 0, SRAM_OSC_3_NENf, 1, "SRAM ring 3 NMOS" },
  12913         { 11, SRAM_OSC_3_PENf, 1, SRAM_OSC_3_NENf, 0, "SRAM ring 3 PMOS" }
  12914     };
  12915     soc_reg_t ctrl_reg, stat_reg;
  12916     uint32 rval, fval;
  12917     int index, core_clk, quo, rem, frac, retry;
  12918 
  12919     core_clk = SOC_INFO(unit).frequency * 1024;
  12920     ctrl_reg = TOP_RING_OSC_CTRLr;
  12921     stat_reg = TOP_OSC_COUNT_STATr;
  12922 
  12923     for (index = 0; index < COUNTOF(osc_tbl); index++) {
  12924         rval = 0;
  12925 
  12926 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  12927         if (SOC_IS_TOMAHAWK2(unit) || (SOC_IS_TOMAHAWK3(unit))) {
  12928             if (SRAM_OSC_1_PENf == osc_tbl[index].field0 ||
  12929                 SRAM_OSC_2_PENf == osc_tbl[index].field0 ||
  12930                 SRAM_OSC_3_PENf == osc_tbl[index].field0) {
  12931                 continue;
  12932             }
  12933         }
  12934 #endif
  12935 
  12936         /*
  12937          * set OSC_CNT_RSTBf to 0 to do softreset
  12938          * set OSC_CNT_START to 0 to hold the counter until it selects
  12939          * the input signal
  12940          */
  12941         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
  12942         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_ENABLEf, 1);
  12943         soc_reg_field_set(unit, ctrl_reg, &rval, IROSC_ENf, 1);
  12944         soc_reg_field_set(unit, ctrl_reg, &rval, osc_tbl[index].field0,
  12945                           osc_tbl[index].value0);
  12946         if (osc_tbl[index].field1 != INVALIDf) {
  12947             soc_reg_field_set(unit, ctrl_reg, &rval, osc_tbl[index].field1,
  12948                               osc_tbl[index].value1);
  12949         }
  12950         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_SELf,
  12951                           osc_tbl[index].osc_sel);
  12952         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
  12953         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_CNT_RSTBf, 1);
  12954         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
  12955         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_CNT_STARTf, 1);
  12956         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
  12957 
  12958         for (retry = 0; retry < 10; retry++) {
  12959             sal_usleep(1000);
  12960             SOC_IF_ERROR_RETURN(READ_TOP_OSC_COUNT_STATr(unit, &rval));
  12961             if (!soc_reg_field_get(unit, stat_reg, rval, OSC_CNT_DONEf)) {
  12962                 continue;
  12963             }
  12964 
  12965             fval = soc_reg_field_get(unit, stat_reg, rval, OSC_CNT_VALUEf);
  12966             quo = core_clk / fval;
  12967             rem = core_clk - quo * fval;
  12968             frac = (rem * 10000) / fval;
  12969             LOG_CLI((BSL_META_U(unit,
  12970                                 "%s: %d.%04d Mhz\n"),
  12971                      osc_tbl[index].name, quo, frac));
  12972             break;
  12973         }
  12974     }
  12975 
  12976     return SOC_E_NONE;
  12977 }
  12978 
  12979 STATIC _soc_th_bst_hw_cb th_bst_cb;
  12980 
  12981 int
  12982 _soc_th_process_mmu_bst(int unit, int xpe, soc_field_t field)
  12983 {
  12984     int rv = SOC_E_NONE;
  12985     if (th_bst_cb != NULL) {
  12986         rv = th_bst_cb(unit);
  12987     }
  12988     return rv;
  12989 }
  12990 
  12991 int soc_th_set_bst_callback(int unit, _soc_th_bst_hw_cb cb)
  12992 {
  12993     th_bst_cb = cb;
  12994     return SOC_E_NONE;
  12995 }
  12996 
  12997 void
  12998 soc_tomahawk_process_func_intr(void *unit_vp, void *d1, void *d2, void *d3, void *d4)
  12999 {
  13000     int rv = SOC_E_NONE;
  13001     int unit = PTR_TO_INT(unit_vp);
  13002     uint32 rval;
  13003     char       prefix_str[10];
  13004     sal_sprintf(prefix_str, "Unit: %d \n", unit);
  13005 
  13006     rv = READ_L2_MGMT_INTRr(unit, &rval);
  13007     if (SOC_FAILURE(rv)) {
  13008         LOG_ERROR(BSL_LS_SOC_COMMON,
  13009                   (BSL_META_U(unit, "Error reading %s reg !!\n"),
  13010                               SOC_REG_NAME(unit, L2_MGMT_INTRr)));
  13011         return;
  13012     }
  13013 
  13014     if (soc_reg_field_get(unit, L2_MGMT_INTRr, rval, SER_FIFO_NOT_EMPTYf)) {
  13015         (void) soc_tomahawk_process_ser_fifo(unit, SOC_BLK_IPIPE,
  13016                                              0, /* pipe */
  13017                                              prefix_str,
  13018                                              1, 0, 0); /* l2_mgmt_ser_fifo */
  13019     }
  13020 
  13021     if (soc_feature(unit, soc_feature_l2_overflow)) {
  13022         if (soc_reg_field_get(unit, L2_MGMT_INTRr, rval, L2_LEARN_INSERT_FAILUREf)) {
  13023             soc_td2_l2_overflow_interrupt_handler(unit);
  13024         }
  13025     }
  13026 
  13027     sal_usleep(SAL_BOOT_QUICKTURN ? 100000 : 1000); /* Don't reenable too soon */
  13028     if (d1 != NULL) {
  13029 #ifdef BCM_CMICM_SUPPORT
  13030         if (soc_feature(unit, soc_feature_cmicm)) {
  13031             (void) soc_cmicm_intr3_enable(unit, PTR_TO_INT(d1));
  13032         }
  13033 #endif
  13034     }
  13035 }
  13036 
  13037 /*
  13038  * All non-parity related interrupts must be handled in this function.
  13039  * All unserviced intr_status bits must either be serviced or disabled.
  13040  *
  13041  * Note:
  13042  * 1. MEM_PAR_ERR_STATf is handled by tomahawk/ser.c, so ignore this
  13043  * 2. blocktype (in) can only be SOC_BLK_MMU_XPE/SC
  13044  */
  13045 int
  13046 soc_th_mmu_non_ser_intr_handler(int unit, soc_block_t blocktype,
  13047                                 int mmu_base_index,
  13048                                 uint32 rval_intr_status_reg)
  13049 {
  13050     int i;
  13051     uint32 rval = 0;
  13052     soc_reg_t intr_stat_reg, intr_clr_reg;
  13053     static soc_field_t xpe_intr_field_list[] = {
  13054         MEM_PAR_ERR_STATf, /* handled by tomahawk/ser.c, so ignore this */
  13055         BST_THDI_INT_STATf,
  13056         BST_THDO_INT_STATf,
  13057         DEQ0_NOT_IP_ERR_STATf,
  13058         DEQ1_NOT_IP_ERR_STATf,
  13059         INVALIDf
  13060     };
  13061     static soc_field_t sc_intr_field_list[] = {
  13062         CFAP_A_MEM_FAIL_STATf,
  13063         CFAP_B_MEM_FAIL_STATf,
  13064         MEM_PAR_ERR_STATf, /* handled by tomahawk/ser.c, so ignore this */
  13065         BST_CFAP_A_INT_STATf,
  13066         BST_CFAP_B_INT_STATf,
  13067         ES_X_DEADLOCK_DET_INT_STATf,
  13068         ES_Y_DEADLOCK_DET_INT_STATf,
  13069         START_BY_START_ERR_STATf,
  13070         ES_X_1IN4_ERR_INT_STATf,
  13071         ES_Y_1IN4_ERR_INT_STATf,
  13072         INVALIDf
  13073     };
  13074 
  13075     if (blocktype == SOC_BLK_MMU_XPE) {
  13076         intr_stat_reg = MMU_XCFG_XPE_CPU_INT_STATr;
  13077         intr_clr_reg = MMU_XCFG_XPE_CPU_INT_CLEARr;
  13078         for (i = 0; xpe_intr_field_list[i] != INVALIDf; i++) {
  13079             if (!soc_reg_field_get(unit, intr_stat_reg,
  13080                                    rval_intr_status_reg,
  13081                                    xpe_intr_field_list[i])) {
  13082                 continue;
  13083             }
  13084             switch (xpe_intr_field_list[i]) {
  13085             case BST_THDI_INT_STATf:
  13086             case BST_THDO_INT_STATf:
  13087                 /* interrupt processing */
  13088                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  13089                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
  13090                                               "from xpe = %0d \n"),
  13091                              unit, SOC_FIELD_NAME(unit, xpe_intr_field_list[i]),
  13092                              mmu_base_index));
  13093 
  13094                 /* clear the interrupt */
  13095                 SOC_IF_ERROR_RETURN
  13096                     (soc_tomahawk_xpe_reg32_get(unit, intr_clr_reg,
  13097                                                 mmu_base_index, mmu_base_index,
  13098                                                 0, &rval));
  13099                 rval |= (1 << i);
  13100                 SOC_IF_ERROR_RETURN
  13101                     (soc_tomahawk_xpe_reg32_set(unit, intr_clr_reg,
  13102                                                 mmu_base_index, mmu_base_index,
  13103                                                 0, rval));
  13104                 SOC_IF_ERROR_RETURN
  13105                     (_soc_th_process_mmu_bst(unit, mmu_base_index,
  13106                                              xpe_intr_field_list[i]));
  13107                 break;
  13108             default:
  13109                 LOG_ERROR(BSL_LS_SOC_COMMON,
  13110                           (BSL_META_U(unit, "Unit: %0d -- Could not service %s "
  13111                                             "intr from xpe = %0d \n"),
  13112                            unit, SOC_FIELD_NAME(unit, xpe_intr_field_list[i]),
  13113                            mmu_base_index));
  13114                 break;
  13115             }
  13116         }
  13117         return SOC_E_NONE;
  13118     }
  13119 
  13120     if (blocktype == SOC_BLK_MMU_SC) {
  13121         intr_stat_reg = MMU_SCFG_SC_CPU_INT_STATr;
  13122         intr_clr_reg = MMU_SCFG_SC_CPU_INT_CLEARr;
  13123         for (i = 0; sc_intr_field_list[i] != INVALIDf; i++) {
  13124             if (!soc_reg_field_get(unit, intr_stat_reg,
  13125                                    rval_intr_status_reg,
  13126                                    sc_intr_field_list[i])) {
  13127                 continue;
  13128             }
  13129             switch (sc_intr_field_list[i]) {
  13130             case BST_CFAP_A_INT_STATf:
  13131             case BST_CFAP_B_INT_STATf:
  13132                 /* interrupt processing */
  13133                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  13134                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
  13135                                               "from sc = %0d \n"),
  13136                              unit, SOC_FIELD_NAME(unit, sc_intr_field_list[i]),
  13137                              mmu_base_index));
  13138 
  13139 
  13140                 /* clear the interrupt */
  13141                 SOC_IF_ERROR_RETURN
  13142                     (soc_tomahawk_sc_reg32_get(unit, intr_clr_reg,
  13143                                                mmu_base_index, mmu_base_index,
  13144                                                0, &rval));
  13145                 rval |= (1 << i);
  13146                 SOC_IF_ERROR_RETURN
  13147                     (soc_tomahawk_sc_reg32_set(unit, intr_clr_reg,
  13148                                                mmu_base_index, mmu_base_index,
  13149                                                0, rval));
  13150                 SOC_IF_ERROR_RETURN
  13151                     (_soc_th_process_mmu_bst(unit, mmu_base_index,
  13152                                              sc_intr_field_list[i]));
  13153 
  13154                 break;
  13155             case CFAP_A_MEM_FAIL_STATf:
  13156             case CFAP_B_MEM_FAIL_STATf:
  13157                 /* interrupt processing */
  13158                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  13159                             (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr "
  13160                                               "from sc = %0d \n"),
  13161                              unit, SOC_FIELD_NAME(unit, sc_intr_field_list[i]),
  13162                              mmu_base_index));
  13163 
  13164                 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR,
  13165                                    SOC_SWITCH_EVENT_DATA_ERROR_CFAP_MEM_FAIL, -1, -1);
  13166 
  13167                 /* clear the interrupt */
  13168                 SOC_IF_ERROR_RETURN
  13169                     (soc_tomahawk_sc_reg32_get(unit, intr_clr_reg,
  13170                                                mmu_base_index, mmu_base_index,
  13171                                                0, &rval));
  13172                 rval |= (1 << i);
  13173                 SOC_IF_ERROR_RETURN
  13174                     (soc_tomahawk_sc_reg32_set(unit, intr_clr_reg,
  13175                                                mmu_base_index, mmu_base_index,
  13176                                                0, rval));
  13177                 break;
  13178             default:
  13179                 LOG_ERROR(BSL_LS_SOC_COMMON,
  13180                           (BSL_META_U(unit, "Unit: %0d -- Could not service %s "
  13181                                             "intr from sc = %0d \n"),
  13182                            unit, SOC_FIELD_NAME(unit, sc_intr_field_list[i]),
  13183                            mmu_base_index));
  13184                 break;
  13185             }
  13186         }
  13187         return SOC_E_NONE;
  13188     }
  13189 
  13190     /* cannot be here for any other blocktype */
  13191     return SOC_E_FAIL;
  13192 }
  13193 
  13194 STATIC int
  13195 _soc_th_mmu_config_shared_update_check(int val1, int val2, int flags)
  13196 {
  13197     int rv = 0;
  13198     if (flags == 1) {
  13199         if (val1 > val2) {
  13200             rv = 1;
  13201         }
  13202     } else {
  13203         if (val1 < val2) {
  13204             rv = 1;
  13205         }
  13206     }
  13207     return rv;
  13208 }
  13209 
  13210 #define TH_MMU_SHARED_LIMIT_CHK(val1, val2, flags) \
  13211     _soc_th_mmu_config_shared_update_check((val1), (val2), (flags))
  13212 
  13213 int
  13214 soc_th_mmu_config_shared_buf_recalc(int unit, int res, 
  13215                         int *thdi_shd, int *thdo_db_shd, int *thdo_qe_shd,
  13216                         int post_update)
  13217 {
  13218     soc_info_t *si;
  13219     int pipe, xpe, xpe_map;
  13220     uint32 entry0[SOC_MAX_MEM_WORDS], cur_limit, rval = 0, rval2 = 0;
  13221     thdi_port_pg_config_entry_t pg_config_mem;
  13222     mmu_thdo_config_qgroup_entry_t cfg_qgrp;
  13223     int port, base, numq, idx, midx;
  13224     soc_mem_t base_mem = INVALIDm;
  13225     soc_mem_t mem = INVALIDm;
  13226     soc_reg_t reg = INVALIDr;
  13227     soc_field_t field = INVALIDf;
  13228     int granularity;
  13229     int thdi_shd_min, thdo_db_shd_min, thdo_qe_shd_min;
  13230 
  13231     si = &SOC_INFO(unit);
  13232 
  13233     xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1];
  13234     
  13235     _TH_ARRAY_MIN(thdi_shd, NUM_XPE(unit), xpe_map, thdi_shd_min);
  13236     _TH_ARRAY_MIN(thdo_db_shd, NUM_XPE(unit), xpe_map, thdo_db_shd_min);
  13237     _TH_ARRAY_MIN(thdo_qe_shd, NUM_XPE(unit), xpe_map, thdo_qe_shd_min);
  13238     
  13239     /***********************************
  13240      * THDI
  13241  */
  13242     if (res & 0x1) { /* if (res & THDI)  */
  13243 
  13244         /* THDI SP entries */
  13245         rval = 0;
  13246         reg = THDI_BUFFER_CELL_LIMIT_SPr;
  13247         field = LIMITf;
  13248         granularity = 1;
  13249         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
  13250             if (!(xpe_map & (1 << xpe))) {
  13251                 continue;
  13252             }
  13253         
  13254             for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
  13255                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 
  13256                     reg, xpe, -1, idx, &rval));
  13257                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13258                 if ((cur_limit != 0) &&
  13259                     TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdi_shd[xpe]/granularity,
  13260                                             post_update)) {
  13261                     soc_reg_field_set(unit, reg, &rval, field, (thdi_shd[xpe]/granularity));
  13262                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
  13263                         reg, xpe, -1, idx, rval));
  13264                 }
  13265             }
  13266         }
  13267 
  13268         /* Input per port settings */
  13269         base_mem = THDI_PORT_PG_CONFIGm;
  13270         PBMP_ALL_ITER(unit, port) {
  13271             pipe = si->port_pipe[port];
  13272             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  13273             field = PG_SHARED_LIMITf;
  13274             granularity = 1;
  13275             /* Input port per Port-PG settings */
  13276             for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
  13277                 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, base_mem, idx);
  13278                 sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem));
  13279                 SOC_IF_ERROR_RETURN
  13280                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  13281                                   midx, &pg_config_mem));
  13282                 if (!soc_mem_field32_get(unit, mem, &pg_config_mem,
  13283                                          PG_SHARED_DYNAMICf)) {
  13284                     cur_limit = soc_mem_field32_get(unit, mem, &pg_config_mem,
  13285                                                     field);
  13286                     if ((cur_limit != 0) &&
  13287                         TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdi_shd_min/granularity,
  13288                                                 post_update)) {
  13289                         soc_mem_field32_set(unit, mem, &pg_config_mem,
  13290                                             field, thdi_shd_min/granularity);
  13291                     }
  13292                 }
  13293 
  13294                 SOC_IF_ERROR_RETURN
  13295                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL,
  13296                                    midx, &pg_config_mem));
  13297             }
  13298         }
  13299     }
  13300 
  13301     /***********************************
  13302      * THDO
  13303  */
  13304     if (res & 0x2) { /* if (res & THDO)  */
  13305         /* Per SP settings */
  13306         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
  13307             if (!(xpe_map & (1 << xpe))) {
  13308                 continue;
  13309             }
  13310 
  13311             for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
  13312                 /* DB entries */
  13313                 rval = 0;
  13314                 reg = MMU_THDM_DB_POOL_SHARED_LIMITr;
  13315                 field = SHARED_LIMITf;
  13316                 granularity = 1;
  13317                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 
  13318                     reg, xpe, -1, idx, &rval));
  13319                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13320                 if ((cur_limit != 0) &&
  13321                     TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd[xpe]/granularity,
  13322                                             post_update)) {
  13323                     soc_reg_field_set(unit, reg, &rval, field, (thdo_db_shd[xpe]/granularity));
  13324                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
  13325                         reg, xpe, -1, idx, rval));
  13326                 }
  13327 
  13328                 rval = 0;
  13329                 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;
  13330                 field = YELLOW_SHARED_LIMITf;
  13331                 granularity = 8;
  13332                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 
  13333                     reg, xpe, -1, idx, &rval));
  13334                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13335                 if ((cur_limit != 0) &&
  13336                     TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd[xpe], granularity),
  13337                                             post_update)) {
  13338                     soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd[xpe], granularity));
  13339                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
  13340                         reg, xpe, -1, idx, rval));
  13341                 }
  13342 
  13343                 rval = 0;
  13344                 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;
  13345                 field = RED_SHARED_LIMITf;
  13346                 granularity = 8;
  13347                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 
  13348                     reg, xpe, -1, idx, &rval));
  13349                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13350                 if ((cur_limit != 0) &&
  13351                     TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd[xpe], granularity),
  13352                                             post_update)) {
  13353                     soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd[xpe], granularity));
  13354                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
  13355                         reg, xpe, -1, idx, rval));
  13356                 }
  13357 
  13358                 rval = 0;
  13359                 reg = MMU_THDM_DB_POOL_RESUME_LIMITr;
  13360                 field = RESUME_LIMITf;
  13361                 granularity = 8;
  13362                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit,
  13363                     reg, xpe, -1, idx, &rval));
  13364                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13365                 if ((cur_limit != 0) &&
  13366                     TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd[xpe], granularity),
  13367                                             post_update)) {
  13368                     soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd[xpe], granularity));
  13369                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit,
  13370                         reg, xpe, -1, idx, rval));
  13371                 }
  13372 
  13373                 rval = 0;
  13374                 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr;
  13375                 field = YELLOW_RESUME_LIMITf;
  13376                 granularity = 8;
  13377                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit,
  13378                     reg, xpe, -1, idx, &rval));
  13379                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13380                 if ((cur_limit != 0) &&
  13381                     TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd[xpe], granularity),
  13382                                             post_update)) {
  13383                     soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd[xpe], granularity));
  13384                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit,
  13385                         reg, xpe, -1, idx, rval));
  13386                 }
  13387 
  13388                 rval = 0;
  13389                 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr;
  13390                 field = RED_RESUME_LIMITf;
  13391                 granularity = 8;
  13392                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit,
  13393                     reg, xpe, -1, idx, &rval));
  13394                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13395                 if ((cur_limit != 0) &&
  13396                     TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd[xpe], granularity),
  13397                                             post_update)) {
  13398                     soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd[xpe], granularity));
  13399                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit,
  13400                         reg, xpe, -1, idx, rval));
  13401                 }
  13402 
  13403                 /* MCQE */
  13404                 rval = 0;
  13405                 reg = MMU_THDM_MCQE_POOL_SHARED_LIMITr;
  13406                 field = SHARED_LIMITf;
  13407                 granularity = 4;
  13408                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 
  13409                     reg, xpe, -1, idx, &rval));
  13410                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13411                 if ((cur_limit != 0) &&
  13412                     TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_qe_shd[xpe]/granularity,
  13413                                             post_update)) {
  13414                     soc_reg_field_set(unit, reg, &rval, field,
  13415                                       (thdo_qe_shd[xpe]/granularity));
  13416                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
  13417                         reg, xpe, -1, idx, rval));
  13418                 }
  13419 
  13420                 rval = 0;
  13421                 reg = MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr;
  13422                 field = YELLOW_SHARED_LIMITf;
  13423                 granularity = 8;
  13424                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 
  13425                     reg, xpe, -1, idx, &rval));
  13426                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13427                 if ((cur_limit != 0) &&
  13428                     TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_qe_shd[xpe]/granularity,
  13429                                             post_update)) {
  13430                     soc_reg_field_set(unit, reg, &rval, field,
  13431                                       (thdo_qe_shd[xpe]/granularity));
  13432                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
  13433                         reg, xpe, -1, idx, rval));
  13434                 }
  13435 
  13436                 rval = 0;
  13437                 reg = MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr;
  13438                 field = RED_SHARED_LIMITf;
  13439                 granularity = 8;
  13440                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 
  13441                     reg, xpe, -1, idx, &rval));
  13442                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13443                 if ((cur_limit != 0) &&
  13444                     TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_qe_shd[xpe]/granularity,
  13445                                             post_update)) {
  13446                     soc_reg_field_set(unit, reg, &rval, field,
  13447                                       (thdo_qe_shd[xpe]/granularity));
  13448                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
  13449                         reg, xpe, -1, idx, rval));
  13450                 }
  13451             }
  13452         }
  13453 
  13454         /* configure Q-groups */
  13455         base_mem = MMU_THDU_CONFIG_QGROUPm;
  13456         for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  13457             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  13458             for (idx = 0; idx < SOC_TH_MMU_CFG_QGROUP_MAX; idx++) {
  13459                 sal_memset(&cfg_qgrp, 0, sizeof(cfg_qgrp));
  13460 
  13461                 SOC_IF_ERROR_RETURN
  13462                         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, idx, &cfg_qgrp));
  13463 
  13464                 field = Q_SHARED_LIMIT_CELLf;
  13465                 granularity = 1;
  13466                 if (!soc_mem_field32_get(unit, mem, &cfg_qgrp, Q_LIMIT_DYNAMIC_CELLf)) {
  13467                     cur_limit = soc_mem_field32_get(unit, mem, &cfg_qgrp, field);
  13468                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd_min/granularity,
  13469                                                 post_update)) {
  13470                         soc_mem_field32_set(unit, mem, &cfg_qgrp,
  13471                                             field, thdo_db_shd_min/granularity);
  13472                     }
  13473                 }
  13474 
  13475                 granularity = 8;
  13476                 if (!soc_mem_field32_get(unit, mem, &cfg_qgrp,
  13477                                          Q_COLOR_LIMIT_DYNAMIC_CELLf)) {
  13478                     field = LIMIT_RED_CELLf;
  13479                     cur_limit = soc_mem_field32_get(unit, mem, &cfg_qgrp, field);
  13480                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd_min/granularity,
  13481                                                 post_update)) {
  13482                         soc_mem_field32_set(unit, mem, &cfg_qgrp,
  13483                                             field, thdo_db_shd_min/granularity);
  13484                     }
  13485 
  13486                     field = LIMIT_YELLOW_CELLf;
  13487                     cur_limit = soc_mem_field32_get(unit, mem, &cfg_qgrp, field);
  13488                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd_min/granularity,
  13489                                                 post_update)) {
  13490                         soc_mem_field32_set(unit, mem, &cfg_qgrp,
  13491                                             field, thdo_db_shd_min/granularity);
  13492                     }
  13493                 }
  13494 
  13495                 SOC_IF_ERROR_RETURN
  13496                         (soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, &cfg_qgrp));
  13497             }
  13498         }
  13499 
  13500         /* Output port per port per queue setting for UC queue */
  13501         PBMP_PORT_ITER(unit, port) {
  13502             base_mem = MMU_THDU_CONFIG_QUEUEm;
  13503             pipe = si->port_pipe[port];
  13504 
  13505             /* per port UC queue */
  13506             numq = si->port_num_uc_cosq[port];
  13507             base = si->port_uc_cosq_base[port];
  13508 
  13509             if (numq == 0) {
  13510                 continue;
  13511             }
  13512             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  13513             for (idx = 0; idx < numq; idx++) {
  13514                 sal_memset(entry0, 0, sizeof(mmu_thdu_config_queue_entry_t));
  13515 
  13516                 SOC_IF_ERROR_RETURN
  13517                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
  13518 
  13519                 field = Q_SHARED_LIMIT_CELLf;
  13520                 granularity = 1;
  13521                 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMIC_CELLf)) {
  13522                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  13523                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd_min/granularity,
  13524                                                 post_update)) {
  13525                         soc_mem_field32_set(unit, mem, entry0,
  13526                                             field, thdo_db_shd_min/granularity);
  13527                     }
  13528                 }
  13529 
  13530                 granularity = 8;
  13531                 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMIC_CELLf)) {
  13532                     field = LIMIT_YELLOW_CELLf;
  13533                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  13534                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd_min, granularity),
  13535                                                 post_update)) {
  13536                         soc_mem_field32_set(unit, mem, entry0,
  13537                                             field, sal_ceil_func(thdo_db_shd_min, granularity));
  13538                     }
  13539                     field = LIMIT_RED_CELLf;
  13540                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  13541                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13542                                 sal_ceil_func(thdo_db_shd_min, granularity), post_update)) {
  13543                         soc_mem_field32_set(unit, mem, entry0,
  13544                                             field, sal_ceil_func(thdo_db_shd_min, granularity));
  13545                     }
  13546                 }
  13547                 SOC_IF_ERROR_RETURN
  13548                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
  13549             }
  13550         }
  13551 
  13552         /* Output port per port per queue setting for MC queue */
  13553         PBMP_PORT_ITER(unit, port) {
  13554             /* DB entries - Queue */
  13555             numq = si->port_num_cosq[port];
  13556             base = si->port_cosq_base[port];
  13557             if (numq == 0) {
  13558                 continue;
  13559             }
  13560 
  13561             base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
  13562             pipe = si->port_pipe[port];
  13563             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  13564 
  13565             for (idx = 0; idx < numq; idx++) {
  13566                 sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_config_entry_t));
  13567 
  13568                 SOC_IF_ERROR_RETURN
  13569                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
  13570 
  13571                 field = Q_SHARED_LIMITf;
  13572                 granularity = 1;
  13573                 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMICf)) {
  13574                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  13575                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13576                                 thdo_db_shd_min/granularity, post_update)) {
  13577                         soc_mem_field32_set(unit, mem, entry0,
  13578                                             field, thdo_db_shd_min/granularity);
  13579                     }
  13580                 }
  13581 
  13582                 granularity = 8;
  13583                 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMICf)) {
  13584                     field = YELLOW_SHARED_LIMITf;
  13585                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  13586                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13587                                 sal_ceil_func(thdo_db_shd_min, granularity), post_update)) {
  13588                         soc_mem_field32_set(unit, mem, entry0,
  13589                                             field, sal_ceil_func(thdo_db_shd_min, granularity));
  13590                     }
  13591                     field = RED_SHARED_LIMITf;
  13592                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  13593                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13594                                 sal_ceil_func(thdo_db_shd_min, granularity), post_update)) {
  13595                         soc_mem_field32_set(unit, mem, entry0,
  13596                                             field, sal_ceil_func(thdo_db_shd_min, granularity));
  13597                     }
  13598                 }
  13599                 SOC_IF_ERROR_RETURN
  13600                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx,
  13601                                    entry0));
  13602             }
  13603 
  13604             /* MCQE - Queue */
  13605             base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
  13606             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  13607             for (idx = 0; idx < numq; idx++) {
  13608                 sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_config_entry_t));
  13609 
  13610                 SOC_IF_ERROR_RETURN
  13611                     (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0));
  13612 
  13613                 field = Q_SHARED_LIMITf;
  13614                 granularity = 4;
  13615                 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMICf)) {
  13616                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  13617                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13618                                 thdo_qe_shd_min/granularity, post_update)) {
  13619                         soc_mem_field32_set(unit, mem, entry0,
  13620                                             field, thdo_qe_shd_min/granularity);
  13621                     }
  13622                 }
  13623 
  13624                 granularity = 8;
  13625                 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMICf)) {
  13626                     field = YELLOW_SHARED_LIMITf;
  13627                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  13628                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13629                                 thdo_qe_shd_min/granularity, post_update)) {
  13630                         soc_mem_field32_set(unit, mem, entry0,
  13631                                             field, thdo_qe_shd_min/granularity);
  13632                     }
  13633                     field = RED_SHARED_LIMITf;
  13634                     cur_limit = soc_mem_field32_get(unit, mem, entry0, field);
  13635                     if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13636                                 thdo_qe_shd_min/granularity, post_update)) {
  13637                         soc_mem_field32_set(unit, mem, entry0,
  13638                                             field, thdo_qe_shd_min/granularity);
  13639                     }
  13640                 }
  13641                 SOC_IF_ERROR_RETURN
  13642                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx,
  13643                                    entry0));
  13644             }
  13645         }
  13646 
  13647         /* RQE */
  13648         for (idx = 0; idx < 11; idx++) {
  13649             rval = 0;
  13650             rval2 = 0;
  13651 
  13652             SOC_IF_ERROR_RETURN
  13653                 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, idx, &rval));
  13654 
  13655             reg = MMU_THDR_DB_CONFIG_PRIQr;
  13656             field = SHARED_LIMITf;
  13657             granularity = 1;
  13658             SOC_IF_ERROR_RETURN
  13659                 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval2));
  13660             if (!soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval,
  13661                                    DYNAMIC_ENABLEf)) {
  13662                 cur_limit = soc_reg_field_get(unit, reg, rval2, field);
  13663                 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13664                             thdo_db_shd_min/granularity, post_update)) {
  13665                     soc_reg_field_set(unit, reg, &rval2, field,
  13666                                       (thdo_db_shd_min/granularity));
  13667                     SOC_IF_ERROR_RETURN
  13668                         (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval2));
  13669                 }
  13670             }
  13671 
  13672             rval2 = 0;
  13673             reg = MMU_THDR_DB_LIMIT_COLOR_PRIQr;
  13674             granularity = 8;
  13675             SOC_IF_ERROR_RETURN
  13676                 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval2));
  13677 
  13678             if (!soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval,
  13679                                    COLOR_LIMIT_DYNAMICf)) {
  13680                 field = SHARED_RED_LIMITf;
  13681                 cur_limit = soc_reg_field_get(unit, reg, rval2, field);
  13682                 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13683                             thdo_db_shd_min/granularity, post_update)) {
  13684                     soc_reg_field_set(unit, reg, &rval2, field, (thdo_db_shd_min/granularity));
  13685                 }
  13686 
  13687                 field = SHARED_YELLOW_LIMITf;
  13688                 cur_limit = soc_reg_field_get(unit, reg, rval2, field);
  13689                 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13690                             thdo_db_shd_min/granularity, post_update)) {
  13691                     soc_reg_field_set(unit, reg, &rval2, field, (thdo_db_shd_min/granularity));
  13692                 }
  13693                 SOC_IF_ERROR_RETURN
  13694                     (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval2));
  13695             }
  13696 
  13697         }
  13698         /* per pool RQE settings */
  13699         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
  13700             if (!(xpe_map & (1 << xpe))) {
  13701                 continue;
  13702             }
  13703 
  13704             for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) {
  13705                 reg = MMU_THDR_DB_CONFIG_SPr;
  13706                 field = SHARED_LIMITf;
  13707                 granularity = 1;
  13708             
  13709                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 
  13710                     reg, xpe, -1, idx, &rval));
  13711                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13712             
  13713                 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13714                             thdo_db_shd[xpe]/granularity, post_update)) {
  13715                     soc_reg_field_set
  13716                         (unit, reg, &rval, field, (thdo_db_shd[xpe]/granularity));
  13717                     SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
  13718                         reg, xpe, -1, idx, rval));
  13719                 }
  13720             
  13721                 reg = MMU_THDR_DB_SP_SHARED_LIMITr;
  13722                 granularity = 8;
  13723             
  13724                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 
  13725                     reg, xpe, -1, idx, &rval));
  13726             
  13727                 field = SHARED_YELLOW_LIMITf;
  13728                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13729             
  13730                 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13731                             thdo_db_shd[xpe]/granularity, post_update)) {
  13732                     soc_reg_field_set
  13733                         (unit, reg, &rval, field, (thdo_db_shd[xpe]/granularity));
  13734                 }
  13735             
  13736                 field = SHARED_RED_LIMITf;
  13737                 cur_limit = soc_reg_field_get(unit, reg, rval, field);
  13738             
  13739                 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit,
  13740                             thdo_db_shd[xpe]/granularity, post_update)) {
  13741                     soc_reg_field_set
  13742                         (unit, reg, &rval, field, (thdo_db_shd[xpe]/granularity));
  13743                 }
  13744                 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 
  13745                     reg, xpe, -1, idx, rval));
  13746             }
  13747         }
  13748     }
  13749     return SOC_E_NONE;
  13750 }
  13751 
  13752 int soc_th_iss_log_to_phy_bank_map_shadow_get(int unit, uint32 *shadow_val)
  13753 {
  13754     if (shadow_val == NULL) {
  13755         return SOC_E_PARAM;
  13756     }
  13757 
  13758     *shadow_val = _soc_th_iss_log_to_phy_bank_map_shadow[unit];
  13759     return SOC_E_NONE;
  13760 }
  13761 
  13762 int soc_th_iss_log_to_phy_bank_map_shadow_set(int unit, uint32 shadow_val)
  13763 {
  13764     _soc_th_iss_log_to_phy_bank_map_shadow[unit] = shadow_val;
  13765     return SOC_E_NONE;
  13766 }
  13767 
  13768 int soc_th_reset_serdes(int unit, soc_port_t port, int reset_delay_us)
  13769 {
  13770     uint32 rval = 0;
  13771     int rv = SOC_E_NONE;
  13772 
  13773     SOC_IF_ERROR_RETURN(READ_CLPORT_XGXS0_CTRL_REGr(unit, port, &rval));
  13774     soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, &rval, RSTB_HWf, 0 );
  13775     SOC_IF_ERROR_RETURN(WRITE_CLPORT_XGXS0_CTRL_REGr(unit, port, rval));
  13776     sal_usleep((reset_delay_us == 0) ? 10 : reset_delay_us );
  13777     soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, &rval, RSTB_HWf, 1 );
  13778     SOC_IF_ERROR_RETURN(WRITE_CLPORT_XGXS0_CTRL_REGr(unit, port, rval));
  13779     sal_usleep((reset_delay_us == 0) ? 10 : reset_delay_us );
  13780     
  13781     return rv;
  13782 }
  13783 
  13784 void
  13785 _soc_th_lpm_view_set(int unit, int index, soc_mem_t view, int pair_lpm)
  13786 {
  13787     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  13788 
  13789     if (!_soc_th_lpm_view_map[unit]) {
  13790         return;
  13791     }
  13792 
  13793     if (pair_lpm) {
  13794         index = (index % tcam_depth) +
  13795                 (index / tcam_depth) * 2 * tcam_depth;
  13796         _soc_th_lpm_view_map[unit][index] = view;
  13797         _soc_th_lpm_view_map[unit][index + tcam_depth] = view;
  13798     } else {
  13799         _soc_th_lpm_view_map[unit][index] = view;
  13800     }
  13801 }
  13802 
  13803 soc_mem_t
  13804 _soc_th_lpm_view_get(int unit, int index, int pair_lpm)
  13805 {
  13806     soc_mem_t view;
  13807     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  13808 
  13809     if (!_soc_th_lpm_view_map[unit]) {
  13810         return INVALIDm;
  13811     }
  13812 
  13813     if (pair_lpm) {
  13814         index = (index % tcam_depth) +
  13815                 (index / tcam_depth) * 2 * tcam_depth;
  13816         view = _soc_th_lpm_view_map[unit][index];
  13817         if (view == INVALIDm) {
  13818             view = _soc_th_lpm_view_map[unit][index + tcam_depth];
  13819         }
  13820     } else {
  13821         view = _soc_th_lpm_view_map[unit][index];
  13822     }
  13823     return view;
  13824 }
  13825 
  13826 #if defined(INCLUDE_FLOWTRACKER)
  13827 STATIC soc_th_ft_em_ser_handler_t th_ft_em_ser_handler[SOC_MAX_NUM_DEVICES] = {NULL};
  13828 
  13829 void
  13830 soc_th_ft_em_ser_handler_register(int unit, soc_th_ft_em_ser_handler_t handler)
  13831 {
  13832     th_ft_em_ser_handler[unit] = handler;
  13833 }
  13834 
  13835 int
  13836 soc_th_ft_em_ser_process(int unit, int pipe, soc_mem_t mem, int index)
  13837 {
  13838     if (th_ft_em_ser_handler[unit]) {
  13839         return th_ft_em_ser_handler[unit](unit, pipe, mem, index);
  13840     } else {
  13841         return SOC_E_UNAVAIL;
  13842     }
  13843 }
  13844 #endif /* INCLUDE_FLOWTRACKER */
  13845 
  13846 #ifndef BCM_SW_STATE_DUMP_DISABLE
  13847 void
  13848 soc_th_flexport_sw_dump(int unit)
  13849 {
  13850     int port, phy_port, mmu_port, pipe, pm, cosq, numq, uc_cosq, uc_numq;
  13851     int max_speed, init_speed, num_lanes;
  13852     char  pfmt[SOC_PBMP_FMT_LEN];
  13853 
  13854     LOG_CLI((BSL_META_U(unit,
  13855                     "  port(log/phy/mmu)  pipe  pm  lanes    "
  13856                     "speed(Max)    uc_Qbase/Numq mc_Qbase/Numq\n")));
  13857     PBMP_ALL_ITER(unit, port) {
  13858         pipe = SOC_INFO(unit).port_pipe[port];
  13859         phy_port = SOC_INFO(unit).port_l2p_mapping[port];
  13860         mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
  13861         num_lanes = SOC_INFO(unit).port_num_lanes[port];
  13862         pm = SOC_INFO(unit).port_serdes[port];
  13863         max_speed = SOC_INFO(unit).port_speed_max[port];
  13864         init_speed = SOC_INFO(unit).port_init_speed[port];
  13865         cosq = SOC_INFO(unit).port_cosq_base[port];
  13866         numq = SOC_INFO(unit).port_num_cosq[port];
  13867         uc_cosq = SOC_INFO(unit).port_uc_cosq_base[port];
  13868         uc_numq = SOC_INFO(unit).port_num_uc_cosq[port];
  13869 
  13870         LOG_CLI((BSL_META_U(unit,
  13871                         "  %4s(%3d/%3d/%3d)  %4d  %2d  %5d %7d(%7d) "
  13872                         "%6d/%-6d  %6d/%-6d\n"),
  13873                     SOC_INFO(unit).port_name[port], port, phy_port, mmu_port,
  13874                     pipe, pm, num_lanes, init_speed, max_speed,
  13875                     uc_cosq, uc_numq, cosq, numq));
  13876     }
  13877 
  13878     LOG_CLI((BSL_META_U(unit,
  13879                         "\n    Oversub Bitmap: %s"),
  13880                 SOC_PBMP_FMT(SOC_INFO(unit).oversub_pbm, pfmt)));
  13881     LOG_CLI((BSL_META_U(unit,
  13882                         "\n    Disabled Bitmap: %s \n"),
  13883                 SOC_PBMP_FMT(SOC_INFO(unit).all.disabled_bitmap, pfmt)));
  13884 }
  13885 
  13886 void
  13887 soc_th_flexport_sw_pipe_speed_group_dump(int unit, int pipe, int speed_id)
  13888 {
  13889     int rv;
  13890     soc_reg_t reg;
  13891     int port_id, pm_id, inst;
  13892     uint32 rval, fval;
  13893     int speed, group, slot;
  13894 
  13895     static char *speed_id_name[] = {
  13896         "NONE", "10G", "20G", "25G", "40G", "50G", "100G"
  13897     };
  13898 
  13899     speed = speed_id;
  13900 
  13901     if (pipe < 0 || pipe > 3) {
  13902         LOG_CLI((BSL_META_U(unit,
  13903                         "\n    Error: pipe %d not valid for chip %s.\n"),
  13904                     pipe, SOC_UNIT_NAME(unit)));
  13905         return;
  13906     }
  13907     if (speed < 0 || speed > SOC_TH_SPEED_CLASS_100G) {
  13908         LOG_CLI((BSL_META_U(unit,
  13909                         "\n    Error: speed class %d not valid for chip %s.\n"),
  13910                     speed, SOC_UNIT_NAME(unit)));
  13911         return;
  13912     }
  13913 
  13914     LOG_CLI((BSL_META_U(unit,
  13915                     "\n    pipe %d OverSub Scheduler IDB & MMU Table\n"),
  13916                 pipe));
  13917     for (group = 0; group < _OVS_GROUP_COUNT; group++) {
  13918         reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe];
  13919         rv = soc_reg32_get(unit, reg, REG_PORT_ANY, group, &rval);
  13920         if (rv < 0) {
  13921             LOG_CLI((BSL_META_U(unit, " FAILED: Register read.\n")));
  13922         }
  13923         fval = soc_reg_field_get(unit, reg, rval, SPEEDf);
  13924         if (fval == speed) {
  13925             LOG_CLI((BSL_META_U(unit,
  13926                             "\n    SPEED %s in IDB SPEED GROUP\n"),
  13927                         speed_id_name[fval]));
  13928             reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe];
  13929             for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
  13930                 rv = soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval);
  13931                 if (rv <0) {
  13932                     continue;
  13933                 }
  13934                 port_id = soc_reg_field_get(unit, reg, rval, PORT_NUMf);
  13935                 if (port_id != 0x3f) {
  13936                     pm_id = soc_reg_field_get(unit, reg, rval, PHY_PORT_IDf);
  13937                     LOG_CLI((BSL_META_U(unit,
  13938                                     "{%d, %d} "),
  13939                                 pm_id, port_id));
  13940                 }
  13941             }
  13942             LOG_CLI((BSL_META_U(unit, "\n")));
  13943         }
  13944     }
  13945 
  13946     for (group = 0; group < _OVS_GROUP_COUNT; group++) {
  13947         reg = OVR_SUB_GRP_CFGr;
  13948         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
  13949         rv = soc_reg32_get(unit, reg, inst, group, &rval);
  13950         if (rv <0) {
  13951             continue;
  13952         }
  13953         fval = soc_reg_field_get(unit, reg, rval, SPEEDf);
  13954         if (fval == speed) {
  13955             LOG_CLI((BSL_META_U(unit,
  13956                             "\n    SPEED %s in MMU SPEED GROUP\n"),
  13957                         speed_id_name[fval]));
  13958             reg = mmu_grp_tbl_regs[group];
  13959             for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) {
  13960                 rv = soc_reg32_get(unit, reg, inst, slot, &rval);
  13961                 if (rv < 0) {
  13962                     continue;
  13963                 }
  13964                 port_id = soc_reg_field_get(unit, reg, rval, PORT_NUMf);
  13965                 if (port_id != 0x3f) {
  13966                     pm_id = soc_reg_field_get(unit, reg, rval, PHY_PORT_IDf);
  13967                     LOG_CLI((BSL_META_U(unit,
  13968                                     "{%d, %d} "),
  13969                                 pm_id, port_id));
  13970                 }
  13971             }
  13972             LOG_CLI((BSL_META_U(unit, "\n")));
  13973         }
  13974     }
  13975 
  13976     LOG_CLI((BSL_META_U(unit, "\n")));
  13977 }
  13978 
  13979 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  13980 
  13981 /*
  13982  * Tomahawk chip driver functions.
  13983  * Pls keep at the end of this file for easy access.
  13984  */
  13985 soc_functions_t soc_tomahawk_drv_funs = {
  13986     _soc_tomahawk_misc_init,
  13987     _soc_tomahawk_mmu_init,
  13988     _soc_tomahawk_age_timer_get,
  13989     _soc_tomahawk_age_timer_max_get,
  13990     _soc_tomahawk_age_timer_set,
  13991     _soc_tomahawk_tscx_firmware_set,
  13992     _soc_tomahawk_tscx_reg_read,
  13993     _soc_tomahawk_tscx_reg_write,
  13994     _soc_tomahawk_bond_info_init
  13995 };
  13996 #endif /* BCM_TOMAHAWK_SUPPORT */