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

tomahawk3.c (211045B)


      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:        tomahawk3.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 #include <soc/cmicx_miim.h>
     22 #endif
     23 #include <soc/bradley.h>
     24 #include <soc/drv.h>
     25 #include <soc/error.h>
     26 #include <soc/debug.h>
     27 #include <soc/mem.h>
     28 #include <soc/i2c.h>
     29 #include <soc/l2x.h>
     30 #include <soc/soc_ser_log.h>
     31 #include <soc/iproc.h>
     32 #include <soc/mcm/intr_iproc.h>
     33 
     34 #ifdef BCM_TOMAHAWK3_SUPPORT
     35 
     36 #ifdef ALPM_ENABLE
     37 #include <soc/lpm.h>
     38 #include <soc/alpm.h>
     39 #include <soc/esw/alpm_int.h>
     40 #endif /* ALPM_ENABLE */
     41 
     42 #include <soc/esw/portctrl.h>
     43 
     44 #include <soc/mmu_config.h>
     45 #include <soc/tomahawk.h>
     46 #include <soc/tomahawk3.h>
     47 #include <soc/init/tomahawk3_tdm.h>
     48 #include <soc/init/tomahawk3_idb_init.h>
     49 #include <soc/trident2.h>
     50 #include <soc/drv.h>
     51 #include <soc/pfc.h>
     52 #include <soc/pstats.h>
     53 
     54 #define NUM_READS 200
     55 
     56 #define _SOC_TH3_HW_TEMP_MAX   (125)
     57 #define _SOC_TH3_SW_TEMP_MAX   (110)
     58 
     59 #define UPDATE_ALL_PIPES -1
     60 
     61 #define _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ptype) \
     62     si->ptype.num = 0; \
     63     si->ptype.min = si->ptype.max = -1; \
     64     PBMP_ITER(si->ptype.bitmap, it_port) { \
     65         si->ptype.port[si->ptype.num++] = it_port; \
     66         if (si->ptype.min < 0) { \
     67             si->ptype.min = it_port; \
     68         } \
     69         if (it_port > si->ptype.max) { \
     70             si->ptype.max = it_port; \
     71         } \
     72     }
     73 
     74 static int num_shared_alpm_banks[SOC_MAX_NUM_DEVICES] = {0};
     75 static soc_mem_t *_soc_th3_lpm_view_map[SOC_MAX_NUM_DEVICES];
     76 uint32 _soc_mem_entry_reset_value[1] = {1};
     77 
     78 soc_th_latency_table_cfg_t
     79 soc_th3_tbl_cfg[SOC_MAX_NUM_DEVICES] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
     80 
     81 static const soc_reg_t temp_thr_reg[] = {
     82     TOP_PVTMON_0_INTR_THRESHOLDr, TOP_PVTMON_1_INTR_THRESHOLDr,
     83     TOP_PVTMON_2_INTR_THRESHOLDr, TOP_PVTMON_3_INTR_THRESHOLDr,
     84     TOP_PVTMON_4_INTR_THRESHOLDr, TOP_PVTMON_5_INTR_THRESHOLDr,
     85     TOP_PVTMON_6_INTR_THRESHOLDr, TOP_PVTMON_7_INTR_THRESHOLDr,
     86     TOP_PVTMON_8_INTR_THRESHOLDr, TOP_PVTMON_9_INTR_THRESHOLDr,
     87     TOP_PVTMON_10_INTR_THRESHOLDr, TOP_PVTMON_11_INTR_THRESHOLDr,
     88     TOP_PVTMON_12_INTR_THRESHOLDr, TOP_PVTMON_13_INTR_THRESHOLDr,
     89     TOP_PVTMON_14_INTR_THRESHOLDr, TOP_PVTMON_15_INTR_THRESHOLDr
     90 };
     91 static const soc_reg_t pvtmon_ctrl_1_reg_th3[] = {
     92     TOP_PVTMON_0_CTRL_1r, TOP_PVTMON_1_CTRL_1r,
     93     TOP_PVTMON_2_CTRL_1r, TOP_PVTMON_3_CTRL_1r,
     94     TOP_PVTMON_4_CTRL_1r
     95 };
     96 
     97 static const struct {
     98     soc_reg_t pvtmon_reg;
     99     soc_field_t pvtmon_field;
    100 } temp_pvtmon_ctrl_reg[] = {
    101         {TOP_PVTMON_0_CTRL_1r, TOP_PVT_MON_MIN_RST_Lf},
    102         {TOP_PVTMON_1_CTRL_1r, TOP_PVT_MON_MIN_RST_Lf},
    103         {TOP_PVTMON_2_CTRL_1r, TOP_PVT_MON_MIN_RST_Lf},
    104         {TOP_PVTMON_3_CTRL_1r, TOP_PVT_MON_MIN_RST_Lf},
    105         {TOP_PVTMON_4_CTRL_1r, TOP_PVT_MON_MIN_RST_Lf},
    106         {TOP_PVTMON_13_17_CTRL_1r, PVTMON13_TOP_PVT_MON_MIN_RST_Lf},
    107         {TOP_PVTMON_13_17_CTRL_1r, PVTMON14_TOP_PVT_MON_MIN_RST_Lf},
    108         {TOP_PVTMON_13_17_CTRL_1r, PVTMON15_TOP_PVT_MON_MIN_RST_Lf},
    109     };
    110 
    111 static const char *temp_thr_prop[] = {
    112     "temp0_threshold", "temp1_threshold", "temp2_threshold",
    113     "temp3_threshold", "temp4_threshold", "temp5_threshold",
    114     "temp6_threshold", "temp7_threshold", "temp8_threshold",
    115     "temp9_threshold", "temp10_threshold", "temp11_threshold",
    116     "temp12_threshold", "temp13_threshold", "temp14_threshold",
    117     "temp15_threshold"
    118 };
    119 
    120 static const soc_reg_t pvtmon_result_reg_th3[] = {
    121     TOP_PVTMON_RESULT_0r, TOP_PVTMON_RESULT_1r,
    122     TOP_PVTMON_RESULT_2r, TOP_PVTMON_RESULT_3r,
    123     TOP_PVTMON_RESULT_4r, TOP_PVTMON_RESULT_5r,
    124     TOP_PVTMON_RESULT_6r, TOP_PVTMON_RESULT_7r,
    125     TOP_PVTMON_RESULT_8r, TOP_PVTMON_RESULT_9r,
    126     TOP_PVTMON_RESULT_10r, TOP_PVTMON_RESULT_11r,
    127     TOP_PVTMON_RESULT_12r, TOP_PVTMON_RESULT_13r,
    128     TOP_PVTMON_RESULT_14r, AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr
    129 };
    130 
    131 int
    132 soc_tomahawk3_mem_config(int unit)
    133 {
    134 #define _SOC_TH3_DEFIP_MAX_TCAMS    8
    135 #define _SOC_TH3_DEFIP_TCAM_DEPTH   256
    136 #define _SOC_TH3_FIXED_L2_TBL_SZ    (8 * 1024)
    137 #define _SOC_TH3_FIXED_L3_TBL_SZ    (16 * 1024)
    138     soc_persist_t *sop;
    139     int l2_entries, l3_entries;
    140     int num_ipv6_128b_entries = 0;
    141     int config_v6_entries = 0;
    142     int defip_config = 0;
    143     int fpem_entries = 0, shared_fpem_banks = 0;
    144     int alpm_enable;
    145     int max_tcams  = _SOC_TH3_DEFIP_MAX_TCAMS;
    146     int tcam_depth = _SOC_TH3_DEFIP_TCAM_DEPTH;
    147     int def_ipv6_128b_entries = 0;
    148 
    149     sop = SOC_PERSIST(unit);
    150 
    151     /* TH3 Emulation has only 16 entries per TCAM slice */
    152     tcam_depth =
    153        soc_property_get(unit, "l3_defip_tcam_depth", _SOC_TH3_DEFIP_TCAM_DEPTH);
    154     def_ipv6_128b_entries = tcam_depth * max_tcams / 4;
    155 
    156     /* Fetch L2 entries */
    157     l2_entries =
    158         soc_property_get(unit, spn_L2_MEM_ENTRIES, _SOC_TH3_FIXED_L2_TBL_SZ);
    159     if (l2_entries > _SOC_TH3_FIXED_L2_TBL_SZ) {
    160         LOG_CLI(("ERROR: Unsupported L2 table size specified in config.bcm\n"));
    161         LOG_CLI(("INFO : L2 table size reduced to 8K \n"));
    162     }
    163     l2_entries  = _SOC_TH3_FIXED_L2_TBL_SZ;  /* 8k dedicated L2 entries */
    164 
    165     /* Fetch L3 entries */
    166     l3_entries =
    167         soc_property_get(unit, spn_L3_MEM_ENTRIES, _SOC_TH3_FIXED_L3_TBL_SZ);
    168     if (l3_entries > _SOC_TH3_FIXED_L3_TBL_SZ) {
    169         LOG_CLI(("ERROR: Unsupported L3 table size specified in config.bcm\n"));
    170         LOG_CLI(("INFO : L3 table size reduced to 16K \n"));
    171     }
    172     l3_entries = _SOC_TH3_FIXED_L3_TBL_SZ;  /* 16k dedicated L3 entries */
    173 
    174     /* Fetch ALPM enable mode */
    175     alpm_enable = soc_property_get(unit, spn_L3_ALPM_ENABLE, 0);
    176 
    177     /* Fetch FPEM entries
    178      * Check if config parameter fpem_mem_entries is defined in the
    179      * file. If not defined then choose default based on ALPM mode
    180      * requested. If ALPM is requested, then no FPEM as user wants to
    181      * use 8 bank (full) mode ALPM. If ALPM is not requested then assign
    182      * max(64K) for FPEM. If fpem_mem_entries is defined then use that
    183      */
    184     if (NULL == soc_property_get_str(unit, spn_FPEM_MEM_ENTRIES)) {
    185         fpem_entries = (alpm_enable) ? 0 : (64 * 1024);
    186     } else {
    187         fpem_entries = soc_property_get(unit, spn_FPEM_MEM_ENTRIES, 0);
    188     }
    189     /* Find out how many UFT banks are taken up by FPEM */
    190     shared_fpem_banks = (fpem_entries + (16 * 1024 - 1)) / (16 * 1024);
    191     fpem_entries = shared_fpem_banks * 16 * 1024;
    192 
    193     /* Max 4 banks from UFT Shared table can be used by FPEM */
    194     if (shared_fpem_banks > 4) {
    195         LOG_CLI(("ERROR: Unsupported FPEM_MEM_ENTRIES in config.bcm\n"));
    196         return SOC_E_PARAM;
    197     }
    198 
    199     /* Adjust L2 table size */
    200     sop->memState[L2Xm].index_max = l2_entries - 1;
    201     sop->memState[L2_ENTRY_ECCm].index_max = l2_entries - 1;
    202     sop->memState[L2_HITDA_ONLYm].index_max = l2_entries / 4 - 1;
    203     sop->memState[L2_HITSA_ONLYm].index_max = l2_entries / 4 - 1;
    204 
    205     /* Adjust L3 table size */
    206     sop->memState[L3_ENTRY_SINGLEm].index_max = l3_entries - 1;
    207     sop->memState[L3_ENTRY_ECCm].index_max = l3_entries - 1;
    208     sop->memState[L3_ENTRY_HIT_ONLYm].index_max = l3_entries / 4 - 1;
    209 
    210     /* Adjust FP exact match table size */
    211     sop->memState[EXACT_MATCH_2m].index_max = fpem_entries - 1;
    212     sop->memState[EXACT_MATCH_4m].index_max = fpem_entries / 2 - 1;
    213 
    214     SOC_CONTROL(unit)->l3_defip_max_tcams = max_tcams;
    215     SOC_CONTROL(unit)->l3_defip_tcam_size = tcam_depth;
    216 
    217     if (soc_feature(unit, soc_feature_alpm)) {
    218         _soc_alpm_mode[unit] = alpm_enable;
    219     }
    220     if (soc_property_get(unit, "l3_defip_sizing", TRUE)) {
    221         if (!(soc_feature(unit, soc_feature_alpm) && alpm_enable)) {
    222             defip_config = soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1);
    223 
    224             num_ipv6_128b_entries =
    225                 soc_property_get(unit, spn_NUM_IPV6_LPM_128B_ENTRIES,
    226                                     (defip_config ? def_ipv6_128b_entries : 0));
    227             num_ipv6_128b_entries = num_ipv6_128b_entries +
    228                                     (num_ipv6_128b_entries % 2);
    229 
    230             config_v6_entries = num_ipv6_128b_entries;
    231             if (soc_property_get(unit, spn_LPM_SCALING_ENABLE, 0)) {
    232                 num_ipv6_128b_entries = 0;
    233                 if (!soc_property_get(unit, spn_LPM_IPV6_128B_RESERVED, 1)) {
    234                     config_v6_entries =
    235                         ((config_v6_entries /
    236                           SOC_CONTROL(unit)->l3_defip_tcam_size) +
    237                          ((config_v6_entries %
    238                            SOC_CONTROL(unit)->l3_defip_tcam_size
    239                           ) ? 1 : 0)
    240                         ) * SOC_CONTROL(unit)->l3_defip_tcam_size;
    241                 }
    242             }
    243             sop->memState[L3_DEFIP_PAIR_LEVEL1m].index_max =
    244                                               num_ipv6_128b_entries - 1;
    245             sop->memState[L3_DEFIP_LEVEL1m].index_max =
    246                                      (SOC_CONTROL(unit)->l3_defip_max_tcams *
    247                                      SOC_CONTROL(unit)->l3_defip_tcam_size) -
    248                                      (num_ipv6_128b_entries * 2) - 1;
    249 
    250             SOC_CONTROL(unit)->l3_defip_index_remap = num_ipv6_128b_entries;
    251         } else {
    252             if (soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1)) {
    253                 /* slightly different processing for v6-128 */
    254                 num_ipv6_128b_entries = soc_property_get(unit,
    255                                             spn_NUM_IPV6_LPM_128B_ENTRIES,
    256                                             def_ipv6_128b_entries);
    257                 num_ipv6_128b_entries = num_ipv6_128b_entries +
    258                                         (num_ipv6_128b_entries % 2);
    259                 if (soc_tomahawk_alpm_mode_get(unit) == 1 ||
    260                     soc_tomahawk_alpm_mode_get(unit) == 3) {
    261                     num_ipv6_128b_entries = (num_ipv6_128b_entries + 3) / 4 * 4;
    262                 }
    263                 config_v6_entries = num_ipv6_128b_entries;
    264                 sop->memState[L3_DEFIP_PAIR_LEVEL1m].index_max =
    265                                                 num_ipv6_128b_entries - 1;
    266                 sop->memState[L3_DEFIP_LEVEL1m].index_max =
    267                                   (SOC_CONTROL(unit)->l3_defip_max_tcams *
    268                                   SOC_CONTROL(unit)->l3_defip_tcam_size) -
    269                                   (num_ipv6_128b_entries * 2) - 1;
    270 
    271                 SOC_CONTROL(unit)->l3_defip_index_remap =
    272                                        (num_ipv6_128b_entries / 2) * 2;
    273             } else {
    274                 sop->memState[L3_DEFIP_PAIR_LEVEL1m].index_max = -1;
    275             }
    276         }
    277         soc_l3_defip_indexes_init(unit, config_v6_entries);
    278     }
    279 
    280     if (fpem_entries > 0) {
    281         num_shared_alpm_banks[unit] = 4;
    282     } else {
    283         num_shared_alpm_banks[unit] = 8;
    284     }
    285 
    286     /* update tbl cfg to latency subsystem for diag purposes */
    287     soc_th3_tbl_cfg[unit].l2_entries = l2_entries;
    288     soc_th3_tbl_cfg[unit].fixed_l2_entries = l2_entries;
    289     soc_th3_tbl_cfg[unit].shared_l2_banks = 0;
    290     soc_th3_tbl_cfg[unit].l3_entries = l3_entries;
    291     soc_th3_tbl_cfg[unit].fixed_l3_entries = l3_entries;
    292     soc_th3_tbl_cfg[unit].shared_l3_banks = 0;
    293     soc_th3_tbl_cfg[unit].fpem_entries = fpem_entries;
    294     soc_th3_tbl_cfg[unit].shared_fpem_banks = shared_fpem_banks;
    295     soc_th3_tbl_cfg[unit].alpm_enable = alpm_enable;
    296     soc_th3_tbl_cfg[unit].max_tcams = max_tcams;
    297     soc_th3_tbl_cfg[unit].tcam_depth = tcam_depth;
    298 
    299     if (_soc_th3_lpm_view_map[unit] != NULL) {
    300         sal_free(_soc_th3_lpm_view_map[unit]);
    301         _soc_th3_lpm_view_map[unit] = NULL;
    302     }
    303 
    304     _soc_th3_lpm_view_map[unit] = sal_alloc((sizeof(soc_mem_t) *
    305                                              SOC_L3_DEFIP_MAX_TCAMS_GET(unit) *
    306                                              SOC_L3_DEFIP_TCAM_DEPTH_GET(unit)),
    307                                             "lpm_view_map");
    308     if (NULL == _soc_th3_lpm_view_map[unit]) {
    309         return SOC_E_MEMORY;
    310     }
    311 
    312     sal_memset(_soc_th3_lpm_view_map[unit], INVALIDm,
    313                sizeof(soc_mem_t) *
    314                SOC_L3_DEFIP_MAX_TCAMS_GET(unit) *
    315                SOC_L3_DEFIP_TCAM_DEPTH_GET(unit));
    316 
    317     return SOC_E_NONE;
    318 }
    319 
    320 int
    321 soc_tomahawk3_mem_cpu_write_control(int unit, soc_mem_t mem, int copyno,
    322                                    int enable, int *orig_enable)
    323 {
    324     soc_reg_t reg;
    325     soc_field_t field;
    326     uint32 rval = 0, fval;
    327     int blk, port, block_info_index;
    328     uint32 orig_fval, enable_fval, disable_fval;
    329 
    330     enable_fval = 1;
    331     disable_fval = 0;
    332 
    333     switch (mem) {
    334     case CLPORT_WC_UCMEM_DATAm:
    335         reg = CLPORT_WC_UCMEM_CTRLr;
    336         field = ACCESS_MODEf;
    337         SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) {
    338             port = SOC_BLOCK_PORT(unit, blk);
    339             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
    340             /* It will use the setting from the last block */
    341             *orig_enable = soc_reg_field_get(unit, reg, rval, field);
    342             soc_reg_field_set(unit, reg, &rval, field, enable ? 1 : 0);
    343             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
    344         }
    345         return SOC_E_NONE;
    346 
    347     case MMU_MTRO_EGRMETERINGBUCKET_PIPE0m:
    348     case MMU_MTRO_EGRMETERINGBUCKET_PIPE1m:
    349     case MMU_MTRO_EGRMETERINGBUCKET_PIPE2m:
    350     case MMU_MTRO_EGRMETERINGBUCKET_PIPE3m:
    351     case MMU_MTRO_EGRMETERINGBUCKET_PIPE4m:
    352     case MMU_MTRO_EGRMETERINGBUCKET_PIPE5m:
    353     case MMU_MTRO_EGRMETERINGBUCKET_PIPE6m:
    354     case MMU_MTRO_EGRMETERINGBUCKET_PIPE7m:
    355     case MMU_MTRO_BUCKET_CPU_L1_PIPE0m:
    356     case MMU_MTRO_BUCKET_CPU_L1_PIPE1m:
    357     case MMU_MTRO_BUCKET_CPU_L1_PIPE2m:
    358     case MMU_MTRO_BUCKET_CPU_L1_PIPE3m:
    359     case MMU_MTRO_BUCKET_CPU_L1_PIPE4m:
    360     case MMU_MTRO_BUCKET_CPU_L1_PIPE5m:
    361     case MMU_MTRO_BUCKET_CPU_L1_PIPE6m:
    362     case MMU_MTRO_BUCKET_CPU_L1_PIPE7m:
    363     case MMU_MTRO_BUCKET_L0_PIPE0m:
    364     case MMU_MTRO_BUCKET_L0_PIPE1m:
    365     case MMU_MTRO_BUCKET_L0_PIPE2m:
    366     case MMU_MTRO_BUCKET_L0_PIPE3m:
    367     case MMU_MTRO_BUCKET_L0_PIPE4m:
    368     case MMU_MTRO_BUCKET_L0_PIPE5m:
    369     case MMU_MTRO_BUCKET_L0_PIPE6m:
    370     case MMU_MTRO_BUCKET_L0_PIPE7m:
    371         reg = MMU_MTRO_CONFIGr;
    372         field = REFRESH_DISABLEf;
    373         enable_fval = 1;
    374         disable_fval = 0;
    375         SOC_IF_ERROR_RETURN
    376             (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    377         orig_fval = soc_reg_field_get(unit, reg, rval, field);
    378         fval = enable ? enable_fval : disable_fval;
    379         *orig_enable = orig_fval == enable_fval;
    380         if (fval != orig_fval) {
    381             soc_reg_field_set(unit, reg, &rval, field, fval);
    382             SOC_IF_ERROR_RETURN
    383                 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    384         }
    385         return SOC_E_NONE;
    386 
    387     case MMU_WRED_AVG_QSIZE_ITM0m:
    388     case MMU_WRED_AVG_QSIZE_ITM1m:
    389     case MMU_WRED_AVG_PORTSP_SIZE_ITM0m:
    390     case MMU_WRED_AVG_PORTSP_SIZE_ITM1m:
    391     case MMU_WRED_PORT_SP_DROP_THD_0_ITM0m:
    392     case MMU_WRED_PORT_SP_DROP_THD_0_ITM1m:
    393     case MMU_WRED_PORT_SP_DROP_THD_1_ITM0m:
    394     case MMU_WRED_PORT_SP_DROP_THD_1_ITM1m:
    395     case MMU_WRED_PORT_SP_DROP_THD_2_ITM0m:
    396     case MMU_WRED_PORT_SP_DROP_THD_2_ITM1m:
    397     case MMU_WRED_PORT_SP_DROP_THD_3_ITM0m:
    398     case MMU_WRED_PORT_SP_DROP_THD_3_ITM1m:
    399     case MMU_WRED_UC_QUEUE_DROP_THD_ITM0m:
    400     case MMU_WRED_UC_QUEUE_DROP_THD_ITM1m:
    401     case MMU_WRED_UC_QUEUE_DROP_THD_MARK_0_ITM0m:
    402     case MMU_WRED_UC_QUEUE_DROP_THD_MARK_0_ITM1m:
    403     case MMU_WRED_UC_QUEUE_DROP_THD_MARK_1_ITM0m:
    404     case MMU_WRED_UC_QUEUE_DROP_THD_MARK_1_ITM1m:
    405         reg = MMU_WRED_REFRESH_CONTROLr;
    406         field = REFRESH_DISABLEf;
    407         enable_fval = 1;
    408         disable_fval = 0;
    409         SOC_IF_ERROR_RETURN
    410             (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    411         orig_fval = soc_reg_field_get(unit, reg, rval, field);
    412         fval = enable ? enable_fval : disable_fval;
    413         *orig_enable = orig_fval == enable_fval;
    414         if (fval != orig_fval) {
    415             soc_reg_field_set(unit, reg, &rval, field, fval);
    416             SOC_IF_ERROR_RETURN
    417                 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    418         }
    419         return SOC_E_NONE;
    420 
    421     case MMU_QSCH_L2_WEIGHT_MEM_PIPE0m:
    422     case MMU_QSCH_L2_WEIGHT_MEM_PIPE1m:
    423     case MMU_QSCH_L2_WEIGHT_MEM_PIPE2m:
    424     case MMU_QSCH_L2_WEIGHT_MEM_PIPE3m:
    425     case MMU_QSCH_L2_WEIGHT_MEM_PIPE4m:
    426     case MMU_QSCH_L2_WEIGHT_MEM_PIPE5m:
    427     case MMU_QSCH_L2_WEIGHT_MEM_PIPE6m:
    428     case MMU_QSCH_L2_WEIGHT_MEM_PIPE7m:
    429         reg = MMU_QSCH_VOQ_FAIRNESS_CONFIGr;
    430         field = DYNAMIC_WEIGHT_ENABLEf;
    431         enable_fval = 0;
    432         disable_fval = 1;
    433         SOC_IF_ERROR_RETURN
    434             (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    435         orig_fval = soc_reg_field_get(unit, reg, rval, field);
    436         fval = enable ? enable_fval : disable_fval;
    437         *orig_enable = orig_fval == enable_fval;
    438         if (fval != orig_fval) {
    439             soc_reg_field_set(unit, reg, &rval, field, fval);
    440             SOC_IF_ERROR_RETURN
    441                 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    442         }
    443         return SOC_E_NONE;
    444 
    445     case MMU_EBMB_CCBE_SLICE_CPU_PIPE0m:
    446     case MMU_EBMB_CCBE_SLICE_CPU_PIPE1m:
    447     case MMU_EBMB_CCBE_SLICE_CPU_PIPE2m:
    448     case MMU_EBMB_CCBE_SLICE_CPU_PIPE3m:
    449     case MMU_EBMB_CCBE_SLICE_CPU_PIPE4m:
    450     case MMU_EBMB_CCBE_SLICE_CPU_PIPE5m:
    451     case MMU_EBMB_CCBE_SLICE_CPU_PIPE6m:
    452     case MMU_EBMB_CCBE_SLICE_CPU_PIPE7m:
    453     case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE0m:
    454     case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE1m:
    455     case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE2m:
    456     case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE3m:
    457     case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE4m:
    458     case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE5m:
    459     case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE6m:
    460     case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE7m:
    461     case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE0m:
    462     case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE1m:
    463     case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE2m:
    464     case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE3m:
    465     case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE4m:
    466     case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE5m:
    467     case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE6m:
    468     case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE7m:
    469     case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE0m:
    470     case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE1m:
    471     case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE2m:
    472     case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE3m:
    473     case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE4m:
    474     case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE5m:
    475     case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE6m:
    476     case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE7m:
    477     case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE0m:
    478     case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE1m:
    479     case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE2m:
    480     case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE3m:
    481     case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE4m:
    482     case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE5m:
    483     case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE6m:
    484     case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE7m:
    485     case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE0m:
    486     case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE1m:
    487     case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE2m:
    488     case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE3m:
    489     case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE4m:
    490     case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE5m:
    491     case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE6m:
    492     case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE7m:
    493     case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE0m:
    494     case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE1m:
    495     case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE2m:
    496     case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE3m:
    497     case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE4m:
    498     case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE5m:
    499     case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE6m:
    500     case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE7m:
    501     case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE0m:
    502     case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE1m:
    503     case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE2m:
    504     case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE3m:
    505     case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE4m:
    506     case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE5m:
    507     case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE6m:
    508     case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE7m:
    509     case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE0m:
    510     case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE1m:
    511     case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE2m:
    512     case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE3m:
    513     case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE4m:
    514     case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE5m:
    515     case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE6m:
    516     case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE7m:
    517         reg = MMU_EBPTS_CBMG_VALUEr;
    518         field = MMU_NULL_SLOT_COUNTER_VALUEf;
    519         enable_fval = 0;
    520         disable_fval = 1;
    521         SOC_IF_ERROR_RETURN
    522             (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    523         orig_fval = soc_reg_field_get(unit, reg, rval, field);
    524         fval = enable ? enable_fval : disable_fval;
    525         *orig_enable = orig_fval == enable_fval;
    526         if (fval != orig_fval) {
    527             soc_reg_field_set(unit, reg, &rval, field, fval);
    528             SOC_IF_ERROR_RETURN
    529                 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    530         }
    531         return SOC_E_NONE;
    532 
    533     default:
    534         block_info_index = SOC_MEM_BLOCK_ANY(unit, mem);
    535         if ((SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_XPE) ||
    536             (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_SC)){
    537             reg = MMU_GCFG_MISCCONFIGr;
    538             field = REFRESH_ENf;
    539             enable_fval = 0;
    540             disable_fval = 1;
    541             SOC_IF_ERROR_RETURN
    542                 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    543             orig_fval = soc_reg_field_get(unit, reg, rval, field);
    544             fval = enable ? enable_fval : disable_fval;
    545             *orig_enable = orig_fval == enable_fval;
    546             if (fval != orig_fval) {
    547                 soc_reg_field_set(unit, reg, &rval, field, fval);
    548                 SOC_IF_ERROR_RETURN
    549                     (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    550             }
    551         }
    552         return _soc_trident2_mem_cpu_write_control(unit, mem, copyno,
    553                                                    enable, orig_enable);
    554     }
    555     return SOC_E_NONE;
    556 }
    557 
    558 int
    559 soc_tomahawk3_reg_cpu_write_control(int unit, int enable)
    560 {
    561     uint32 intfo_dis = 0;
    562 
    563     if (enable) {
    564         /* Disable HW updates */
    565         soc_reg_field_set(unit, MMU_INTFO_HW_UPDATE_DISr, &intfo_dis,
    566                           RQE_SPf, 1);
    567         soc_reg_field_set(unit, MMU_INTFO_HW_UPDATE_DISr, &intfo_dis,
    568                           EG_SPf, 1);
    569         soc_reg_field_set(unit, MMU_INTFO_HW_UPDATE_DISr, &intfo_dis,
    570                           ING_SPf, 1);
    571         soc_reg_field_set(unit, MMU_INTFO_HW_UPDATE_DISr, &intfo_dis,
    572                           CONGST_STf, 1);
    573     }
    574     SOC_IF_ERROR_RETURN(WRITE_MMU_INTFO_HW_UPDATE_DISr(unit, intfo_dis));
    575 
    576     return SOC_E_NONE;
    577 }
    578 
    579 uint32 _soc_th3_mmu_port(int unit, int port)
    580 {
    581     soc_info_t *si = &SOC_INFO(unit);
    582     return si->port_p2m_mapping[si->port_l2p_mapping[port]];
    583 }
    584 
    585 STATIC int
    586 soc_tomahawk3_max_frequency_get(int unit,  uint16 dev_id, uint8 rev_id,
    587                                int skew_id, int *frequency)
    588 {
    589     switch (dev_id) {
    590     case BCM56984_DEVICE_ID:
    591         *frequency = 925;
    592         break;
    593     default:
    594         *frequency = 1325;
    595         break;
    596     }
    597 
    598     return SOC_E_NONE;
    599 }
    600 
    601 void
    602 soc_tomahawk3_tsc_map_get(int unit, uint32 *tsc_map)
    603 {
    604     *tsc_map = 0xffffffff;
    605 }
    606 
    607 void
    608 soc_tomahawk3_pipe_map_get(int unit, uint32 *pipe_map)
    609 {
    610     soc_info_t *si;
    611     int port;
    612 
    613     si = &SOC_INFO(unit);
    614 
    615     *pipe_map = 0;
    616     PBMP_LB_ITER(unit, port) {
    617         *pipe_map |= 1 << si->port_pipe[port];
    618     }
    619 }
    620 
    621 int soc_tomahawk3_itm_valid(int unit, int itm) {
    622     soc_info_t *si;
    623     uint32 itm_map;
    624 
    625     si = &SOC_INFO(unit);
    626     itm_map = si->itm_map;
    627 
    628     if (itm < 0 || itm >= NUM_ITM(unit)) {
    629         return 0;
    630     }
    631     if (itm_map & (1U << itm)) {
    632         return 1;
    633     }
    634     return 0;
    635 }
    636 
    637 /* Function:
    638  *      _soc_tomahawk3_port_flex_init
    639  * Purpose:
    640  *      Set flexport configuration parameters from the config file.
    641  * Parameters:
    642  *      unit            - (IN) Unit number.
    643  *      is_any_cap      - (IN) All PM can flex
    644  * Returns:
    645  *      SOC_E_XXX
    646  */
    647 STATIC int
    648 _soc_tomahawk3_port_flex_init(int unit, int is_any_cap)
    649 {
    650     soc_info_t *si;
    651     int pm, blk_idx, blk_type;
    652     int flex_en, static_ports, max_ports;
    653 
    654     si = &SOC_INFO(unit);
    655     SHR_BITCLR_RANGE(si->flexible_pm_bitmap, 0, SOC_MAX_NUM_BLKS);
    656 
    657     /* portmap_x=y:speed:i */
    658     /* portmap_x=y:speed:cap */
    659     if (SOC_PBMP_NOT_NULL(SOC_PORT_DISABLED_BITMAP(unit, all)) || is_any_cap) {
    660         SHR_BITSET_RANGE(si->flexible_pm_bitmap, 1, _TH3_PBLKS_PER_DEV);
    661     } else {
    662         /* port_flex_enable */
    663         for (blk_idx = 0; blk_idx < SOC_MAX_NUM_BLKS; blk_idx++) {
    664             blk_type = SOC_BLOCK_TYPE(unit, blk_idx);
    665             pm = SOC_BLOCK_NUMBER(unit, blk_idx);
    666             if (blk_type == SOC_BLK_CDPORT) {
    667                 /* port_flex_enable_corex=<0...1> */
    668                 flex_en = soc_property_suffix_num_get_only_suffix(unit,
    669                     pm, spn_PORT_FLEX_ENABLE, "core", -1);
    670                 /* port_flex_enable{x}=<0...1> */
    671                 /* port_flex_enable=<0...1> */
    672                 if (flex_en == -1) {
    673                     flex_en = soc_property_phys_port_get(unit,
    674                         (pm * _TH3_PORTS_PER_PBLK + 1),
    675                         spn_PORT_FLEX_ENABLE, 0);
    676                 }
    677                 if (flex_en) {
    678                     SHR_BITSET(si->flexible_pm_bitmap, blk_idx);
    679                 }
    680             }
    681         }
    682     }
    683 
    684     /* TH3's CDPORT blocks start at 65 */
    685     si->flex_eligible =
    686         (!SHR_BITNULL_RANGE(si->flexible_pm_bitmap, 65, _TH3_PBLKS_PER_DEV));
    687 
    688     /* port_flex_max_ports */
    689     memset(&(si->pm_max_ports), 0xff, sizeof(si->pm_max_ports));
    690     for (blk_idx = 0; blk_idx < SOC_MAX_NUM_BLKS; blk_idx++) {
    691         blk_type = SOC_BLOCK_TYPE(unit, blk_idx);
    692         pm = SOC_BLOCK_NUMBER(unit, blk_idx);
    693         if (blk_type == SOC_BLK_CDPORT) {
    694             static_ports = _soc_th3_ports_per_pm_get(unit, pm);
    695             if (SHR_BITGET(si->flexible_pm_bitmap, blk_idx)) {
    696                 /* port_flex_max_ports_corex=y */
    697                 max_ports = soc_property_suffix_num_get_only_suffix(unit,
    698                     pm, spn_PORT_FLEX_MAX_PORTS, "core", -1);
    699                 /* port_flex_max_ports{x}=y */
    700                 /* port_flex_max_ports=y */
    701                 if (max_ports == -1) {
    702                     max_ports = soc_property_phys_port_get(unit,
    703                         (pm * _TH3_PORTS_PER_PBLK + 1),
    704                         spn_PORT_FLEX_MAX_PORTS, 8);
    705                 }
    706                 /* validation check */
    707                 if ((max_ports < 0) || (max_ports > 8) || (max_ports < static_ports)) {
    708                     LOG_CLI((BSL_META_U(unit,
    709                         "Core %d: Bad port_flex_max_ports %d; static ports %d"),
    710                         pm, max_ports, static_ports));
    711                     return SOC_E_CONFIG;
    712                 }
    713                 si->pm_max_ports[blk_idx] = max_ports;
    714             } else {
    715                 si->pm_max_ports[blk_idx] = static_ports;
    716             }
    717 
    718         }
    719     }
    720 
    721     return SOC_E_NONE;
    722 }
    723 /*
    724  * Function:
    725  *      _soc_tomahwk3_port_ratio_resolve
    726  * Purpose:
    727  *      Derive the modes each of the 4-lane macs (2 macs in TH3) is
    728  *      operating in.  In previous devices, there was only 1 4-lane
    729  *      mac, so *mode only carried that information.  However, there
    730  *      are 2 4-lane macs in each TH3 PM, so the mode needs to be
    731  *      derived for each of them.  There's an additional bit that
    732  *      gets set when the PM is in 400G mode so the port will combine
    733  *      the two macs into one port.
    734  *
    735  *      In single port mode, each mac is only supporting 1 port:
    736  *                                              200G (4 x 50G in PAM-4)
    737  *                                              100G (4 x 25G in 25G-NRZ)
    738  *                                              40G  (4 x 10G in 10G-NRZ)
    739  *
    740  *      In Dual port mode, each mac supports 2 ports
    741  *
    742  *      In Tri port mode, each mac supports 3 ports, but the mac needs
    743  *      to know which port is taking up 2 lanes, hence
    744  *      SOC_TH3_PORT_RATIO_TRI_023_2_1_1 and SOC_TH3_PORT_RATIO_TRI_012_1_1_2
    745  *      where 023 indicates lane 0 is used for one port and lanes 2 and 3 are
    746  *      used for the others.
    747  *
    748  *      In Quad port mode, each mac supports 4 ports.
    749  *
    750  *      Examples are below.
    751  *
    752  * Parameters:
    753  *      unit - (IN) Unit number
    754  *      num_lanes - (IN) an array containing the number of lanes occupied
    755  *      speed_max - (IN) an array containing the speeds of the ports
    756  *      mode - (OUT) an encoding of the mac modes where the 4 least
    757  *                  significant bits are mac0, the next 4 bits are mac1
    758  *                  and the most significant bit is whether to combine
    759  *                  both macs into a single 400G port
    760  *
    761  * Returns:
    762  *      Nothing
    763  *
    764  * #1   single: 400  -   x  -   x  -   x  SOC_TH3_PORT_RATIO_SINGLE
    765  *                x  -   x  -   x  -   x
    766  *
    767  * #2   single: 200  -   x  -   x  -   x  SOC_TH3_PORT_RATIO_SINGLE
    768  *              200  -   x  -   x  -   x
    769  * #3   single: 100  -   x  -   x  -   x  SOC_TH3_PORT_RATIO_SINGLE
    770  * #4   single:  40  -   x  -   x  -   x  SOC_TH3_PORT_RATIO_SINGLE
    771  * #5   dual:   100  -   x  -  100 -   x  SOC_TH3_PORT_RATIO_DUAL_1_1
    772  * #6   dual:    50  -   x  -  50  -   x  SOC_TH3_PORT_RATIO_DUAL_1_1
    773  * #7   dual:   100  -   x  -  50  -   x  SOC_TH3_PORT_RATIO_DUAL_2_1
    774  * #8   dual:    50  -   x  -  100 -   x  SOC_TH3_PORT_RATIO_DUAL_1_2
    775  * #9   tri:    100  -   x  - 50/x - 50/x SOC_TH3_PORT_RATIO_TRI_023_2_1_1
    776  * #10  tri:     50  -   x  - 25/x - 25/x SOC_TH3_PORT_RATIO_TRI_023_2_1_1
    777  * #11  tri:    50/x - 50/x -  100 -   x  SOC_TH3_PORT_RATIO_TRI_012_1_1_2
    778  * #12  tri:    25/x - 25/x -  50  -   x  SOC_TH3_PORT_RATIO_TRI_012_1_1_2
    779  * #13  quad:   25/x - 25/x - 25/x - 25/x SOC_TH3_PORT_RATIO_QUAD
    780  * #14  quad:   50/x - 50/x - 50/x - 50/x SOC_TH3_PORT_RATIO_QUAD
    781  * #15  quad:   10/x - 10/x - 10/x - 10/x SOC_TH3_PORT_RATIO_QUAD
    782  */
    783 #define _TH3_MACS_PER_PM 2
    784 #define _TH3_LANES_PER_MAC 4
    785 
    786 STATIC void
    787 _soc_tomahawk3_port_ratio_resolve(int unit, 
    788                                   const int * num_lanes, 
    789                                   const int * speed_max,
    790                                   int * mode)
    791 {
    792     int i;
    793 
    794     *mode = 0;
    795     /* Encode Mac0 in the 4 least significant bits, 0-3, and encode Mac1 in bits 4-7 */
    796     if (num_lanes[0] == 8) {
    797         /* 8 lanes means 400G port, so encode as such */
    798         *mode |= (SOC_TH3_PORT_RATIO_SINGLE | 
    799                  (SOC_TH3_PORT_RATIO_SINGLE << 4));
    800         /* also encode that the 400G field should be set */
    801         *mode |= 1 << 8;
    802     } else {
    803         /* Iterate through both macs in the pm (2) */
    804         for (i = 0; i < _TH3_MACS_PER_PM; i++) {
    805             /* If the port in the mac uses 4 lanes, it's a single port */
    806             if (num_lanes[i * _TH3_LANES_PER_MAC] == 4) {
    807                 *mode |= SOC_TH3_PORT_RATIO_SINGLE << (i * 4);
    808             } else if (num_lanes[i * _TH3_LANES_PER_MAC] == 2 && 
    809                        num_lanes[(i * _TH3_LANES_PER_MAC) + 2] == 2) {
    810                 /* First Port uses 2 lanes and Second Port uses 2 lanes,
    811                  * so Dual mode */
    812                 if (speed_max[i * _TH3_LANES_PER_MAC] == 
    813                         speed_max[(i * _TH3_LANES_PER_MAC) + 2]) {
    814                     *mode |= SOC_TH3_PORT_RATIO_DUAL_1_1 << (i * 4);
    815                 } else if (speed_max[i * _TH3_LANES_PER_MAC] > 
    816                         speed_max[(i * _TH3_LANES_PER_MAC) + 2]) {
    817                     *mode |= SOC_TH3_PORT_RATIO_DUAL_2_1 << (i * 4);
    818                 } else {
    819                     *mode |= SOC_TH3_PORT_RATIO_DUAL_1_2 << (i * 4);
    820                 }
    821             } else if (num_lanes[i * _TH3_LANES_PER_MAC] == 2) {
    822                 /* First Port uses 2 lanes */
    823                 if (num_lanes[(i * _TH3_LANES_PER_MAC) + 2] == -1) {
    824                     /* Second port is not specified, so leave in Dual mode */
    825                     *mode |= SOC_TH3_PORT_RATIO_DUAL_1_1 << (i * 4);
    826                 } else {
    827                     /* Second port is 1 lane (2 lanes would have been the 
    828                      * Dual mode case in the first else if), so tri mode
    829                      * with the first port occupying 2 lanes */
    830                     *mode |= SOC_TH3_PORT_RATIO_TRI_023_2_1_1 << (i * 4); 
    831                 }
    832             } else if (num_lanes[(i * _TH3_LANES_PER_MAC) + 2] == 2) {
    833                 /* Second Port uses 2 lanes */
    834                 if (num_lanes[i * _TH3_LANES_PER_MAC] == -1) {
    835                     /* If the first port is undefined, leave in dual mode */
    836                     *mode |= SOC_TH3_PORT_RATIO_DUAL_1_1 << (i * 4);
    837                 } else {
    838                     /* First port is 1 lane, indicating Tri mode */
    839                     *mode |= SOC_TH3_PORT_RATIO_TRI_012_1_1_2 << (i * 4);
    840                 }
    841             } else {
    842                 /* 4 ports in this mac */
    843                 *mode |= SOC_TH3_PORT_RATIO_QUAD << (i * 4);
    844             }
    845         }
    846     }
    847 }
    848 
    849 /*
    850  * Function:
    851  *      soc_tomahwk3_port_ratio_get
    852  * Purpose:
    853  *      Derive the modes of the cdport port macro passed in.  This function
    854  *      calls _soc_tomahawk3_port_ratio_get after fetching the designated
    855  *      port macro's lane assignment and port speeds.
    856  * Parameters:
    857  *      unit     - (IN) Unit number
    858  *      initTime - (IN) Whether the device is being initialized
    859  *      cdport   - (IN) Which port macro we need the mode of (0 - 31)
    860  *      mode     - (OUT) an encoding of the mac modes where the 4 least
    861  *                  significant bits are mac0, the next 4 bits are mac1
    862  *                  and the most significant bit is whether to combine
    863  *                  both macs into a single 400G port
    864  *
    865  * Returns:
    866  *      Nothing
    867  */
    868 void
    869 soc_tomahawk3_port_ratio_get(int unit, int initTime, int cdport, int *mode)
    870 {
    871     soc_info_t *si;
    872     int port, phy_port_base, lane;
    873     int num_lanes[_TH3_PORTS_PER_PBLK];
    874     int speed_max[_TH3_PORTS_PER_PBLK];
    875 
    876     si = &SOC_INFO(unit);
    877     phy_port_base = 1 + cdport * _TH3_PORTS_PER_PBLK;
    878     for (lane = 0; lane < _TH3_PORTS_PER_PBLK; lane += 2) {
    879         port = si->port_p2l_mapping[phy_port_base + lane];
    880         if (port == -1 || SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
    881             num_lanes[lane] = -1;
    882             speed_max[lane] = -1;
    883         } else {
    884             num_lanes[lane] = si->port_num_lanes[port];
    885             /* At init time port_speed_max_max contains port init speed_max and
    886              * at run time during flex port opeartion, init_speed_max
    887              * contains current port speed_max
    888              */
    889             speed_max[lane] = initTime ? si->port_speed_max[port] :
    890                               si->port_init_speed[port];
    891         }
    892     }
    893     _soc_tomahawk3_port_ratio_resolve(unit, num_lanes, speed_max, mode);
    894 }
    895 
    896 /*
    897  * Function:
    898  *      soc_tomahwk3_port_ratio_get_schedule_state
    899  * Purpose:
    900  *      Derive the modes of the cdport port macro passed in, but use
    901  *      the num_lanes and speed_max from the passed port_map. This function
    902  *      calls _soc_tomahawk3_port_ratio_get after fetching the designated
    903  *      port macro's lane assignment and port speeds.
    904  * Parameters:
    905  *      unit     - (IN) Unit number
    906  *      port_schedule_state - (IN) Pointer containing the num_lanes
    907  *                                 and speed_max we're to use for the PM,
    908  *                                 rather than using SOC_INFO
    909  *      cdport   - (IN) Which port macro we need the mode of (0 - 31)
    910  *      mode     - (OUT) an encoding of the mac modes where the 4 least
    911  *                  significant bits are mac0, the next 4 bits are mac1
    912  *                  and the most significant bit is whether to combine
    913  *                  both macs into a single 400G port
    914  *      prev_or_new - (IN) Function looks in in_port_map or out_port_map
    915  *
    916  * Returns:
    917  *      Nothing
    918  */
    919 void
    920 soc_tomahawk3_port_ratio_get_schedule_state(int unit,
    921                              soc_port_schedule_state_t *port_schedule_state,
    922                              int cdport, int *mode,
    923                              int prev_or_new)
    924 {
    925     int port, phy_port_base, lane;
    926     int num_lanes[_TH3_PORTS_PER_PBLK];
    927     int speed_max[_TH3_PORTS_PER_PBLK];
    928     soc_port_map_type_t *port_map;
    929 
    930     if (prev_or_new == 1) {
    931         port_map = &port_schedule_state->in_port_map;
    932     } else {
    933         port_map = &port_schedule_state->out_port_map;
    934     }
    935 
    936     phy_port_base = 1 + cdport * _TH3_PORTS_PER_PBLK;
    937     for (lane = 0; lane < _TH3_PORTS_PER_PBLK; lane += 2) {
    938         port = port_map->port_p2l_mapping[phy_port_base + lane];
    939         if (port == -1 || (port_map->log_port_speed[port]==0) ){
    940             num_lanes[lane] = -1;
    941             speed_max[lane] = -1;
    942         } else {
    943             num_lanes[lane] = port_map->port_num_lanes[port];
    944             speed_max[lane] = port_map->log_port_speed[port];
    945         }
    946     }
    947     _soc_tomahawk3_port_ratio_resolve(unit, num_lanes, speed_max, mode);
    948 }
    949 
    950 #if 0
    951 STATIC void
    952 _soc_tomahawk3_pipe_bandwidth_get(int unit, int pipe,
    953                                  int *max_pipe_core_bandwidth,
    954                                  int *pipe_linerate_bandwidth,
    955                                  int *pipe_oversub_bandwidth)
    956 {
    957     soc_info_t *si;
    958     int port;
    959     int bandwidth;
    960 
    961     si = &SOC_INFO(unit);
    962 
    963     *max_pipe_core_bandwidth = si->bandwidth / 4;
    964 
    965     *pipe_linerate_bandwidth = 0;
    966     *pipe_oversub_bandwidth = 0;
    967     PBMP_PORT_ITER(unit, port) {
    968         if (si->port_pipe[port] != pipe) {
    969             continue;
    970         }
    971         bandwidth = si->port_speed_max[port] >= 2500 ?
    972             si->port_speed_max[port] : 2500;
    973         if (SOC_PBMP_MEMBER(si->oversub_pbm, port)) {
    974             *pipe_oversub_bandwidth += bandwidth;
    975         } else {
    976             *pipe_linerate_bandwidth += bandwidth;
    977         }
    978     }
    979     /* 10G cpu/management, 5G loopback, 10G purge/refresh */
    980     *pipe_linerate_bandwidth += 25;
    981 }
    982 #endif
    983 
    984 int
    985 _soc_th3_port_speed_cap[SOC_MAX_NUM_DEVICES][_TH3_DEV_PORTS_PER_DEV];
    986 
    987 STATIC int
    988 _soc_th3_post_mmu_init_update(int unit)
    989 {
    990     int port;
    991     soc_info_t *si = &SOC_INFO(unit);
    992 
    993     PBMP_ALL_ITER(unit, port) {
    994         /* Set init speed to max speed by default */
    995         si->port_init_speed[port] = si->port_speed_max[port];
    996         if (_soc_th3_port_speed_cap[unit][port]) {
    997             /* If cap speed is available then adjust max speed for further use */
    998             si->port_speed_max[port] = _soc_th3_port_speed_cap[unit][port];
    999         }
   1000     }
   1001     return SOC_E_NONE;
   1002 }
   1003 
   1004 /*
   1005  * FUNCTION : soc_th3_bypass_unused_pm
   1006  * ARGS:
   1007  *         unit    -    IN, unit number
   1008  * Description :
   1009  * Bypass unused port blocks, by programming TOP_TSC_ENABLEr
   1010  * appropriately.
   1011  */
   1012 soc_error_t
   1013 soc_th3_bypass_unused_pm(int unit)
   1014 {
   1015     int port, phy_port, pm, block, bn;
   1016     uint32 rval = 0, orval, xrval, pipe_map;
   1017     uint16 dev_id;
   1018     uint8 rev_id;
   1019     int is_master_pm;
   1020     soc_info_t *si = &SOC_INFO(unit);
   1021     uint8 used_pm_map[_TH3_PBLKS_PER_DEV + 1]; /* #CDPORT + #XLPORT */
   1022     soc_reg_t reg = TOP_TSC_ENABLEr;
   1023     soc_field_t reg_field[_TH3_PBLKS_PER_DEV] = {
   1024         TSC_0_ENABLEf, TSC_1_ENABLEf, TSC_2_ENABLEf, TSC_3_ENABLEf,
   1025         TSC_4_ENABLEf, TSC_5_ENABLEf, TSC_6_ENABLEf, TSC_7_ENABLEf,
   1026         TSC_8_ENABLEf, TSC_9_ENABLEf, TSC_10_ENABLEf, TSC_11_ENABLEf,
   1027         TSC_12_ENABLEf, TSC_13_ENABLEf, TSC_14_ENABLEf, TSC_15_ENABLEf,
   1028         TSC_16_ENABLEf, TSC_17_ENABLEf, TSC_18_ENABLEf, TSC_19_ENABLEf,
   1029         TSC_20_ENABLEf, TSC_21_ENABLEf, TSC_22_ENABLEf, TSC_23_ENABLEf,
   1030         TSC_24_ENABLEf, TSC_25_ENABLEf, TSC_26_ENABLEf, TSC_27_ENABLEf,
   1031         TSC_28_ENABLEf, TSC_29_ENABLEf, TSC_30_ENABLEf, TSC_31_ENABLEf
   1032     };
   1033 
   1034     sal_memset(used_pm_map, 0, sizeof(used_pm_map));
   1035     for (phy_port = 1; phy_port <= _TH3_PORTS_PER_DEV; phy_port++) {
   1036         port = si->port_p2l_mapping[phy_port];
   1037         if (port > 0) {
   1038             pm = si->port_serdes[port];
   1039             if ((-1 != pm) && (0 == used_pm_map[pm])) {
   1040                 used_pm_map[pm] = 1;
   1041             }
   1042         }
   1043     }
   1044 
   1045     SOC_IF_ERROR_RETURN(
   1046         soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1047     orval = rval;
   1048 
   1049     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   1050 
   1051     soc_cm_get_id(unit, &dev_id, &rev_id);
   1052 
   1053     /* Upper loop bound omits XLPORT block intentionally */
   1054     for (pm = 0; pm < _TH3_PBLKS_PER_DEV; pm++) {
   1055 
   1056         is_master_pm = 0;
   1057 
   1058         /* In TH3 A0, the "inner" port macros in a pipe are the master port
   1059          * macros -- they drive the "outer" port macros and act as
   1060          * the refclk master. Do not shut them off
   1061          */
   1062         if (rev_id == BCM56980_A0_REV_ID) {
   1063             if ((pm == 1 || pm == 2 || pm == 5 || pm == 6 ||
   1064               pm == 9 || pm == 10 || pm == 13 || pm == 14 ||
   1065               pm == 17 || pm == 18 || pm == 21 || pm == 22 ||
   1066               pm == 25 || pm == 26 || pm == 29 || pm == 30)) {
   1067                 is_master_pm = 1;
   1068             }
   1069         } else {
   1070             if ((pm == 3 || pm == 4 || pm == 11 || pm == 12 ||
   1071                  pm == 19 || pm == 20 || pm == 27 || pm == 28)) {
   1072                 is_master_pm = 1;
   1073             }
   1074         }
   1075 
   1076         if (is_master_pm) {
   1077             /* If the pipe is active, skip turning off the master port macros */
   1078             if (pipe_map & (1 << (pm / _TH3_PBLKS_PER_PIPE))) {
   1079                 continue;
   1080             }
   1081         }
   1082 
   1083         /* If PM is not used, bypass it */
   1084         if (0 == used_pm_map[pm]) {
   1085             soc_reg_field_set(unit, reg, &rval, reg_field[pm], 0);
   1086             phy_port = 1 + (pm * _TH3_PORTS_PER_PBLK);
   1087             block = SOC_PORT_BLOCK(unit, phy_port);
   1088             /* Invalidate port block in soc info */
   1089             if (SOC_BLK_CDPORT == SOC_BLOCK_INFO(unit, block).type) {
   1090                 si->block_valid[block] = 0;
   1091             }
   1092         }
   1093     }
   1094     if (rval != orval) {
   1095         /*Calculate different bits number between old and new*/
   1096         xrval = rval ^ orval;
   1097         for (bn = 0; xrval != 0; bn++) {
   1098             xrval &= (xrval - 1);
   1099         }
   1100 
   1101         /*Do two steps configuration change for the case of different bits number beyond 10*/
   1102         if (bn > 10) {
   1103             /*Change half of those different bits to new at first*/
   1104             bn /= 2;
   1105             xrval = rval ^ orval;
   1106             do {
   1107                 xrval &= (xrval-1);
   1108             } while (bn-- > 0);
   1109             xrval ^= rval;
   1110             SOC_IF_ERROR_RETURN(
   1111                 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1112             sal_usleep(100000);
   1113         }
   1114         SOC_IF_ERROR_RETURN(
   1115                 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1116         sal_usleep(100000);
   1117     }
   1118 
   1119     return SOC_E_NONE;
   1120 }
   1121 
   1122 #if 0
   1123 static int
   1124 _soc_tomahawk3_phy_dev_port_check(int unit, int phy_port, int dev_port)
   1125 {
   1126     int num_phy_port = 136;
   1127 
   1128     if( phy_port < 0 || phy_port >= num_phy_port) {
   1129         return FALSE;
   1130     } else if ( phy_port >= 1 && phy_port <= 32) {
   1131         return ( dev_port >= 1 && dev_port <=32 );
   1132     } else if ( phy_port >= 33 && phy_port <= 64) {
   1133         return ( dev_port >= 34 && dev_port <= 66 );
   1134     } else if ( phy_port >= 65 && phy_port <= 96) {
   1135         return ( dev_port >= 68 && dev_port <= 100 );
   1136     } else if ( phy_port >= 97 && phy_port <= 128) {
   1137         return ( dev_port >= 102 && dev_port <= 133 );
   1138     } else if ( phy_port == 129) {
   1139         return ( dev_port >= 34 && dev_port <= 66 );
   1140     } else if ( phy_port == 131) {
   1141         return ( dev_port >= 68 && dev_port <= 100 );
   1142     } else {
   1143         /*skip LBPORT(132,133,134,135) , CPU port(0) and hole (130)*/
   1144         return TRUE;
   1145     }
   1146 
   1147 }
   1148 #endif
   1149 
   1150 /*
   1151  *Function: soc_tomahawk3_dpr_frequency_range_check
   1152  *Purpose: Check if dpr frequency is in valid range based on the core clock
   1153  *         frequency. Packet Processor can have a maximum of 1000 (1G) or
   1154  *         the core clock frequency, whichever is less
   1155  *Params:
   1156  *      unit: Device unit number
   1157  *      dpr_freq: dpr frequency value
   1158  */
   1159 int
   1160 soc_tomahawk3_dpr_frequency_range_check(int unit, int dpr_freq)
   1161 {
   1162     int dpr_freq_max, dpr_freq_min;
   1163     soc_info_t *si = &SOC_INFO(unit);
   1164 
   1165     dpr_freq_max = si->frequency;
   1166 
   1167     /* set maximum to 1000 if si->frequency is greater than 1000 */
   1168     if (dpr_freq_max > 1000) {
   1169         dpr_freq_max = 1000;
   1170     }
   1171 
   1172     dpr_freq_min = si->frequency / 2;
   1173     if ((dpr_freq < dpr_freq_min) || (dpr_freq > dpr_freq_max) ||
   1174             dpr_freq == -1) {
   1175         LOG_CLI((BSL_META_U(unit,
   1176             "*** Input DPR clock frequency %dMHz is not supported!\n"
   1177             "Valid range is in between %dMHz and %dMHz\n"), dpr_freq,
   1178             dpr_freq_max, dpr_freq_min));
   1179         return SOC_E_PARAM;
   1180     }
   1181     return SOC_E_NONE;
   1182 }
   1183 
   1184 STATIC int
   1185 _soc_tomahawk3_port_mapping_check(int unit)
   1186 {
   1187     soc_info_t *si;
   1188     int port, phy_port, lanes, i;
   1189 
   1190     si = &SOC_INFO(unit);
   1191 
   1192     for (phy_port = 1; phy_port < _TH3_PORTS_PER_DEV;) {
   1193         port = si->port_p2l_mapping[phy_port];
   1194         if (port < 0) {
   1195             phy_port ++;
   1196             continue;
   1197         }
   1198         if (port >= _TH3_DEV_PORTS_PER_DEV) {
   1199             LOG_CLI((BSL_META_U(unit, "wrong logical port %d, phy %d\n"),
   1200                      port, phy_port));
   1201             return SOC_E_CONFIG;
   1202         }
   1203         lanes = si->port_num_lanes[port];
   1204         if ((lanes < 0) || (lanes > 8)) {
   1205             LOG_CLI((BSL_META_U(unit, "wrong lane number, port %d, lanes %d\n"),
   1206                      port, lanes));
   1207             return SOC_E_CONFIG;
   1208         }
   1209         for (i = 1; i < lanes; i ++) {
   1210             if (si->port_p2l_mapping[phy_port + i] != -1) {
   1211                 LOG_CLI((BSL_META_U(unit, "port overlay, port %d(%d-%d) and "
   1212                                           "port %d(%d..)\n"),
   1213                          port, phy_port, phy_port + lanes - 1,
   1214                          si->port_p2l_mapping[phy_port + i], phy_port + i));
   1215                 return SOC_E_CONFIG;
   1216             }
   1217         }
   1218         phy_port += lanes;
   1219     }
   1220 
   1221     return SOC_E_NONE;
   1222 }
   1223 /*
   1224  * Function: soc_tomahawk3_find_disabled_pipes
   1225  *
   1226  * Purpose: In the event of half chip or emulation, sometimes TH3 doesn't
   1227  * have all 8 pipes.  This function is meant to mark the ones that do not
   1228  * exist so that calls to soc_tomahawk3_pipe_map_get will be accurate
   1229  * 
   1230  * Parameters:
   1231  *      unit            - Switch unit
   1232  *      disabled_pipes  - Array of pipes indicating enabled or disabled
   1233  *
   1234  * Returns:
   1235  *      SOC_E_XXX
   1236  */
   1237 STATIC int
   1238 soc_tomahawk3_find_disabled_pipes(int unit, int *disabled_pipes)
   1239 {
   1240     uint32 reg_val;
   1241     uint16 dev_id;
   1242     uint8  rev_id;
   1243 
   1244     soc_cm_get_id(unit, &dev_id, &rev_id);
   1245     /* DMU_PCU_OTP_CONFIG_4.otp_config[7] tells us whether only
   1246      * pipes 0, 1, 4, 5 are active */
   1247     SOC_IF_ERROR_RETURN(READ_DMU_PCU_OTP_CONFIG_4r(unit, &reg_val));
   1248     if (reg_val & 0x80) {
   1249         disabled_pipes[2] = 1;
   1250         disabled_pipes[3] = 1;
   1251         disabled_pipes[6] = 1;
   1252         disabled_pipes[7] = 1;
   1253     } else if (SAL_BOOT_QUICKTURN && SOC_INFO(unit).num_pipe == 4) {
   1254         disabled_pipes[2] = 1;
   1255         disabled_pipes[3] = 1;
   1256         disabled_pipes[4] = 1;
   1257         disabled_pipes[5] = 1;
   1258     } else if (dev_id == BCM56983_DEVICE_ID) {
   1259         disabled_pipes[2] = 1;
   1260         disabled_pipes[3] = 1;
   1261         disabled_pipes[4] = 1;
   1262         disabled_pipes[5] = 1;
   1263     }
   1264 
   1265     return SOC_E_NONE;
   1266 }
   1267 /*
   1268  * Tomahawk3 port mapping
   1269  *
   1270  *                   physical   idb/       device   mmu
   1271  *                   port       idb port   port     port
   1272  *     CMIC          0          0/19       0        19
   1273  *     CDPORT0-3     1-32       0/0-17     1-18     0-17
   1274  *     CDPORT4-7     33-64      1/0-17     20-37    39-49
   1275  *     CDPORT8-11    65-96      2/0-17     40-57    64-81
   1276  *     CDPORT12-15   97-128     3/0-17     60-77    96-113
   1277  *     CDPORT16-19   129-160    4/0-17     80-97    128-145
   1278  *     CDPORT20-23   161-192    5/0-17     100-117  160-177
   1279  *     CDPORT24-27   193-224    6/0-17     120-137  192-209
   1280  *     CDPORT28-31   225-256    7/0-17     140-157  224-241
   1281  *     XLPORT0/1     257        1/19       38       51
   1282  *     XLPORT0/5     258        5/19       118      179
   1283  *     LBPORT0       259        0/18       19       18
   1284  *     LBPORT1       260        1/18       39       50
   1285  *     LBPORT2       261        2/18       59       82
   1286  *     LBPORT3       262        3/18       79       114
   1287  *     LBPORT4       263        4/18       99       146
   1288  *     LBPORT5       264        5/18       119      178
   1289  *     LBPORT6       265        6/18       139      210
   1290  *     LBPORT7       266        7/18       159      242
   1291  * Device port number is flexible within the above range
   1292  * Although MMU port number is flexible within the above range, it is
   1293  *     configured as a fixed mapped to physical port number
   1294  */
   1295 int
   1296 soc_tomahawk3_port_config_init(int unit, uint16 dev_id)
   1297 {
   1298 #define BCM_TH3_MAX_LOGICAL_PORT_NUM    (160)
   1299     soc_info_t *si;
   1300     char *config_str, *sub_str, *sub_str_end;
   1301     static const char str_2p5[] = "2.5";
   1302     char str_buf[8];
   1303     int rv, oversub_mode, frequency;
   1304     int port, phy_port, mmu_port, idb_port;
   1305     int pipe, itm, index, bandwidth_cap, is_any_cap = FALSE;
   1306     int port_bandwidth, freq_list_len, blk_idx;
   1307     int disabled_pipe[_TH3_PIPES_PER_DEV];
   1308     int dpr_freq;
   1309     uint16 dev_id_temp;
   1310     uint8 rev_id;
   1311     char option1, option2;
   1312     uint32 pipe_map, itm_map, ipipe_map = 0;
   1313     static const int freq_list[] = { 1325, 1250, 1175, 1100, 1000, 925,
   1314                                      850, 775, 675 };
   1315     static const struct {
   1316         int port;
   1317         int phy_port;
   1318         int pipe;
   1319         int idb_port;
   1320         int mmu_port;
   1321     } fixed_ports[] = {
   1322         { 0,   0,   0, 19, 19 },    /* cpu port */
   1323         { 19,  259, 0, 18, 18 },    /* loopback port 0 */
   1324         { 39,  260, 1, 18, 50 },    /* loopback port 1 */
   1325         { 59,  261, 2, 18, 82 },   /* loopback port 2 */
   1326         { 79,  262, 3, 18, 114 },    /* loopback port 3 */
   1327         { 99,  263, 4, 18, 146 },    /* loopback port 4 */
   1328         { 119, 264, 5, 18, 178 },    /* loopback port 5 */
   1329         { 139, 265, 6, 18, 210 },    /* loopback port 6 */
   1330         { 159, 266, 7, 18, 242 },    /* loopback port 7 */
   1331     };
   1332     portmod_speed_config_t speed_config_temp;
   1333 
   1334 
   1335     si = &SOC_INFO(unit);
   1336 
   1337 
   1338     /* Keep track of the pipes that are disabled */
   1339     sal_memset(disabled_pipe, 0, _TH3_PIPES_PER_DEV * sizeof(int));
   1340     SOC_IF_ERROR_RETURN(soc_tomahawk3_find_disabled_pipes(unit, disabled_pipe));
   1341 
   1342     /* Can't read TOP register at this point */
   1343     soc_tomahawk3_max_frequency_get(unit, dev_id, -1, -1, &si->frequency);
   1344     frequency = soc_property_get(unit, spn_CORE_CLOCK_FREQUENCY, -1);
   1345 
   1346 
   1347     /* Core CLK frequency */
   1348     if (frequency != -1 && frequency != si->frequency) {
   1349         freq_list_len = COUNTOF(freq_list);
   1350         for (index = 0; index < freq_list_len; index++) {
   1351             if (freq_list[index] <= si->frequency &&
   1352                 frequency == freq_list[index]) {
   1353                 break;
   1354             }
   1355         }
   1356 
   1357         if (index < freq_list_len) {
   1358             si->frequency = frequency;
   1359         } else {
   1360             LOG_CLI((BSL_META_U(unit,
   1361                                 "*** Input core clock frequency %dMHz is not "
   1362                                 "supported!\n"), frequency));
   1363         }
   1364     }
   1365 
   1366 
   1367     /*DPR frequency check*/
   1368     /*TH3 supports the DPR:clock frequency ratio between 1:2 and 1:1*/
   1369     dpr_freq = soc_property_get(unit, spn_DPR_CLOCK_FREQUENCY, -1);
   1370 #if defined(PLISIM)
   1371     if (SAL_BOOT_PLISIM) {
   1372         dpr_freq = 0;
   1373     }
   1374 #endif
   1375     if (dpr_freq) {
   1376         /* PCID server is property agnostic  */
   1377         SOC_IF_ERROR_RETURN
   1378             (soc_tomahawk3_dpr_frequency_range_check(unit, dpr_freq));
   1379     }
   1380 
   1381     /* TH3 is only oversubscribed mode */
   1382     oversub_mode = 1;
   1383     si->oversub_mode = oversub_mode;
   1384 
   1385     for (phy_port = 0; phy_port < 267; phy_port++) {
   1386         si->port_p2l_mapping[phy_port] = -1;
   1387         si->port_p2m_mapping[phy_port] = -1;
   1388     }
   1389     for (port = 0; port < BCM_TH3_MAX_LOGICAL_PORT_NUM; port++) {
   1390         si->port_l2p_mapping[port] = -1;
   1391         si->port_l2i_mapping[port] = -1;
   1392         si->port_speed_max[port] = -1;
   1393         si->port_group[port] = -1;
   1394         si->port_serdes[port] = -1;
   1395         si->port_pipe[port] = -1;
   1396         si->port_num_lanes[port] = -1;
   1397         _soc_th3_port_speed_cap[unit][port] = 0;
   1398     }
   1399     for (mmu_port = 0; mmu_port < _TH3_MMU_PORTS_PER_DEV; mmu_port++) {
   1400         si->port_m2p_mapping[mmu_port] = -1;
   1401     }
   1402     SOC_PBMP_CLEAR(si->eq_pbm);
   1403     SOC_PBMP_CLEAR(si->management_pbm);
   1404     for (pipe = 0; pipe < si->num_pipe; pipe++) {
   1405         SOC_PBMP_CLEAR(si->pipe_pbm[pipe]);
   1406     }
   1407     SOC_PBMP_CLEAR(si->oversub_pbm);
   1408     SOC_PBMP_CLEAR(si->all.disabled_bitmap);
   1409 
   1410     /* Populate the fixed mapped ports */
   1411     for (index = 0; index < COUNTOF(fixed_ports); index++) {
   1412         port = fixed_ports[index].port;
   1413         phy_port = fixed_ports[index].phy_port;
   1414         pipe = fixed_ports[index].pipe;;
   1415         si->port_l2p_mapping[port] = phy_port;
   1416         si->port_l2i_mapping[port] = fixed_ports[index].idb_port;
   1417         si->port_p2l_mapping[phy_port] = port;
   1418         si->port_p2m_mapping[phy_port] = fixed_ports[index].mmu_port;
   1419         si->port_pipe[port] = pipe;
   1420     }
   1421 
   1422 
   1423     rv = SOC_E_NONE;
   1424     for (port = 1; port < BCM_TH3_MAX_LOGICAL_PORT_NUM; port++) {
   1425         if (si->port_l2p_mapping[port] != -1) { /* fixed mapped port */
   1426             continue;
   1427         }
   1428 #if 0 
   1429         if (port == 134) { /* Reserved port */
   1430             continue;
   1431         }
   1432 #endif
   1433         config_str = soc_property_port_get_str(unit, port, spn_PORTMAP);
   1434         if (config_str == NULL) {
   1435             continue;
   1436         }
   1437 
   1438         /*
   1439          * portmap_<port>=<physical port number>:<bandwidth in Gb>[:<bandwidth cap in Gb/i(inactive)/1/2/4(num lanes)>][:<i>]
   1440          * eg:    portmap_1=1:100
   1441          *     or portmap_1=1:40
   1442          *     or portmap_1=1:40:i
   1443          *     or portmap_1=1:40:2
   1444          *     or portmap_1=1:40:2:i
   1445          *     or portmap_1=1:10:100
   1446          */
   1447         sub_str = config_str;
   1448 
   1449         /* Parse physical port number */
   1450         phy_port = sal_ctoi(sub_str, &sub_str_end);
   1451         if (sub_str == sub_str_end) {
   1452             LOG_CLI((BSL_META_U(unit,
   1453                                 "Port %d: Missing physical port information "
   1454                                 "\"%s\"\n"),
   1455                      port, config_str));
   1456             rv = SOC_E_FAIL;
   1457             continue;
   1458         }
   1459         if (phy_port < 0 || phy_port >= 267) {
   1460             LOG_CLI((BSL_META_U(unit,
   1461                                 "Port %d: Invalid physical port number %d\n"),
   1462                      port, phy_port));
   1463             rv = SOC_E_FAIL;
   1464             continue;
   1465         }
   1466         /* coverity[check_after_sink : FALSE] */
   1467         if (si->port_p2l_mapping[phy_port] != -1) {
   1468             LOG_CLI((BSL_META_U(unit,
   1469                                 "Port %d: Physical port %d is used by port "
   1470                                 "%d\n"),
   1471                      port, phy_port, si->port_p2l_mapping[phy_port]));
   1472             rv = SOC_E_FAIL;
   1473             continue;
   1474         }
   1475         /* In order to reuse the mapping between logical and physical port
   1476          * number for the mapping relationship between physical and IDB port
   1477          * number, we have to make maping between IDB and logical port as fixed.
   1478          * For the management ports:
   1479          *  phy_port    IDB port  => Logical port
   1480          *  257         32              66
   1481          *  259         32              100
   1482          */
   1483         if ((phy_port == 257 && port != 38) ||
   1484             (phy_port == 258 && port != 118)) {
   1485             LOG_CLI((BSL_META_U(unit,
   1486                                 "Management Port %d: Invalid port number %d\n"),
   1487                      phy_port, port));
   1488             rv = SOC_E_FAIL;
   1489             continue;
   1490         }
   1491 
   1492         pipe = port/_TH3_DEV_PORTS_PER_PIPE;
   1493         if ((port != 38 && port != 118) &&
   1494             ((phy_port < (pipe * 32 + 1)) ||
   1495             (phy_port > (pipe + 1) * 32))) {
   1496             LOG_CLI((BSL_META_U(unit,
   1497                                 "Port %d, Physical port %d: "
   1498                                 "Not in same pipeline range\n"),
   1499                      port, phy_port));
   1500             rv = SOC_E_FAIL;
   1501             continue;
   1502         }
   1503 
   1504 
   1505         /* Skip ':' between physical port number and bandwidth */
   1506         sub_str = sub_str_end;
   1507         if (*sub_str != '\0') {
   1508             if (*sub_str != ':') {
   1509                 LOG_CLI((BSL_META_U(unit,
   1510                                     "Port %d: Bad config string \"%s\"\n"),
   1511                          port, config_str));
   1512                 rv = SOC_E_FAIL;
   1513                 continue;
   1514             }
   1515             sub_str++;
   1516         }
   1517 
   1518         /* Parse bandwidth */
   1519         for (index = 0; index < sizeof(str_2p5) - 1; index++) {
   1520             if (sub_str[index] == '\0') {
   1521                 break;
   1522             }
   1523             str_buf[index] = sub_str[index];
   1524         }
   1525         str_buf[index] = '\0';
   1526         if (!sal_strcmp(str_buf, str_2p5)) {
   1527             port_bandwidth = 2500;
   1528             sub_str_end = &sub_str[sizeof(str_2p5) - 1];
   1529         } else {
   1530             port_bandwidth = sal_ctoi(sub_str, &sub_str_end) * 1000;
   1531             if (sub_str == sub_str_end) {
   1532                 LOG_CLI((BSL_META_U(unit,
   1533                                     "Port %d: Missing bandwidth information "
   1534                                     "\"%s\"\n"),
   1535                          port, config_str));
   1536                 rv = SOC_E_FAIL;
   1537                 continue;
   1538             }
   1539             switch (port_bandwidth) {
   1540             case 1000:
   1541             case 10000:
   1542             case 25000:
   1543             case 40000:
   1544             case 50000:
   1545             case 100000:
   1546             case 200000:
   1547             case 400000:
   1548                 break;
   1549             default:
   1550                 LOG_CLI((BSL_META_U(unit,
   1551                                     "Port %d: Invalid bandwidth %d Gb\n"),
   1552                          port, port_bandwidth / 1000));
   1553                 rv = SOC_E_FAIL;
   1554                 continue;
   1555             }
   1556         }
   1557 
   1558         /* Check if option presents */
   1559         option1 = 0; option2 = 0;
   1560         sub_str = sub_str_end;
   1561         if (*sub_str != '\0') {
   1562             /* Skip ':' between bandwidth and cap or options */
   1563             if (*sub_str != ':') {
   1564                 LOG_CLI((BSL_META_U(unit,
   1565                                     "Port %d: Bad config string \"%s\"\n"),
   1566                          port, config_str));
   1567                 rv = SOC_E_FAIL;
   1568                 continue;
   1569             }
   1570             sub_str++;
   1571 
   1572             if (*sub_str != '\0') {
   1573                 /* Parse bandwidth cap or options */
   1574                 bandwidth_cap = sal_ctoi(sub_str, &sub_str_end) * 1000;
   1575                 switch (bandwidth_cap) {
   1576                 case 10000:
   1577                 case 25000:
   1578                 case 40000:
   1579                 case 50000:
   1580                 case 100000:
   1581                 case 200000:
   1582                 case 400000:
   1583                     sub_str = sub_str_end;
   1584                     _soc_th3_port_speed_cap[unit][port] = bandwidth_cap;
   1585                     /* Flex config detected, port speed cap specified */
   1586                     is_any_cap = TRUE;
   1587                     break;
   1588                 default:
   1589                     if (!(*sub_str == 'i' || *sub_str == '1' ||
   1590                           *sub_str == '2' || *sub_str == '4' ||
   1591                           *sub_str == '8')) {
   1592                         LOG_CLI((BSL_META_U(unit,
   1593                                             "Port %d: Bad config string "
   1594                                             "\"%s\"\n"),
   1595                                  port, config_str));
   1596                         rv = SOC_E_FAIL;
   1597                         continue;
   1598                     } else {
   1599                         option1 = *sub_str;
   1600                         sub_str++;
   1601                     }
   1602                 }
   1603                 /* Check if more options present */
   1604                 if (*sub_str != '\0') {
   1605                     /* Skip ':' between options */
   1606                     if (*sub_str != ':') {
   1607                         LOG_CLI((BSL_META_U(unit,
   1608                                             "Port %d: Bad config string "
   1609                                             "\"%s\"\n"),
   1610                                  port, config_str));
   1611                         rv = SOC_E_FAIL;
   1612                         continue;
   1613                     }
   1614                     sub_str++;
   1615 
   1616                     if (*sub_str != 'i') {
   1617                         LOG_CLI((BSL_META_U(unit,
   1618                                             "Port %d: Bad config string "
   1619                                             "\"%s\"\n"),
   1620                                  port, config_str));
   1621                         rv = SOC_E_FAIL;
   1622                         continue;
   1623                     }
   1624                     option2 = *sub_str;
   1625                     sub_str++;
   1626                 }
   1627             }
   1628         }
   1629 
   1630         /* Check trailing string */
   1631         if (*sub_str != '\0') {
   1632             LOG_CLI((BSL_META_U(unit,
   1633                                 "Port %d: Bad config string \"%s\"\n"),
   1634                      port, config_str));
   1635             rv = SOC_E_FAIL;
   1636             continue;
   1637         }
   1638 
   1639         /* Update soc_info */
   1640         si->port_l2p_mapping[port] = phy_port;
   1641         si->port_p2l_mapping[phy_port] = port;
   1642         si->port_speed_max[port] = port_bandwidth;
   1643         if (option1 == 'i') {
   1644             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port);
   1645         } else {
   1646             switch (option1) {
   1647             case '1': si->port_num_lanes[port] = 1; break;
   1648             case '2': si->port_num_lanes[port] = 2; break;
   1649             case '4': si->port_num_lanes[port] = 4; break;
   1650             case '8': si->port_num_lanes[port] = 8; break;
   1651             default: break;
   1652             }
   1653         }
   1654         if (option2 == 'i') {
   1655             SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port);
   1656         }
   1657     }
   1658 
   1659     /* Setup port_num_lanes */
   1660     for (port = 0; port < BCM_TH3_MAX_LOGICAL_PORT_NUM; port++) {
   1661         if (si->port_speed_max[port] == 400000) {
   1662             si->port_num_lanes[port] = 8;
   1663         } else if (si->port_speed_max[port] == 200000) {
   1664             si->port_num_lanes[port] = 4;
   1665         } else if (si->port_speed_max[port] == 100000 &&
   1666                    si->port_num_lanes[port] == -1) {
   1667             /* if it's 100G and the user didn't specify the number of lanes,
   1668              * choose 2 lanes (2 x 50G) */
   1669             si->port_num_lanes[port] = 2;
   1670         } else if (si->port_speed_max[port] == 50000 &&
   1671                    si->port_num_lanes[port] == -1) {
   1672             /* if it's 50G and the user didn't specify the number of lanes,
   1673              * choose 1 lane (1 x 50G) */
   1674             si->port_num_lanes[port] = 1;
   1675         } else if (si->port_speed_max[port] == 40000 &&
   1676                     si->port_num_lanes[port] == -1) {
   1677                 si->port_num_lanes[port] = 2;
   1678         } else if (si->port_speed_max[port] > 0) {
   1679             if (si->port_num_lanes[port] == -1) {
   1680                 /* But RXAUI and XAUI on mgmt ports use 2 and 4 lanes, which
   1681                  * can be provided via the portmap interface.
   1682                  */
   1683                 si->port_num_lanes[port] = 1;
   1684             }
   1685         }
   1686 
   1687         /* If the port is mapped, find out its fec, link training, lane config
   1688          * from config file */
   1689         if (si->port_speed_max[port] > 0) {
   1690             /* Fetch FEC, Link Training and Phy lane Config from Config File */
   1691             SOC_IF_ERROR_RETURN(soc_esw_portctrl_speed_config_fill(unit, port,
   1692                             si->port_speed_max[port],
   1693                             si->port_num_lanes[port],
   1694                             -1,
   1695                             -1,
   1696                             -1,
   1697                             &speed_config_temp));
   1698             si->port_fec_type[port] = speed_config_temp.fec;
   1699             si->port_link_training[port] = speed_config_temp.link_training;
   1700             si->port_phy_lane_config[port] = speed_config_temp.lane_config;
   1701         }
   1702     }
   1703 
   1704 
   1705     /* check portmap */
   1706     SOC_IF_ERROR_RETURN(_soc_tomahawk3_port_mapping_check(unit));
   1707 
   1708     /* get flex port properties */
   1709     if (SOC_FAILURE(_soc_tomahawk3_port_flex_init(unit, is_any_cap))) {
   1710         rv = SOC_E_FAIL;
   1711     }
   1712 
   1713 #if defined(BCM_WARM_BOOT_SUPPORT)
   1714     if (si->flex_eligible) {
   1715         if (SOC_WARM_BOOT(unit)) {
   1716             SOC_IF_ERROR_RETURN(
   1717                 soc_th3_flexport_scache_recovery(unit));
   1718         } else {
   1719             SOC_IF_ERROR_RETURN(
   1720                 soc_th3_flexport_scache_allocate(unit));
   1721         }
   1722     }
   1723 #endif
   1724 
   1725 
   1726     /* Setup high speed port (HSP) pbm */
   1727     for (port = 0; port < BCM_TH3_MAX_LOGICAL_PORT_NUM; port++) {
   1728         phy_port = si->port_l2p_mapping[port];
   1729         if (phy_port <= 0 || phy_port > 258) {
   1730             continue;
   1731         }
   1732 
   1733         pipe = port/_TH3_DEV_PORTS_PER_PIPE;
   1734         if (phy_port == 257) {
   1735             si->port_l2i_mapping[port] = 19;
   1736             si->port_p2m_mapping[phy_port] = 51;
   1737             si->port_serdes[port] = 32;
   1738             SOC_PBMP_PORT_ADD(si->management_pbm, port);
   1739         } else if (phy_port == 258) {
   1740             si->port_l2i_mapping[port] = 19;
   1741             si->port_p2m_mapping[phy_port] = 179;
   1742             si->port_serdes[port] = 32;
   1743             SOC_PORT_BLOCK(unit, phy_port) = SOC_PORT_BLOCK(unit, 257);
   1744             SOC_PORT_BINDEX(unit, phy_port) = 2;
   1745             SOC_PBMP_PORT_ADD(si->management_pbm, port);
   1746         } else {
   1747             idb_port = (port % 20) - (pipe == 0 ? 1 : 0);
   1748             mmu_port = pipe * 32 + idb_port;
   1749             si->port_l2i_mapping[port] = idb_port;
   1750             si->port_p2m_mapping[phy_port] = mmu_port;
   1751             si->port_serdes[port] = (phy_port - 1) / 8;
   1752         }
   1753 
   1754         si->port_pipe[port] = pipe;
   1755         SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port);
   1756 
   1757         if (si->port_speed_max[port] >= 40000) {
   1758             SOC_PBMP_PORT_ADD(si->eq_pbm, port);
   1759         }
   1760     }
   1761 
   1762     for (index = 1; index < COUNTOF(fixed_ports); index++) {
   1763         pipe = fixed_ports[index].pipe;
   1764         port = fixed_ports[index].port;
   1765         phy_port = fixed_ports[index].phy_port;
   1766         /* If this is a half chip or a SKU with disabled pipes,
   1767          * remove the mappings */
   1768         if (disabled_pipe[pipe] == 1) {
   1769             /* Remove loopback port if the entire pipe does not exist */
   1770             si->port_l2p_mapping[port] = -1;
   1771             si->port_l2i_mapping[port] = -1;
   1772             si->port_p2l_mapping[phy_port] = -1;
   1773             si->port_p2m_mapping[phy_port] = -1;
   1774             si->port_pipe[port] = -1;
   1775         } else {
   1776             SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port);
   1777         }
   1778     }
   1779 
   1780     /* Add CPU Port to PIP_PBM of PIPE 0 */
   1781     SOC_PBMP_PORT_ADD(si->pipe_pbm[0], CMIC_PORT(unit));
   1782 
   1783     /* Since we have the port speeds and lanes from the config file,
   1784      * or WB, calculate the port macro VCOs for later PM init
   1785      */
   1786     SOC_IF_ERROR_RETURN(soc_th3_portctrl_vco_soc_info_update(unit));
   1787 
   1788     /* Setup pipe/xpe mapping
   1789      * XPE0 (SC_R/XPE_A): IP 0/3 EP 0/1
   1790      * XPE1 (SC_S/XPE_A): IP 0/3 EP 2/3
   1791      * XPE2 (SC_R/XPE_B): IP 1/2 EP 0/1
   1792      * XPE3 (SC_S/XPE_B): IP 1/2 EP 2/3
   1793      */
   1794     pipe_map = 0;
   1795     for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) {
   1796         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   1797             continue;
   1798         }
   1799         pipe_map |= 1 << pipe;
   1800     }
   1801     itm_map = 0;
   1802     for (itm = 0; itm < NUM_ITM(unit); itm++) {
   1803         ipipe_map = (itm == 0 ? 0xc3 : 0x3c) & pipe_map;
   1804         if (ipipe_map == 0) {
   1805             continue;
   1806         }
   1807         itm_map |= 1 << itm;
   1808         /* Number of ITMs is 2 in Tomahawk3 */
   1809         /* coverity[overrun-local : FALSE] */
   1810         si->itm_ipipe_map[itm] = ipipe_map;
   1811     }
   1812     for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) {
   1813         /* Number of pipes is 8 in Tomahawk3 */
   1814         /* coverity[overrun-local : FALSE] */
   1815         if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) {
   1816             continue;
   1817         }
   1818         /* coverity[overrun-local : FALSE] */
   1819         si->ipipe_itm_map[pipe] = ((pipe < 2 || pipe > 5 )? 0x1 : 0x2) ;
   1820     }
   1821     si->itm_map = itm_map;
   1822 
   1823     /* Setup cdport refclk master block bitmap.
   1824      * In Tomahawk3, the "inner" port macros in a pipe are the master
   1825      * port macros and will drive the "outer" port macros in a pipe from the
   1826      * system board and they will act as the refclk master to drive the other
   1827      * instances.
   1828      */
   1829     SHR_BITCLR_RANGE(si->pm_ref_master_bitmap, 0, SOC_MAX_NUM_BLKS);
   1830     for (blk_idx = 0; blk_idx < SOC_MAX_NUM_BLKS; blk_idx++) {
   1831         int blknum = SOC_BLOCK_NUMBER(unit, blk_idx);
   1832         int blktype = SOC_BLOCK_TYPE(unit, blk_idx);
   1833         if (blktype == SOC_BLK_CDPORT) {
   1834             soc_cm_get_id(unit, &dev_id_temp, &rev_id);
   1835 
   1836             /* Set Master PM bitmap for flexport purposes depending on whether
   1837              * it's A0 or B0 chip */
   1838             if (rev_id == BCM56980_A0_REV_ID) {
   1839                 if ((blknum == 1 || blknum == 2 || blknum == 5 || blknum == 6 ||
   1840                   blknum == 9 ||blknum == 10 || blknum == 13 || blknum == 14 ||
   1841                   blknum == 17 || blknum == 18 || blknum == 21 || blknum == 22 ||
   1842                   blknum == 25 || blknum == 26 || blknum == 29 || blknum == 30)) {
   1843                     SHR_BITSET(si->pm_ref_master_bitmap, blk_idx);
   1844                 }
   1845             } else {
   1846                 if ((blknum == 3 || blknum == 4 || blknum == 11 || blknum == 12 ||
   1847                   blknum == 19 || blknum == 20 || blknum == 27 || blknum == 28)) {
   1848                     SHR_BITSET(si->pm_ref_master_bitmap, blk_idx);
   1849                 }
   1850             }
   1851         }
   1852     }
   1853 
   1854 #undef BCM_TH3_MAX_LOGICAL_PORT_NUM
   1855     return rv;
   1856 }
   1857 
   1858 STATIC int _soc_tomahawk3_init_ipep_memory(int unit);
   1859 
   1860 static int
   1861 _soc_th3_pp_pll_config(int unit, int freq)
   1862 {
   1863     uint32 rval;
   1864     unsigned pp_idx;
   1865     static const soc_pp_pll_param_t pp_pll[] = {
   1866     /* Fref,       Ndiv,   Pdiv, Mdiv, pp_clk,  VCO */
   1867       {110010,      80,     1,    4,    1000,    4},
   1868       {110010,      70,     1,    4,     875,  3.5},
   1869       {110010,      60,     1,    4,     750,    3},
   1870       {110010,      53,     1,    4,   662.5, 2.65},
   1871       {110010,      50,     1,    4,     625,  2.5},
   1872       {110010,      40,     1,    4,     500,  2.0}
   1873     };
   1874 
   1875 
   1876     for (pp_idx = 0; pp_idx < sizeof(pp_pll)/sizeof(pp_pll[0]); ++pp_idx) {
   1877         if (pp_pll[pp_idx].pp_clk == freq) {
   1878             break;
   1879         }
   1880     }
   1881 
   1882     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   1883     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_PP_PLL_RST_Lf, 0);
   1884     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_PP_PLL_POST_RST_Lf, 0);
   1885     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   1886 
   1887     /* hold all post div channels */
   1888     SOC_IF_ERROR_RETURN(READ_TOP_PP_PLL_CTRL_1r(unit, &rval));
   1889     soc_reg_field_set(unit, TOP_PP_PLL_CTRL_1r, &rval, POST_HOLD_ALLf, 1);
   1890     SOC_IF_ERROR_RETURN(WRITE_TOP_PP_PLL_CTRL_1r(unit, rval));
   1891 
   1892     /* Enable glitchless bypass enable */
   1893     SOC_IF_ERROR_RETURN(READ_TOP_PP_PLL_CTRL_4r(unit, &rval));
   1894     soc_reg_field_set(unit, TOP_PP_PLL_CTRL_4r, &rval, PLL_RESERVEDf, 2);
   1895     SOC_IF_ERROR_RETURN(WRITE_TOP_PP_PLL_CTRL_4r(unit, rval));
   1896 
   1897     /* Set to normal operation instead of bypassing all post-div channels*/
   1898     SOC_IF_ERROR_RETURN(READ_TOP_PP_PLL_CTRL_1r(unit, &rval));
   1899     soc_reg_field_set(unit, TOP_PP_PLL_CTRL_1r, &rval, CH_BYP_ENf, 0);
   1900     SOC_IF_ERROR_RETURN(WRITE_TOP_PP_PLL_CTRL_1r(unit, rval));
   1901 
   1902     /* Set ndiv_int and mdiv for target freq */
   1903     SOC_IF_ERROR_RETURN
   1904         (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_0r,
   1905                                 REG_PORT_ANY, NDIV_INTf,
   1906                                 pp_pll[pp_idx].ndiv_int));
   1907    SOC_IF_ERROR_RETURN
   1908         (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_3r,
   1909                                 REG_PORT_ANY, CH_MDIVf,
   1910                                 pp_pll[pp_idx].mdiv));
   1911 
   1912     /* Deassert PP_PLL_RST_L */
   1913     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   1914     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_PP_PLL_RST_Lf, 1);
   1915     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   1916 
   1917     /* Wait for 10us */
   1918     sal_usleep(10);
   1919 
   1920     /* Deassert PP_PLL_POST_RST_L */
   1921     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   1922     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_PP_PLL_POST_RST_Lf, 1);
   1923     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   1924 
   1925     SOC_IF_ERROR_RETURN(READ_TOP_PP_PLL_CTRL_4r(unit, &rval));
   1926     soc_reg_field_set(unit, TOP_PP_PLL_CTRL_4r, &rval, PLL_RESERVEDf, 0);
   1927     SOC_IF_ERROR_RETURN(WRITE_TOP_PP_PLL_CTRL_4r(unit, rval));
   1928 
   1929     /* Adjusting the clock phases on 2 post div channels. We set the
   1930        channel#1  twice so it is shifted by 2 VCO cycles which is
   1931        180 degrees */
   1932 
   1933     SOC_IF_ERROR_RETURN
   1934         (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_3r,
   1935                                 REG_PORT_ANY, CH_MDELf, 0));
   1936     SOC_IF_ERROR_RETURN
   1937         (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_3r,
   1938                                 REG_PORT_ANY, CH_MDELf, 2));
   1939     SOC_IF_ERROR_RETURN
   1940         (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_3r,
   1941                                 REG_PORT_ANY, CH_MDELf, 0));
   1942     SOC_IF_ERROR_RETURN
   1943         (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_3r,
   1944                                 REG_PORT_ANY, CH_MDELf, 2));
   1945 
   1946     /* Release all post div channels to normal operation */
   1947     SOC_IF_ERROR_RETURN(READ_TOP_PP_PLL_CTRL_1r(unit, &rval));
   1948     soc_reg_field_set(unit, TOP_PP_PLL_CTRL_1r, &rval, POST_HOLD_ALLf, 0);
   1949     SOC_IF_ERROR_RETURN(WRITE_TOP_PP_PLL_CTRL_1r(unit, rval));
   1950 
   1951     return 0;
   1952 }
   1953 
   1954 /*
   1955  * Function:
   1956  *      soc_tomahawk3_core_pll_bypass_prog_pre
   1957  * Purpose:
   1958  *      Performs steps 1-3 of the CORE_PLL Programming sequence, and
   1959  *      is done when TH3 is operating at a different core clock frequency
   1960  * Parameters:
   1961  *      unit     - (IN) Unit number
   1962  * Returns:
   1963  *      SOC_E_XXX
   1964  */
   1965 STATIC int
   1966 _soc_tomahawk3_core_pll_bypass_prog_pre(int unit)
   1967 {
   1968     uint32 rval;
   1969 
   1970     /* 1 */
   1971     SOC_IF_ERROR_RETURN(READ_TOP_CORE_PLL_CTRL_1r(unit, &rval));
   1972     soc_reg_field_set(unit, TOP_CORE_PLL_CTRL_1r, &rval, AUX_POST_BYP_ENf, 1);
   1973     SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL_1r(unit, rval));
   1974 
   1975     /* 2: wait 1 us */
   1976     sal_usleep(1);
   1977 
   1978     /* 3 */
   1979     soc_reg_field_set(unit, TOP_CORE_PLL_CTRL_1r, &rval, SW_RST_ENf, 1);
   1980     SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL_1r(unit, rval));
   1981 
   1982     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   1983     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_CORE_PLL_RST_Lf, 0);
   1984     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_CORE_PLL_POST_RST_Lf, 0);
   1985     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   1986 
   1987 
   1988     /* To 4: Programming of PLL config parameters follows this in calling
   1989      * function */
   1990 
   1991     return SOC_E_NONE;
   1992 }
   1993 
   1994 /*
   1995  * Function:
   1996  *      soc_tomahawk3_core_pll_bypass_prog_post
   1997  * Purpose:
   1998  *      Performs steps 5-9 of the CORE_PLL Programming sequence, and
   1999  *      is done when TH3 is operating at a different core clock frequency
   2000  * Parameters:
   2001  *      unit     - (IN) Unit number
   2002  * Returns:
   2003  *      SOC_E_XXX
   2004  */
   2005 STATIC int
   2006 _soc_tomahawk3_core_pll_bypass_prog_post(int unit)
   2007 {
   2008     uint32 rval;
   2009 
   2010     /* From 4: This follows the programming of the PLL config parameters from
   2011      * the calling function */
   2012 
   2013     /* 5 */
   2014     SOC_IF_ERROR_RETURN(READ_TOP_CORE_PLL_CTRL_1r(unit, &rval));
   2015     soc_reg_field_set(unit, TOP_CORE_PLL_CTRL_1r, &rval, SW_CFG_SELf, 1);
   2016     SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL_1r(unit, rval));
   2017 
   2018     /* 6 */
   2019     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   2020     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_CORE_PLL_RST_Lf, 1);
   2021     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   2022 
   2023     /* 7: wait 10 us */
   2024     sal_usleep(10);
   2025 
   2026     /* 8 */
   2027     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   2028     soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_CORE_PLL_POST_RST_Lf, 1);
   2029     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   2030 
   2031     /* 9 */
   2032     SOC_IF_ERROR_RETURN(READ_TOP_CORE_PLL_CTRL_1r(unit, &rval));
   2033     soc_reg_field_set(unit, TOP_CORE_PLL_CTRL_1r, &rval, AUX_POST_BYP_ENf, 0);
   2034     SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL_1r(unit, rval));
   2035 
   2036     return SOC_E_NONE;
   2037 }
   2038 
   2039 /*
   2040  * Function:
   2041  *      soc_tomahawk3_core_pll_config
   2042  * Purpose:
   2043  *      Performs necessary steps to configure the chip for different
   2044  *      core frequencies.  For TH3, only TOP_CORE_PLL_CTRL_0.NDIV_INT
   2045  *      is changed
   2046  * Parameters:
   2047  *      unit     - (IN) Unit number
   2048  * Returns:
   2049  *      SOC_E_XXX
   2050  */
   2051 STATIC int
   2052 _soc_tomahawk3_core_pll_config(int unit, int frequency)
   2053 {
   2054 #define _SOC_TH3_PLL_CFG_FIELDS  (1)
   2055 
   2056     soc_field_t fields[_SOC_TH3_PLL_CFG_FIELDS];
   2057     uint32 values[_SOC_TH3_PLL_CFG_FIELDS];
   2058 
   2059     int ndiv_int = -1;
   2060     int count;
   2061 
   2062     if (frequency > 0) {
   2063         switch (frequency) {
   2064         case 1325:
   2065             /* Don't do anything if core clock is default */
   2066             break;
   2067         case 1250:
   2068             ndiv_int = 100;
   2069             break;
   2070         case 1175:
   2071             ndiv_int = 94;
   2072             break;
   2073         case 1100:
   2074             ndiv_int = 88;
   2075             break;
   2076         case 1000:
   2077             ndiv_int = 80;
   2078             break;
   2079         case 925:
   2080             ndiv_int = 74;
   2081             break;
   2082         default:
   2083             break;
   2084         }
   2085     } else {
   2086         ndiv_int = soc_property_get(unit, "force_core_pll_ndiv_int", -1);
   2087     }
   2088 
   2089     count = 0;
   2090     if (ndiv_int != -1) {
   2091         LOG_INFO(BSL_LS_SOC_COMMON,
   2092                  (BSL_META_U(unit,
   2093                              "*** change NDIV_INT to %d\n"), ndiv_int));
   2094         fields[count] = NDIV_INTf;
   2095         values[count] = ndiv_int;
   2096         count++;
   2097     }
   2098     if (count > 0) {
   2099         /* Call this to prepare TH3 for changing the core pll frequency */
   2100         SOC_IF_ERROR_RETURN(_soc_tomahawk3_core_pll_bypass_prog_pre(unit));
   2101 
   2102         SOC_IF_ERROR_RETURN
   2103             (soc_reg_fields32_modify(unit, TOP_CORE_PLL_CTRL_0r,
   2104                                      REG_PORT_ANY, count, fields, values));
   2105         /* Call this after changing the core pll frequency to bring the
   2106          * core pll bypass out of reset */
   2107         SOC_IF_ERROR_RETURN(_soc_tomahawk3_core_pll_bypass_prog_post(unit));
   2108     }
   2109 
   2110     return SOC_E_NONE;
   2111 }
   2112 
   2113 int
   2114 soc_tomahawk3_chip_reset(int unit)
   2115 {
   2116     uint16 dev_id;
   2117     uint8 rev_id;
   2118     uint32 to_usec, temp_mask;
   2119     uint32 rval, temp_thr;
   2120     uint32 trval;
   2121     uint32 val;
   2122     soc_reg_t reg;
   2123     int index = 0, freq = 0;
   2124     int parity_enable;
   2125     int frequency;
   2126 
   2127     soc_cm_get_id(unit, &dev_id, &rev_id);
   2128     to_usec = SAL_BOOT_QUICKTURN ? (250 * MILLISECOND_USEC) :
   2129                                    (10 * MILLISECOND_USEC);
   2130 
   2131     /*
   2132      * SBUS ring and block number:
   2133      * ring 0: OTPC(6,7), AVS(87), TOP(8)
   2134      * ring 1: IP(1)
   2135      * ring 2: EP(2)
   2136      * ring 3: MMU_ITM(3), MMU_EB(4), MMU_GLB(5)
   2137      * ring 4: PM0(16), PM1(17), ... , PM14(30), PM15(31)
   2138      * ring 5: PM16(32), PM17(33), ... , PM30(46), PM31(47)
   2139      * ring 6: CEV(88)
   2140      * ring 7: PM_MGMT(12)
   2141      */
   2142 #ifdef BCM_CMICX_SUPPORT
   2143     if (soc_feature(unit, soc_feature_cmicx)) {
   2144         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_0_7_OFFSET,0x00333210);
   2145         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_8_15_OFFSET,0x00070000);
   2146         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_16_23_OFFSET,0x44444444);
   2147         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_24_31_OFFSET,0x44444444);
   2148         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_32_39_OFFSET,0x55555555);
   2149         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_40_47_OFFSET,0x55555555);
   2150         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_48_55_OFFSET,0x00000000);
   2151         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_56_63_OFFSET,0x00005004);
   2152         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_64_71_OFFSET,0x00000000);
   2153         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_72_79_OFFSET,0x00000000);
   2154         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_80_87_OFFSET,0x00000000);
   2155         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_88_95_OFFSET,0x00000006);
   2156         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_96_103_OFFSET,0x00000000);
   2157         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_104_111_OFFSET,0x00000000);
   2158         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_112_119_OFFSET,0x00000000);
   2159         soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_120_127_OFFSET,0x00000000);
   2160         /*if (!SAL_BOOT_QUICKTURN) {*/
   2161         soc_pci_write(unit, CMIC_TOP_SBUS_TIMEOUT_OFFSET,0x2700);
   2162         /*}*/
   2163     }
   2164 #endif
   2165     sal_usleep(to_usec);
   2166 
   2167 
   2168     if (!SAL_BOOT_SIMULATION) {
   2169         if (soc_property_get(unit, "force_core_pll", 0)) {
   2170             frequency = soc_property_get(unit, "force_core_pll_freq", -1);
   2171         } else {
   2172             frequency = SOC_INFO(unit).frequency;
   2173         }
   2174         SOC_IF_ERROR_RETURN(_soc_tomahawk3_core_pll_config(unit, frequency));
   2175         sal_usleep(to_usec);
   2176     }
   2177 
   2178     /* Set the PP_PLL */
   2179     if (!SAL_BOOT_SIMULATION) {
   2180         freq = soc_property_get(unit, spn_DPR_CLOCK_FREQUENCY, 1000);
   2181         SOC_IF_ERROR_RETURN(_soc_th3_pp_pll_config(unit, freq));
   2182     }
   2183 
   2184 
   2185     /* PLLs are not required in simulation environments */
   2186     if (!SAL_BOOT_SIMULATION) {
   2187         /* Configure TS PLL */
   2188         
   2189 #if 0
   2190         SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_1r(unit,&rval));
   2191         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, &rval, PDIVf,
   2192                           soc_property_get(unit, spn_PTP_TS_PLL_PDIV, 2));
   2193         SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_1r(unit, rval));
   2194 
   2195         SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_2r(unit,&rval));
   2196         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_2r, &rval, CH0_MDIVf,
   2197                           soc_property_get(unit, spn_PTP_TS_PLL_MNDIV, 5));
   2198         SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_2r(unit, rval));
   2199 
   2200         SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_0r(unit,&rval));
   2201         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_0r, &rval, NDIV_INTf,
   2202                           soc_property_get(unit, spn_PTP_TS_PLL_N, 100));
   2203         SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_0r(unit, rval));
   2204 
   2205         SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_1r(unit,&rval));
   2206         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, &rval, KAf,
   2207                           soc_property_get(unit, spn_PTP_TS_KA, 10));
   2208         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, &rval, KIf,
   2209                           soc_property_get(unit, spn_PTP_TS_KI, 3));
   2210         soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, &rval, KPf,
   2211                           soc_property_get(unit, spn_PTP_TS_KP, 10));
   2212         SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_1r(unit, rval));
   2213 #endif
   2214         /* Set 250Mhz (implies 4ns resolution) default timesync clock to
   2215            calculate assymentric delays */
   2216         SOC_TIMESYNC_PLL_CLOCK_NS(unit) = (1/250 * 1000); /* clock period in nsec */
   2217 #if 0
   2218         /* Configure BS PLL0 */
   2219         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_1r(unit, &rval));
   2220         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, &rval, PDIVf,
   2221                       soc_property_get(unit, spn_PTP_BS_PDIV, 2));
   2222         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_1r(unit, rval));
   2223 
   2224         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_2r(unit, &rval));
   2225         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_2r, &rval, CH0_MDIVf,
   2226                           soc_property_get(unit, spn_PTP_BS_MNDIV, 125));
   2227         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_2r(unit, rval));
   2228 
   2229         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_0r(unit, &rval));
   2230         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_0r, &rval, NDIV_INTf,
   2231                       soc_property_get(unit, spn_PTP_BS_NDIV_INT, 100));
   2232         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_0r(unit, rval));
   2233 
   2234         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_1r(unit, &rval));
   2235         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, &rval, KAf,
   2236                           soc_property_get(unit, spn_PTP_BS_KA, 10));
   2237         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, &rval, KIf,
   2238                           soc_property_get(unit, spn_PTP_BS_KI, 3));
   2239         soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, &rval, KPf,
   2240                           soc_property_get(unit, spn_PTP_BS_KP, 10));
   2241         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_1r(unit, rval));
   2242 
   2243         /* Configure BS PLL1 */
   2244         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_1r(unit, &rval));
   2245         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, &rval, PDIVf,
   2246                           soc_property_get(unit, spn_PTP_BS_PDIV, 2));
   2247         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_1r(unit, rval));
   2248 
   2249         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_2r(unit, &rval));
   2250         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_2r, &rval, CH0_MDIVf,
   2251                           soc_property_get(unit, spn_PTP_BS_MNDIV, 125));
   2252         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_2r(unit, rval));
   2253 
   2254         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_0r(unit, &rval));
   2255         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_0r, &rval, NDIV_INTf,
   2256                           soc_property_get(unit, spn_PTP_BS_NDIV_INT, 100));
   2257         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_0r(unit, rval));
   2258 
   2259         SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_1r(unit, &rval));
   2260         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, &rval, KAf,
   2261                           soc_property_get(unit, spn_PTP_BS_KA, 10));
   2262         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, &rval, KIf,
   2263                           soc_property_get(unit, spn_PTP_BS_KI, 3));
   2264         soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, &rval, KPf,
   2265                           soc_property_get(unit, spn_PTP_BS_KP, 10));
   2266         SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_1r(unit, rval));
   2267 #endif
   2268 
   2269         /* Bring LCPLL, time sync, BroadSync, IPROC, PP, CORE PLLs
   2270            and AVS out of reset */
   2271         SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   2272         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_TS_PLL_RST_Lf, 1);
   2273         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL0_RST_Lf,
   2274                           1);
   2275         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL1_RST_Lf,
   2276                           1);
   2277         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf, 1);
   2278         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2279                           TOP_IPROC_PLL_RST_Lf, 1);
   2280         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2281                           TOP_PP_PLL_RST_Lf, 1);
   2282         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2283                           TOP_CORE_PLL_RST_Lf, 1);
   2284         SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   2285 
   2286         SOC_IF_ERROR_RETURN(READ_IDM_GENRES_S0_IDM_RESET_CONTROLr(unit, &rval));
   2287         soc_reg_field_set(unit, IDM_GENRES_S0_IDM_RESET_CONTROLr, &rval, RESETf, 1);
   2288         SOC_IF_ERROR_RETURN(WRITE_IDM_GENRES_S0_IDM_RESET_CONTROLr(unit, rval));
   2289         
   2290         SOC_IF_ERROR_RETURN(READ_IDM_GENRES_S0_IDM_RESET_CONTROLr(unit, &rval));
   2291         soc_reg_field_set(unit, IDM_GENRES_S0_IDM_RESET_CONTROLr, &rval, RESETf, 0);
   2292         SOC_IF_ERROR_RETURN(WRITE_IDM_GENRES_S0_IDM_RESET_CONTROLr(unit, rval));
   2293 
   2294 
   2295 
   2296 
   2297         sal_usleep(to_usec);
   2298 
   2299         /* Check LCPLL lock status */
   2300         
   2301 #if 0
   2302         reg = TOP_XG_PLL0_STATUSr;
   2303         SOC_IF_ERROR_RETURN
   2304             (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2305         if (!soc_reg_field_get(unit, reg, rval, TOP_XGPLL_LOCKf)) {
   2306             LOG_ERROR(BSL_LS_SOC_COMMON,
   2307                       (BSL_META_U(unit,
   2308                                  "LCPLL %d not locked on unit %d "
   2309                                  "status = 0x%08x\n"), index, unit, rval));
   2310         }
   2311 #endif
   2312 
   2313         /* Check time sync lock status */
   2314         reg = TOP_TS_PLL_STATUSr;
   2315         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2316         if (!soc_reg_field_get(unit, reg, rval, LOCKf)) {
   2317             LOG_ERROR(BSL_LS_SOC_COMMON,
   2318                       (BSL_META_U(unit,
   2319                                   "TS_PLL not locked on unit %d "
   2320                                   "status = 0x%08x\n"), unit, rval));
   2321         }
   2322         /* Check BroadSync lock status */
   2323         reg = TOP_BS_PLL0_STATUSr;
   2324         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2325         if (!soc_reg_field_get(unit, reg, rval, LOCKf)) {
   2326             LOG_ERROR(BSL_LS_SOC_COMMON,
   2327                       (BSL_META_U(unit,
   2328                                   "BS_PLL0 not locked on unit %d "
   2329                                   "status = 0x%08x\n"), unit, rval));
   2330         }
   2331 
   2332         reg = TOP_BS_PLL1_STATUSr;
   2333         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2334         if (!soc_reg_field_get(unit, reg, rval, LOCKf)) {
   2335             LOG_ERROR(BSL_LS_SOC_COMMON,
   2336                       (BSL_META_U(unit,
   2337                                   "BS_PLL0 not locked on unit %d "
   2338                                   "status = 0x%08x\n"), unit, rval));
   2339         }
   2340 
   2341         /* Check PP lock status */
   2342         reg = TOP_PP_PLL_STATUSr;
   2343         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2344         if (!soc_reg_field_get(unit, reg, rval, LOCKf)) {
   2345             LOG_ERROR(BSL_LS_SOC_COMMON,
   2346                       (BSL_META_U(unit,
   2347                                   "BS_PLL0 not locked on unit %d "
   2348                                   "status = 0x%08x\n"), unit, rval));
   2349         }
   2350 
   2351         /* De-assert LCPLL's post reset */
   2352         SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval));
   2353         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2354                           TOP_TS_PLL_POST_RST_Lf, 1);
   2355         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2356                           TOP_BS_PLL0_POST_RST_Lf, 1);
   2357         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2358                           TOP_BS_PLL1_POST_RST_Lf, 1);
   2359         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2360                           TOP_IPROC_PLL_POST_RST_Lf, 1);
   2361         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2362                           TOP_PP_PLL_POST_RST_Lf, 1);
   2363         soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval,
   2364                           TOP_CORE_PLL_POST_RST_Lf, 1);
   2365         SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval));
   2366     }
   2367 
   2368     sal_usleep(to_usec);
   2369 
   2370     /* Check the the sticky bit whether HW PVTMON High Temperature Protection
   2371     * happened in system's previous running or not. Halt the current bootup, print error
   2372     * message, and ask for a system reboot if the sticky bit was set. */
   2373 
   2374     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_RESULT_0r(unit, &rval));
   2375     if (soc_reg_field_get(unit, TOP_PVTMON_RESULT_0r,
   2376                           rval, PVTMON_HIGHTEMP_STATUSf)) {
   2377         LOG_ERROR(BSL_LS_SOC_COMMON,
   2378                   (BSL_META_U(unit,
   2379                               "HW PVTMON High Temperature Protection "
   2380                               "was invoked during last system run. "
   2381                               "Please correct the temperature problem "
   2382                               "and cycle power to continue.\n")));
   2383 
   2384             /* Clear HIGHTEMP sticky bit on all PVTMONs */
   2385             SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROL_1r(unit, &rval));
   2386             soc_reg_field_set(unit, TOP_MISC_CONTROL_1r, &rval, PVTMON_HIGHTEMP_STAT_CLEARf, 1);
   2387             SOC_IF_ERROR_RETURN(WRITE_TOP_MISC_CONTROL_1r(unit, rval));
   2388 
   2389         return SOC_E_FAIL;
   2390     }
   2391 
   2392 
   2393     /* Set correct value for BG_ADJ */
   2394     /* TH2 leaves it to be default
   2395     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_0r(unit, &rval));
   2396     soc_reg_field_set(unit, TOP_PVTMON_CTRL_0r, &rval, BG_ADJf, 0);
   2397     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_0r(unit, rval));
   2398     */
   2399 
   2400     /* Enable high temperature interrupt monitoring.
   2401      */
   2402     temp_mask = soc_property_get(unit, "temp_monitor_select", ((1 << 16)-1));
   2403     /* The above is a 9 bit mask to indicate which temp sensor to hook up to
   2404      * the interrupt.
   2405      */
   2406     val = 0;
   2407     for (index = 0; index <COUNTOF(temp_thr_reg)-1; index++) {
   2408         /* AVS excluded */
   2409 
   2410         trval = 0;
   2411         /* Temp = 434.10 - o_ADC_data * 0.53504
   2412          * data = (434.10 - temp)/0.53504 = (434100-(temp*1000))/535
   2413          * Note: Since this is a high temp value we can safely assume it to
   2414          * always be a +ive number. This is in degrees celcius.
   2415          */
   2416         temp_thr =
   2417             soc_property_get(unit, temp_thr_prop[index], 
   2418                 ((index < 5) || (index == 6) || (index == 10)) ? \
   2419                 _SOC_TH3_HW_TEMP_MAX : _SOC_TH3_SW_TEMP_MAX);
   2420         if (temp_thr > _SOC_TH3_HW_TEMP_MAX) {
   2421             LOG_ERROR(BSL_LS_SOC_COMMON,
   2422                       (BSL_META_U(unit,
   2423                                     "Unsupported temp value %d !!. "
   2424                                     "Max %d. Using %d.\n"),
   2425                         temp_thr, _SOC_TH3_HW_TEMP_MAX,  _SOC_TH3_HW_TEMP_MAX));
   2426             temp_thr = _SOC_TH3_HW_TEMP_MAX;
   2427         }
   2428 
   2429         /* Convert temperature to config data */
   2430         temp_thr = (434100-(temp_thr*1000))/535;
   2431 
   2432         SOC_IF_ERROR_RETURN
   2433             (soc_reg32_get(unit, temp_thr_reg[index], REG_PORT_ANY, 0, &trval));
   2434         soc_reg_field_set(unit, temp_thr_reg[index], &trval, MIN_THRESHOLDf,
   2435                           temp_thr);
   2436         SOC_IF_ERROR_RETURN
   2437             (soc_reg32_set(unit, temp_thr_reg[index], REG_PORT_ANY, 0, trval));
   2438         if (temp_mask & (1 << index)) {
   2439             val |= (1 << ((index * 2) + 1)); /* 2 bits per pvtmon, using min */
   2440         }
   2441     }
   2442     _soc_th_temp_mon_mask[unit] = temp_mask;
   2443 
   2444     /* Enable high temperature interrupt monitoring excluding 15 (AVS), 10, 6, 4, 3, 2, 1, 0 . */
   2445     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_INTR_MASK_0r(unit, val & 0x3fcfcc00));
   2446 
   2447     /* Enable PVTMON interrupt in CMIC */
   2448     SOC_IF_ERROR_RETURN(soc_iproc_getreg(unit,
   2449                         soc_reg_addr(unit, ICFG_CHIP_LP_INTR_ENABLE_REG0r,
   2450                         REG_PORT_ANY, 0), &rval));
   2451     rval |= 0x4;
   2452     SOC_IF_ERROR_RETURN(soc_iproc_setreg(unit,
   2453                         soc_reg_addr(unit, ICFG_CHIP_LP_INTR_ENABLE_REG0r,
   2454                         REG_PORT_ANY, 0), rval));
   2455 
   2456 
   2457     /* Bring the Temp monitor minimum value out of reset */
   2458     for (index = 0; index <COUNTOF(temp_pvtmon_ctrl_reg); index++) {
   2459 
   2460         trval = 0;
   2461         SOC_IF_ERROR_RETURN
   2462             (soc_reg32_get(unit, temp_pvtmon_ctrl_reg[index].pvtmon_reg,
   2463                            REG_PORT_ANY, 0, &trval));
   2464         soc_reg_field_set(unit, temp_pvtmon_ctrl_reg[index].pvtmon_reg, &trval,
   2465                           temp_pvtmon_ctrl_reg[index].pvtmon_field, 1);
   2466         SOC_IF_ERROR_RETURN
   2467             (soc_reg32_set(unit, temp_pvtmon_ctrl_reg[index].pvtmon_reg,
   2468                            REG_PORT_ANY, 0, trval));
   2469     }
   2470 
   2471     /* Enable HW PVTMON high temperature protection by setting
   2472        hightemp_ctrl_en field for pvtmon 0-4, 6 and 10 */
   2473     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_0_CTRL_1r(unit, &rval));
   2474     soc_reg_field_set(unit, TOP_PVTMON_0_CTRL_1r, &rval, PVTMON_HIGHTEMP_CTRL_ENf, 1);
   2475     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_0_CTRL_1r(unit, rval));
   2476 
   2477     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_1_CTRL_1r(unit, &rval));
   2478     soc_reg_field_set(unit, TOP_PVTMON_1_CTRL_1r, &rval, PVTMON_HIGHTEMP_CTRL_ENf, 1);
   2479     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_1_CTRL_1r(unit, rval));
   2480 
   2481     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_2_CTRL_1r(unit, &rval));
   2482     soc_reg_field_set(unit, TOP_PVTMON_2_CTRL_1r, &rval, PVTMON_HIGHTEMP_CTRL_ENf, 1);
   2483     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_2_CTRL_1r(unit, rval));
   2484 
   2485     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_3_CTRL_1r(unit, &rval));
   2486     soc_reg_field_set(unit, TOP_PVTMON_3_CTRL_1r, &rval, PVTMON_HIGHTEMP_CTRL_ENf, 1);
   2487     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_3_CTRL_1r(unit, rval));
   2488 
   2489     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_4_CTRL_1r(unit, &rval));
   2490     soc_reg_field_set(unit, TOP_PVTMON_4_CTRL_1r, &rval, PVTMON_HIGHTEMP_CTRL_ENf, 1);
   2491     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_4_CTRL_1r(unit, rval));
   2492 
   2493     SOC_IF_ERROR_RETURN(READ_TOP_TMON_CTRL_1r(unit, &rval));
   2494     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_6_PVTMON_HIGHTEMP_CTRL_ENf, 1);
   2495     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_10_PVTMON_HIGHTEMP_CTRL_ENf, 1);
   2496     SOC_IF_ERROR_RETURN(WRITE_TOP_TMON_CTRL_1r(unit, rval));
   2497 
   2498     /* Bring port blocks out of reset */
   2499     rval = 0;
   2500     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_PM_MGMT_RST_Lf, 1);
   2501     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_TS_RST_Lf, 1);
   2502     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval));
   2503     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_3r(unit, 0xffffffff));
   2504     sal_usleep(to_usec);
   2505 
   2506     /* Need set PSG/PCG to 0 before de-assert IP/EP/MMU SOFT reset  */
   2507     SOC_IF_ERROR_RETURN(WRITE_TOP_CLOCKING_ENFORCE_PSGr(unit, 0));
   2508     SOC_IF_ERROR_RETURN(WRITE_TOP_CLOCKING_ENFORCE_PCGr(unit, 0));
   2509 
   2510     /* Bring IP, EP, and MMU blocks out of reset */
   2511     SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REGr(unit, &rval));
   2512     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_IP_RST_Lf, 1);
   2513     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_EP_RST_Lf, 1);
   2514     soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_MMU_RST_Lf, 1);
   2515     SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval));
   2516     sal_usleep(to_usec);
   2517 
   2518     /* Need to enable SLOT_PIPELINE_ECC_EN before configuring slot pipeline */
   2519     parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE);
   2520     if (parity_enable) {
   2521         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, IPOST_SER_CONTROLr,
   2522                                                    REG_PORT_ANY,
   2523                                                    SLOT_PIPELINE_ECC_ENf,1));
   2524         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, EPOST_SER_CONTROLr,
   2525                                                    REG_PORT_ANY,
   2526                                                    SLOT_PIPELINE_ECC_ENf,1));
   2527     }
   2528     /* IP/EP Slot pipeline configuration */
   2529     /* Needs to be configured before accessing registers in IP/EP
   2530        and also before ip/ep memories are initialized
   2531     */
   2532     SOC_IF_ERROR_RETURN(soc_tomahawk3_slot_pipeline_config(unit));
   2533 
   2534     SOC_IF_ERROR_RETURN(_soc_tomahawk3_init_ipep_memory(unit));
   2535 
   2536     /* Bypass unused Port Blocks */
   2537     if (soc_property_get(unit, "disable_unused_port_blocks", TRUE)) {
   2538         SOC_IF_ERROR_RETURN(soc_th3_bypass_unused_pm(unit));
   2539     }
   2540 
   2541     return SOC_E_NONE;
   2542 }
   2543 
   2544 STATIC
   2545 int _soc_tomahawk3_activate_pm8x50(int unit, int phy_port)
   2546 {
   2547     uint8 at;
   2548     uint32 raddr, reg_val;
   2549     soc_block_t block;
   2550     soc_reg_t reg = CDPORT_XGXS0_CTRL_REGr;
   2551     int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100;
   2552 
   2553     /* index the register by phy port to activate the PM */
   2554     raddr = soc_reg_addr_get(unit, reg, phy_port, 0,
   2555             SOC_REG_ADDR_OPTION_PRESERVE_PORT, &block, &at);
   2556     SOC_IF_ERROR_RETURN(_soc_reg32_get(unit, block, at, raddr, &reg_val));
   2557 
   2558     soc_reg_field_set(unit, reg, &reg_val, TSC_PWRDWNf, 0);
   2559     soc_reg_field_set(unit, reg, &reg_val, TSC_CLK_SELf, 1);
   2560     SOC_IF_ERROR_RETURN(_soc_reg32_set(unit, block, at, raddr, reg_val));
   2561     sal_usleep(sleep_usec);
   2562 
   2563     soc_reg_field_set(unit, reg, &reg_val, TSC_RSTBf, 0);
   2564     SOC_IF_ERROR_RETURN(_soc_reg32_set(unit, block, at, raddr, reg_val));
   2565     sal_usleep(sleep_usec+10000);
   2566 
   2567     soc_reg_field_set(unit, reg, &reg_val, TSC_RSTBf, 1);
   2568     SOC_IF_ERROR_RETURN(_soc_reg32_set(unit, block, at, raddr, reg_val));
   2569     sal_usleep(sleep_usec);
   2570 
   2571     return SOC_E_NONE;
   2572 }
   2573 
   2574 STATIC
   2575 int soc_tomahawk3_cdport_reset(int unit)
   2576 {
   2577     int i, blk, pm, port, phy_port = 1;
   2578     uint32 pipe_map;
   2579     soc_info_t * si;
   2580     int pm_reset[_TH3_PBLKS_PER_DEV];
   2581     uint16 dev_id;
   2582     uint8 rev_id;
   2583 
   2584     si = &SOC_INFO(unit);
   2585 
   2586     sal_memset(pm_reset, 0, sizeof(pm_reset));
   2587 
   2588     /* reset the PMs that have mappings */
   2589     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CDPORT) {
   2590         port = SOC_BLOCK_PORT(unit, blk);
   2591 
   2592         phy_port = si->port_l2p_mapping[port];
   2593         /* mark that this PM has been reset */
   2594         pm_reset[(phy_port-1)/_TH3_PORTS_PER_PBLK] = 1;
   2595 
   2596         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_reset(unit, port, 0));
   2597     }
   2598 
   2599     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   2600 
   2601     soc_cm_get_id(unit, &dev_id, &rev_id);
   2602 
   2603     /* reset any master PMs that haven't been reset yet.
   2604      * In TH3 A0 the master PMs are 1, 2, 5, 6, 9, 10, 13, 14, 17,
   2605      *                              18, 22, 22, 26, 26, 29, 30 */
   2606     if (rev_id == BCM56980_A0_REV_ID) {
   2607         for (i = 0; i < 2; i++) {
   2608             for (pm = 1 + i; pm < _TH3_PBLKS_PER_DEV; pm+=4) {
   2609                 /* skip if the pm has already been reset */
   2610                 if (pm_reset[pm] == 1) {
   2611                     continue;
   2612                 }
   2613 
   2614                 /* skip a PM if the pipe it is located in is disabled */
   2615                 if ((pipe_map & (1 << (pm / _TH3_PBLKS_PER_PIPE))) == 0) {
   2616                     continue;
   2617                 }
   2618 
   2619                 /* get the first phy port of the PM */
   2620                 phy_port = (pm * _TH3_PORTS_PER_PBLK) + 1;
   2621 
   2622                 /* Activate the PM */
   2623                 SOC_IF_ERROR_RETURN(
   2624                         _soc_tomahawk3_activate_pm8x50(unit, phy_port));
   2625             }
   2626         }
   2627     } else {
   2628         /* In TH3 B0 the master PMs are 3, 4, 11, 12, 19, 20, 27, 28 */
   2629         for (pm = 0; pm < _TH3_PBLKS_PER_DEV; pm++) {
   2630             /* Skip if not a master PM */
   2631             if ( !(pm == 3 || pm == 4 || pm == 11 || pm == 12 ||
   2632                    pm == 19 || pm == 20 || pm == 27 || pm == 28) ) {
   2633                 continue;
   2634             }
   2635 
   2636             /* skip if the pm has already been reset */
   2637             if (pm_reset[pm] == 1) {
   2638                 continue;
   2639             }
   2640 
   2641             /* skip a PM if the pipe it is located in is disabled */
   2642             if ((pipe_map & (1 << (pm / _TH3_PBLKS_PER_PIPE))) == 0) {
   2643                 continue;
   2644             }
   2645 
   2646             /* get the first phy port of the PM */
   2647             phy_port = (pm * _TH3_PORTS_PER_PBLK) + 1;
   2648 
   2649             /* Activate the PM */
   2650             SOC_IF_ERROR_RETURN(
   2651                     _soc_tomahawk3_activate_pm8x50(unit, phy_port));
   2652 
   2653         }
   2654     }
   2655 
   2656     return SOC_E_NONE;
   2657 }
   2658 
   2659 int
   2660 soc_tomahawk3_port_reset(int unit)
   2661 {
   2662     uint32 rval;
   2663     int blk, port;
   2664 
   2665     /* Instead of using the generic TSC init, TH3 needs to be aware
   2666      * of master port macros that need to be initialized so that the clocks
   2667      * of the slaves will come up. This is why this function is needed
   2668      * rather than calling soc_tsc_xgxs_reset */
   2669     SOC_IF_ERROR_RETURN(soc_tomahawk3_cdport_reset(unit));
   2670 
   2671     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   2672         port = SOC_BLOCK_PORT(unit, blk);
   2673         SOC_IF_ERROR_RETURN(soc_tsc_xgxs_reset(unit, port, 0));
   2674     }
   2675 
   2676 
   2677     SOC_BLOCK_ITER(unit, blk, SOC_BLK_CDPORT) {
   2678         port = SOC_BLOCK_PORT(unit, blk);
   2679 
   2680         SOC_IF_ERROR_RETURN(READ_CDPORT_MAC_CONTROLr(unit, port, &rval));
   2681         soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &rval, CDMAC0_RESETf, 1);
   2682         soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &rval, CDMAC1_RESETf, 1);
   2683         SOC_IF_ERROR_RETURN(WRITE_CDPORT_MAC_CONTROLr(unit, port, rval));
   2684         sal_udelay(10);
   2685         soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &rval, CDMAC0_RESETf, 0);
   2686         soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &rval, CDMAC1_RESETf, 0);
   2687 #if 0
   2688         /* removed from latest regsfile */
   2689         soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &rval, SYS_64B_INTF_MODEf, 1);
   2690 #endif
   2691 
   2692         SOC_IF_ERROR_RETURN(WRITE_CDPORT_MAC_CONTROLr(unit, port, rval));
   2693     }
   2694 
   2695     SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) {
   2696         port = SOC_BLOCK_PORT(unit, blk);
   2697 
   2698         SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_CONTROLr(unit, port, &rval));
   2699         soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1);
   2700         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval));
   2701         sal_udelay(10);
   2702         soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0);
   2703         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval));
   2704     }
   2705 
   2706     return SOC_E_NONE;
   2707 }
   2708 
   2709 
   2710 int
   2711 soc_tomahawk3_port_speed_update(int unit, soc_port_t port, int speed)
   2712 {
   2713     uint32 rval, fval;
   2714     uint32 entry[SOC_MAX_MEM_WORDS];
   2715     soc_info_t *si = &SOC_INFO(unit);
   2716     int rv;
   2717 
   2718     /*
   2719      * No reconfiguration is needed if new speed
   2720      * matches current speed
   2721      */
   2722     if (speed == si->port_init_speed[port]) {
   2723         return SOC_E_NONE;
   2724     }
   2725 
   2726     rv = soc_th_port_asf_mode_set(unit, port, speed,
   2727                                   _SOC_TH_ASF_MODE_CFG_UPDATE);
   2728     if ((SOC_E_NONE != rv) && (SOC_E_UNAVAIL != rv) && (SOC_E_PARAM != rv)) {
   2729         return rv;
   2730     }
   2731 
   2732     /* OS related updates */
   2733     if (SOC_PBMP_NOT_NULL(SOC_INFO(unit).oversub_pbm)) {
   2734         sal_memset(entry, 0, sizeof(egr_xmit_start_count_entry_t));
   2735         fval = (speed * 11875)/100000;
   2736         soc_mem_field32_set(unit, EDB_1DBG_Bm, &entry, FIELD_Bf, fval);
   2737         SOC_IF_ERROR_RETURN
   2738             (soc_mem_write(unit, EDB_1DBG_Bm, MEM_BLOCK_ALL,
   2739                            SOC_INFO(unit).port_l2p_mapping[port], entry));
   2740 
   2741         rval = 0;
   2742         if (speed >= 100000) {
   2743             fval = 140;
   2744         } else if (speed >= 40000) {
   2745             fval = 60;
   2746         } else if (speed >= 25000) {
   2747             fval = 40;
   2748         } else if (speed >= 20000) {
   2749             fval = 30;
   2750         } else {
   2751             fval = 15;
   2752         }
   2753         soc_reg_field_set(unit, MMU_3DBG_Cr, &rval, FIELD_Af,
   2754                           fval + sal_rand() % 20);
   2755         SOC_IF_ERROR_RETURN
   2756             (soc_tomahawk_sc_reg32_set(unit, MMU_3DBG_Cr, -1, port, 0, rval));
   2757     }
   2758     if (!SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
   2759         soc_th_port_lanes_t lanes_ctrl;
   2760 
   2761         sal_memset(&lanes_ctrl, 0, sizeof(lanes_ctrl));
   2762         lanes_ctrl.port_base = port;
   2763         lanes_ctrl.lanes = TH_FLEXPORT_SPEED_SET_NUM_LANES;
   2764         lanes_ctrl.speed = speed;
   2765         SOC_IF_ERROR_RETURN(soc_th3_speed_set_init_ctrl(unit, &lanes_ctrl));
   2766         SOC_IF_ERROR_RETURN
   2767             (soc_tomahawk_port_lanes_set(unit, &lanes_ctrl));
   2768     }
   2769 
   2770     return SOC_E_NONE;
   2771 }
   2772 
   2773 int soc_th3_get_alpm_banks(int unit)
   2774 {
   2775     int rv = SOC_E_NONE;
   2776     uint32 bank_config;
   2777     uint32 hash_control_entry[SOC_MAX_MEM_WORDS];
   2778 
   2779     if (num_shared_alpm_banks[unit] == 0) {
   2780         rv = READ_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0, hash_control_entry);
   2781         if (SOC_FAILURE(rv)) {
   2782             num_shared_alpm_banks[unit] = 8;
   2783         } else {
   2784             bank_config = soc_mem_field32_get(unit, EXACT_MATCH_HASH_CONTROLm,
   2785                                   hash_control_entry, HASH_TABLE_BANK_CONFIGf);
   2786             if (bank_config & 0xF) { /* EXACT MATCH used UFT banks */
   2787                 num_shared_alpm_banks[unit] = 4; /* TH3 ALPM uses only 4 or 8 UFT banks */
   2788             } else {
   2789                 num_shared_alpm_banks[unit] = 8;
   2790             }
   2791         }
   2792     }
   2793 
   2794     return num_shared_alpm_banks[unit];
   2795 }
   2796 
   2797 int
   2798 soc_tomahawk3_alpm_mode_get(int unit)
   2799 {
   2800     return _soc_alpm_mode[unit];
   2801 }
   2802 
   2803 void
   2804 _soc_tomahawk3_alpm_bkt_view_set(int unit, int index, soc_mem_t view)
   2805 {
   2806     int bkt = (index >> (soc_th3_get_alpm_banks(unit) + 1) / 2) & SOC_TH_ALPM_BKT_MASK(unit);
   2807 
   2808     if (view != INVALIDm) {
   2809         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2810                     (BSL_META_U(unit,
   2811                                 "Unit:%d ALPM bkt set index:%d bkt:%d view:%s\n"),
   2812                                 unit, index, bkt, SOC_MEM_NAME(unit, view)));
   2813     }
   2814 }
   2815 
   2816 soc_mem_t
   2817 _soc_tomahawk3_alpm_bkt_view_get(int unit, int index)
   2818 {
   2819     soc_mem_t view = L3_DEFIP_ALPM_LEVEL3m;
   2820     int bkt = (index >> (soc_th3_get_alpm_banks(unit) + 1) / 2) & SOC_TH_ALPM_BKT_MASK(unit);
   2821 
   2822     if (view != INVALIDm) {
   2823         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   2824                     (BSL_META_U(unit,
   2825                                 "Unit:%d ALPM bkt get index:%d bkt:%d view:%s\n"),
   2826                                 unit, index, bkt, SOC_MEM_NAME(unit, view)));
   2827     }
   2828     return view;
   2829 }
   2830 
   2831 int soc_tomahawk3_mem_basetype_get(int unit, soc_mem_t mem)
   2832 {
   2833     int base_type;
   2834 
   2835     base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7;
   2836     return base_type;
   2837 }
   2838 
   2839 /* Function to Clear all Memories.
   2840  * Param
   2841  *   mmu_init - bool val to indicate whether to initialize mmu or not.
   2842  */
   2843 STATIC int
   2844 _soc_tomahawk3_init_ipep_memory(int unit)
   2845 {
   2846     uint32 pipe_map;
   2847     soc_reg_t reg;
   2848     int  pipe;
   2849     uint32 rval, in_progress;
   2850     int pipe_init_usec;
   2851     soc_timeout_t to;
   2852     l2_entry_hash_control_entry_t l2_entry_hash_control;
   2853     l3_entry_hash_control_entry_t l3_entry_hash_control;
   2854     tunnel_hash_control_entry_t tunnel_hash_control;
   2855     mpls_entry_hash_control_entry_t mpls_entry_hash_control;
   2856     exact_match_hash_control_entry_t exact_match_hash_control;
   2857 
   2858     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   2859 
   2860     sal_memset(&l2_entry_hash_control, 0, sizeof(l2_entry_hash_control_entry_t));
   2861     sal_memset(&l3_entry_hash_control, 0, sizeof(l3_entry_hash_control_entry_t));
   2862     sal_memset(&tunnel_hash_control, 0, sizeof(tunnel_hash_control_entry_t));
   2863     sal_memset(&mpls_entry_hash_control, 0, sizeof(mpls_entry_hash_control_entry_t));
   2864     sal_memset(&exact_match_hash_control, 0, sizeof(exact_match_hash_control_entry_t));
   2865 
   2866     /* In TH3, some of the IPEP memories are hash memories and we need special settings to clear
   2867        the hash memories. The settings include the configuring the reset_val of the fields in the
   2868        respective hash_control memories of the hash tables. Refer TH3-3821
   2869     */
   2870     soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm, &l2_entry_hash_control, ROBUST_HASH_ENf, 0x1);
   2871     soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm, &l2_entry_hash_control, HASH_OFFSET_DEDICATED_BANK_1f, 0x20);
   2872     soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm, &l2_entry_hash_control, HASH_TABLE_BANK_CONFIGf, 0x3);
   2873     SOC_IF_ERROR_RETURN
   2874         (WRITE_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   2875                                              &l2_entry_hash_control));
   2876 
   2877     soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm, &l3_entry_hash_control, ROBUST_HASH_ENf, 0x1);
   2878     soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm, &l3_entry_hash_control, HASH_OFFSET_DEDICATED_BANK_1f, 0x20);
   2879     soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm, &l3_entry_hash_control, HASH_TABLE_BANK_CONFIGf, 0xf);
   2880     SOC_IF_ERROR_RETURN
   2881         (WRITE_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   2882                                              &l3_entry_hash_control));
   2883 
   2884     soc_mem_field32_set(unit, L3_TUNNEL_HASH_CONTROLm, &tunnel_hash_control, ROBUST_HASH_ENf, 0x1);
   2885     soc_mem_field32_set(unit, L3_TUNNEL_HASH_CONTROLm, &tunnel_hash_control, HASH_OFFSET_DEDICATED_BANK_1f, 0x20);
   2886     soc_mem_field32_set(unit, L3_TUNNEL_HASH_CONTROLm, &tunnel_hash_control, HASH_TABLE_BANK_CONFIGf, 0xf);
   2887     SOC_IF_ERROR_RETURN
   2888         (WRITE_L3_TUNNEL_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   2889                                              &tunnel_hash_control));
   2890 
   2891     soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, &mpls_entry_hash_control, ROBUST_HASH_ENf, 0x1);
   2892     soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, &mpls_entry_hash_control, HASH_OFFSET_DEDICATED_BANK_1f, 0x20);
   2893     soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, &mpls_entry_hash_control, HASH_TABLE_BANK_CONFIGf, 0x3);
   2894     SOC_IF_ERROR_RETURN
   2895         (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   2896                                              &mpls_entry_hash_control));
   2897 
   2898     soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, &exact_match_hash_control, ROBUST_HASH_ENf, 0x1);
   2899     soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, &exact_match_hash_control, LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf, 0x1);
   2900     soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, &exact_match_hash_control, LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf, 0x2);
   2901     soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, &exact_match_hash_control, LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf, 0x3);
   2902     SOC_IF_ERROR_RETURN
   2903         (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   2904                                              &exact_match_hash_control));
   2905 
   2906 	/* Initial IPIPE memory */
   2907     rval = 0;
   2908     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1);
   2909     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1);
   2910     soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, 0x20000);
   2911     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   2912 
   2913     /* Initial DLB memory */
   2914     rval = 0;
   2915     soc_reg_field_set(unit, DLB_ECMP_HW_RESET_CONTROLr, &rval, RESET_ALLf, 1);
   2916     soc_reg_field_set(unit, DLB_ECMP_HW_RESET_CONTROLr, &rval, VALIDf, 1);
   2917     soc_reg_field_set(unit, DLB_ECMP_HW_RESET_CONTROLr, &rval, COUNTf, 0x1000);
   2918     SOC_IF_ERROR_RETURN(WRITE_DLB_ECMP_HW_RESET_CONTROLr(unit, rval));
   2919 
   2920     /* Initial EPIPE memory */
   2921     rval = 0;
   2922     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1);
   2923     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, VALIDf, 1);
   2924     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, COUNTf, 0xFFFF);
   2925     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval));
   2926 
   2927     /* Initial EPIPE memory */
   2928     rval = 0;
   2929     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1_COREr, &rval, RESET_ALLf, 1);
   2930     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1_COREr, &rval, VALIDf, 1);
   2931     soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1_COREr, &rval, COUNTf, 0xFFFF);
   2932     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1_COREr(unit, rval));
   2933 
   2934     /* For simulation, set timeout to 10 sec.  Otherwise, timeout = 50 ms */
   2935     if (SAL_BOOT_SIMULATION) {
   2936         pipe_init_usec = 10000000;
   2937     } else {
   2938         pipe_init_usec = 50000;
   2939     }
   2940     soc_timeout_init(&to, pipe_init_usec, 0);
   2941 
   2942     if (!SAL_BOOT_SIMULATION || SAL_BOOT_QUICKTURN)
   2943     {
   2944         /* Wait for IPIPE memory initialization done */
   2945         in_progress = pipe_map;
   2946         do {
   2947             for (pipe = 0; pipe < _TH3_PIPES_PER_DEV && in_progress; pipe++) {
   2948                 if (!(pipe_map & (1 << pipe))) {
   2949                     continue;
   2950                 }
   2951                 reg = SOC_REG_UNIQUE_ACC(unit, ING_HW_RESET_CONTROL_2r)[pipe];
   2952                 if (in_progress & (1 << pipe)) { /* not done yet */
   2953                     SOC_IF_ERROR_RETURN
   2954                         (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2955                         if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   2956                             in_progress ^= 1 << pipe;
   2957                         }
   2958                 }
   2959             }
   2960             if (soc_timeout_check(&to)) {
   2961                 LOG_WARN(BSL_LS_SOC_COMMON,
   2962                          (BSL_META_U(unit,
   2963                                      "unit %d : ING_HW_RESET timeout\n"), unit));
   2964                 break;
   2965             }
   2966         } while (in_progress != 0);
   2967 
   2968         /* Wait for EPIPE memory initialization done */
   2969         in_progress = pipe_map;
   2970         do {
   2971             for (pipe = 0; pipe < _TH3_PIPES_PER_DEV && in_progress; pipe++) {
   2972                 if (!(pipe_map & (1 << pipe))) {
   2973                     continue;
   2974                 }
   2975                 reg = SOC_REG_UNIQUE_ACC(unit, EGR_HW_RESET_CONTROL_1r)[pipe];
   2976                 if (in_progress & (1 << pipe)) { /* not done yet */
   2977                     SOC_IF_ERROR_RETURN
   2978                         (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2979                         if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   2980                             in_progress ^= 1 << pipe;
   2981                         }
   2982                 }
   2983             }
   2984             if (soc_timeout_check(&to)) {
   2985                 LOG_WARN(BSL_LS_SOC_COMMON,
   2986                          (BSL_META_U(unit,
   2987                                      "unit %d : ING_HW_RESET timeout\n"), unit));
   2988                 break;
   2989             }
   2990         } while (in_progress != 0);
   2991 
   2992         /* Wait for DLB memory initialization done */
   2993         in_progress = 1;
   2994         do {
   2995             reg = DLB_ECMP_HW_RESET_CONTROLr;
   2996             SOC_IF_ERROR_RETURN
   2997                 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   2998             if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   2999                 in_progress = 0;
   3000             }
   3001             if (soc_timeout_check(&to)) {
   3002                 LOG_WARN(BSL_LS_SOC_COMMON,
   3003                          (BSL_META_U(unit,
   3004                                      "unit %d : EGR_HW_RESET timeout\n"), unit));
   3005                 break;
   3006             }
   3007         } while (in_progress != 0);
   3008 
   3009         /* Wait for EPIPE memory initialization done */
   3010         /* This is a new register EGR_HW_RESET_CONTROL_1_CORE added for
   3011            TH3 which would help in initializing the EPIPE memories */
   3012         in_progress = pipe_map;
   3013         do {
   3014             for (pipe = 0; pipe < _TH3_PIPES_PER_DEV && in_progress; pipe++) {
   3015                 if (!(pipe_map & (1 << pipe))) {
   3016                     continue;
   3017                 }
   3018                 reg = SOC_REG_UNIQUE_ACC(unit, EGR_HW_RESET_CONTROL_1_COREr)[pipe];
   3019                 if (in_progress & (1 << pipe)) { /* not done yet */
   3020                     SOC_IF_ERROR_RETURN
   3021                         (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   3022                         if (soc_reg_field_get(unit, reg, rval, DONEf)) {
   3023                             in_progress ^= 1 << pipe;
   3024                         }
   3025                 }
   3026             }
   3027             if (soc_timeout_check(&to)) {
   3028                 LOG_WARN(BSL_LS_SOC_COMMON,
   3029                          (BSL_META_U(unit,
   3030                                      "unit %d : EGR_HW_RESET timeout\n"), unit));
   3031                 break;
   3032             }
   3033         } while (in_progress != 0);
   3034     }
   3035 
   3036     rval = 0;
   3037     SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval));
   3038     SOC_IF_ERROR_RETURN(WRITE_DLB_ECMP_HW_RESET_CONTROLr(unit, rval));
   3039     rval = SOC_REG_INFO(unit, EGR_HW_RESET_CONTROL_1r).rst_val_lo;
   3040     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval));
   3041     rval = SOC_REG_INFO(unit, EGR_HW_RESET_CONTROL_1_COREr).rst_val_lo;
   3042     SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1_COREr(unit, rval));
   3043 
   3044     return SOC_E_NONE;
   3045 }
   3046 
   3047 
   3048 STATIC int
   3049 _soc_tomahawk3_port_mapping_init(int unit)
   3050 {
   3051     soc_info_t *si;
   3052     int port, phy_port;
   3053     /* int num_port, num_phy_port; */
   3054     /* uint32 entry[SOC_MAX_MEM_WORDS];*/
   3055     int i;
   3056     uint16 dev_id = 0;
   3057     uint8 rev_id = 0;
   3058 
   3059     /*
   3060      * 96 entries MMU_CHFC_SYSPORT_MAPPINGm.SYS_PORT
   3061      * 256 entries SYS_PORTMAPm.DEVICE_PORT_NUMBER
   3062      */
   3063 
   3064     si = &SOC_INFO(unit);
   3065     soc_cm_get_id(unit, &dev_id, &rev_id);
   3066 
   3067     /*sal_memset(&entry, 0, sizeof(entry));*/
   3068 
   3069 
   3070 
   3071 #if 0
   3072     num_port = soc_mem_index_count(unit, PORT_TABm) - 1;
   3073     num_phy_port = 136;
   3074 
   3075     /* Ingress physical to device port mapping */
   3076     /* Ingress GPP port to device port mapping */
   3077     mem = SYS_PORTMAPm;
   3078     sal_memset(&entry, 0, sizeof(sys_portmap_entry_t));
   3079     for (port = 0; port < num_port; port++) {
   3080         soc_mem_field32_set(unit, mem, &entry, DEVICE_PORT_NUMBERf, port);
   3081         SOC_IF_ERROR_RETURN
   3082             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, port, &entry));
   3083     }
   3084 
   3085     /* Ingress device port to GPP port mapping
   3086      * PORT_TAB.SRC_SYS_PORT_ID is programmed in the general port config
   3087      * init routine _bcm_fb_port_cfg_init()
   3088      */
   3089 
   3090 #endif
   3091 
   3092     if (BCM56963_DEVICE_ID == dev_id) {
   3093         const int phy_pbmp_lb_disable[] = {
   3094             13,14,15,16,17,18,19,20,25,26,27,28,29,30,31,32,45,46,47,48,
   3095             57,58,59,60,61,62,63,64,73,74,75,76,77,78,79,80,89,90,91,92,
   3096             93,94,95,96,113,114,115,116,121,122,123,124,125,126,127,128};
   3097         for (i = 0; i < COUNTOF(phy_pbmp_lb_disable); i++) {
   3098             phy_port = phy_pbmp_lb_disable[i];
   3099             port = si->port_p2l_mapping[phy_port];
   3100             if (port != -1) {
   3101                 SOC_PBMP_PORT_ADD(loopback_disable[unit],port);
   3102             }
   3103         }
   3104     }
   3105 
   3106     /* MMU portmapping from TM */
   3107     SOC_IF_ERROR_RETURN(soc_tomahawk3_mmu_port_mapping_init(unit));
   3108 
   3109     return SOC_E_NONE;
   3110 }
   3111 
   3112 extern int
   3113 (*_phy_tsce_firmware_set_helper[SOC_MAX_NUM_DEVICES])(int, int, uint8 *, int);
   3114 extern int
   3115 (*_phy_tscf_firmware_set_helper[SOC_MAX_NUM_DEVICES])(int, int, uint8 *, int);
   3116 
   3117 STATIC int
   3118 _soc_tomahawk3_tscx_firmware_set(int unit, int port, uint8 *array, int datalen)
   3119 {
   3120     soc_mem_t mem = IS_CL_PORT(unit, port) ?
   3121                     CLPORT_WC_UCMEM_DATAm : XLPORT_WC_UCMEM_DATAm;
   3122     soc_reg_t reg = IS_CL_PORT(unit, port) ?
   3123                     CLPORT_WC_UCMEM_CTRLr : XLPORT_WC_UCMEM_CTRLr;
   3124 
   3125     return soc_warpcore_firmware_set(unit, port, array, datalen, 0, mem, reg);
   3126 }
   3127 
   3128 #define TSC_REG_ADDR_TSCID_SET(_phy_reg, _phyad)    \
   3129                             ((_phy_reg) |= ((_phyad) & 0x1f) << 19)
   3130 
   3131 STATIC int
   3132 _soc_tomahawk3_mdio_addr_to_port(uint32 phy_addr)
   3133 {
   3134     int bus, offset;
   3135 
   3136     /* Must be internal MDIO address */
   3137     if ((phy_addr & 0x80) == 0) {
   3138         return 0;
   3139     }
   3140 
   3141     /*
   3142      * Internal phy address:
   3143      * bus 0 phy 1 to 24 are mapped to Physical port 1 to 24
   3144      * bus 1 phy 1 to 24 are mapped to Physical port 25 to 48
   3145      * bus 2 phy 1 to 24 are mapped to Physical port 49 to 72
   3146      * bus 3 phy 1 to 24 are mapped to Physical port 73 to 96
   3147      * bus 4 phy 1 to 24 are mapped to Physical port 97 to 120
   3148      * bus 5 phy 1 to 24 are mapped to Physical port 121 to 144
   3149      * bus 6 phy 1 to 24 are mapped to Physical port 145 to 168
   3150      * bus 7 phy 1 to 24 are mapped to Physical port 169 to 192
   3151      * bus 8 phy 1 to 24 are mapped to Physical port 193 to 216
   3152      * bus 9 phy 1 to 24 are mapped to Physical port 217 to 240
   3153      * bus 10 phy 1 to 16 are mapped to Physical port 241 to 256
   3154      * bus 11 phy 1 is mapped to Physical port 257 and
   3155      *        phy 2 is mapped to Physical port 258
   3156      */
   3157     bus = PHY_ID_BUS_NUM(phy_addr);
   3158     if (bus > 11) {
   3159         return 0;
   3160     }
   3161     switch (bus) {
   3162     case 0: offset = 0;
   3163         break;
   3164     case 1: offset = 24;
   3165         break;
   3166     case 2: offset = 48;
   3167         break;
   3168     case 3: offset = 72;
   3169         break;
   3170     case 4: offset = 96;
   3171         break;
   3172     case 5: offset = 120;
   3173         break;
   3174     case 6: offset = 144;
   3175         break;
   3176     case 7: offset = 168;
   3177         break;
   3178     case 8: offset = 192;
   3179         break;
   3180     case 9: offset = 216;
   3181         break;
   3182     case 10: offset = 240;
   3183         break;
   3184     case 11: offset = 256;
   3185         /* Management ports take up the first 2 ports on the 4x10G in TH3 */
   3186         if ((phy_addr & 0x1f) > 2) {
   3187             return 0;
   3188         }
   3189         break;
   3190     default:
   3191         return 0;
   3192     }
   3193 
   3194     return (phy_addr & 0x1f) + offset;
   3195 }
   3196 
   3197 STATIC int
   3198 _soc_tomahawk3_tscx_reg_read(int unit, uint32 phy_addr,
   3199                             uint32 phy_reg, uint32 *phy_data)
   3200 {
   3201     int rv, blk, port;
   3202     int phy_port = _soc_tomahawk3_mdio_addr_to_port(phy_addr);
   3203 
   3204     port = SOC_INFO(unit).port_p2l_mapping[phy_port];
   3205     blk = SOC_PORT_BLOCK(unit, phy_port);
   3206     LOG_INFO(BSL_LS_SOC_MII,
   3207              (BSL_META_U(unit,
   3208                          "soc_tomahawk3_tscx_reg_read[%d]: %d/%d/%d/%d\n"),
   3209               unit, phy_addr, phy_port, port, blk));
   3210     rv = soc_sbus_tsc_reg_read(unit, port, blk, phy_addr,
   3211                                phy_reg, phy_data);
   3212     return rv;
   3213 }
   3214 
   3215 STATIC int
   3216 _soc_tomahawk3_tscx_reg_write(int unit, uint32 phy_addr,
   3217                              uint32 phy_reg, uint32 phy_data)
   3218 {
   3219     int rv, blk, port;
   3220     int phy_port = _soc_tomahawk3_mdio_addr_to_port(phy_addr);
   3221 
   3222     port = SOC_INFO(unit).port_p2l_mapping[phy_port];
   3223     blk = SOC_PORT_BLOCK(unit, phy_port);
   3224     LOG_INFO(BSL_LS_SOC_MII,
   3225              (BSL_META_U(unit,
   3226                          "soc_tomahawk3_tscx_reg_write[%d]: %d/%d/%d/%d\n"),
   3227               unit, phy_addr, phy_port, port, blk));
   3228     rv = soc_sbus_tsc_reg_write(unit, port, blk, phy_addr,
   3229                                 phy_reg, phy_data);
   3230     return rv;
   3231 }
   3232 
   3233 #ifdef BCM_CMICX_SUPPORT 
   3234 STATIC int
   3235 _soc_th3_ledup_init(int unit)
   3236 {
   3237     soc_info_t *si = &SOC_INFO(unit);
   3238     int freq;
   3239     uint32 rval, clk_half_period, refresh_period;
   3240 
   3241     /* freq in KHz */
   3242     freq = (si->frequency) * 1000;
   3243 
   3244     /* For LED refresh period = 33 ms (about 30Hz)  */
   3245 
   3246     /* refresh period
   3247        = (required refresh period in sec)*(switch clock frequency in Hz)
   3248      */
   3249     refresh_period = (freq * 33);
   3250 
   3251     rval = 0;
   3252     soc_reg_field_set(unit, U0_LED_REFRESH_CTRLr, &rval,
   3253                       REFRESH_CYCLE_PERIODf, refresh_period);
   3254 
   3255     SOC_IF_ERROR_RETURN(WRITE_U0_LED_REFRESH_CTRLr(unit, rval));
   3256 
   3257     /* For LED clock period */
   3258     /* LEDCLK_HALF_PERIOD
   3259        = [(required LED clock period in sec)/2]*(M0SS clock frequency in Hz)
   3260 
   3261        Where M0SS freqency is 858MHz and
   3262        Typical LED clock period is 200ns(5MHz) = 2*10^-7
   3263     */
   3264     freq = 858 * 1000000;
   3265     clk_half_period = (freq + 2500000) / 5000000;
   3266     clk_half_period = clk_half_period / 2;
   3267     
   3268     rval = 0;
   3269     soc_reg_field_set(unit, U0_LED_CLK_DIV_CTRLr, &rval, 
   3270                       LEDCLK_HALF_PERIODf, clk_half_period);      
   3271 
   3272     SOC_IF_ERROR_RETURN(WRITE_U0_LED_CLK_DIV_CTRLr(unit, rval)); 
   3273 
   3274 
   3275     SOC_IF_ERROR_RETURN(READ_U0_LED_ACCU_CTRLr(unit, &rval)); 
   3276     soc_reg_field_set(unit, U0_LED_ACCU_CTRLr, &rval, 
   3277                       LAST_PORTf, 0);
   3278     SOC_IF_ERROR_RETURN(WRITE_U0_LED_ACCU_CTRLr(unit, rval));
   3279  
   3280     /* To initialize M0s for LED or Firmware Link Scan*/ 
   3281     if (soc_feature(unit, soc_feature_cmicx) && !(SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM)) {
   3282         SOC_IF_ERROR_RETURN(soc_iproc_m0_init(unit));
   3283     }
   3284 
   3285     return SOC_E_NONE;
   3286 }
   3287 #endif /* BCM_CMICX_SUPPORT */    
   3288 
   3289 STATIC int
   3290 _soc_tomahawk3_management_port_init (int unit) {
   3291 
   3292     int port, fval;
   3293     uint32 rval;
   3294     soc_info_t *si=&SOC_INFO(unit);
   3295     
   3296     SOC_PBMP_ITER(si->management_pbm, port) {
   3297         /* Assert XLPORT soft reset */
   3298         rval = 0;
   3299         if (si->port_p2l_mapping[257] != -1) { /* management port 0 */
   3300             soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, PORT0f, 1);
   3301         }
   3302         if (si->port_p2l_mapping[258] != -1) { /* management port 1 */
   3303             soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, PORT2f, 1);
   3304         }
   3305         SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, rval));
   3306 
   3307         /* Set port mode based upon lanes config */
   3308         rval = 0;
   3309         /* Note - this is a special h/w requirement to ONLY use dual lane mode */
   3310         fval = 3;
   3311         soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf,
   3312                           fval);
   3313         soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf,
   3314                           fval);
   3315         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, port, rval));
   3316 
   3317         /* De-assert XLPORT soft reset */
   3318         SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, 0));
   3319 
   3320         /* Enable XLPORT */
   3321         rval = 0;
   3322         if (si->port_p2l_mapping[257] != -1) { /* management port 0 */
   3323             soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, PORT0f, 1);
   3324         }
   3325         if (si->port_p2l_mapping[258] != -1) { /* management port 1 */
   3326             soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, PORT2f, 1);
   3327         }
   3328         SOC_IF_ERROR_RETURN(WRITE_XLPORT_ENABLE_REGr(unit, port, rval));
   3329 
   3330         rval = 0;
   3331         soc_reg_field_set(unit, XLPORT_FLOW_CONTROL_CONFIGr, &rval,
   3332                           MERGE_MODE_ENf, 1);
   3333         SOC_IF_ERROR_RETURN
   3334             (WRITE_XLPORT_FLOW_CONTROL_CONFIGr(unit, port, rval));
   3335     }
   3336 
   3337     return SOC_E_NONE;
   3338 }
   3339 
   3340 /*
   3341  * Function:
   3342  *      _soc_tomahawk3_l2mcast_size_set
   3343  * Purpose:
   3344  *      This function programs L2 multicast table size in hardware and sets
   3345  *      up soc_control structure's mc_size field value
   3346  * Parameters:
   3347  *      unit    - (IN) Unit number
   3348  *      mc_size - (IN) Size of L2 multicast table. Cannot exceed hardware
   3349  *                L2 multicast table size
   3350  * Returns:
   3351  *      Nothing
   3352  * Note:
   3353  *      TH3 has separate L2 and L3 multicast tables (as in TD3). Hardware
   3354  *      may not use value programmed in MC_CONTROL_5r's field.
   3355  */
   3356 STATIC int
   3357 _soc_tomahawk3_l2mcast_size_set(int unit, int mc_size)
   3358 {
   3359     uint32	mc_ctrl;
   3360     soc_control_t       *soc = SOC_CONTROL(unit);
   3361     int l2mc_table_size = soc_mem_index_count(unit, L2MCm);
   3362 
   3363     if (mc_size > l2mc_table_size) {
   3364         return SOC_E_PARAM;
   3365     }
   3366 
   3367     SOC_IF_ERROR_RETURN(READ_MC_CONTROL_5r(unit, &mc_ctrl));
   3368     soc_reg_field_set(unit, MC_CONTROL_5r, &mc_ctrl,
   3369                       SHARED_TABLE_L2MC_SIZEf, mc_size);
   3370     SOC_IF_ERROR_RETURN(WRITE_MC_CONTROL_5r(unit, mc_ctrl));
   3371 
   3372     soc->mcast_size = mc_size;
   3373 
   3374     return SOC_E_NONE;
   3375 }
   3376 
   3377 /*
   3378  * Function:
   3379  *      _soc_tomahawk3_ipmc_size_set
   3380  * Purpose:
   3381  *      This function programs IPMC table size in hardware and sets
   3382  *      up soc_control structure's mc_size field value
   3383  * Parameters:
   3384  *      unit    - (IN) Unit number
   3385  *      mc_size - (IN) Size of IPMC table. Cannot exceed hardware
   3386  *                IPMC size
   3387  * Returns:
   3388  *      Nothing
   3389  * Note:
   3390  *      TH3 has separate L2 and L3 multicast tables (as in TD3). Hardware
   3391  *      may not use value programmed in MC_CONTROL_5r's field.
   3392  */
   3393 STATIC int
   3394 _soc_tomahawk3_ipmc_size_set(int unit, int mc_size)
   3395 {
   3396     uint32	mc_ctrl;
   3397     soc_control_t       *soc = SOC_CONTROL(unit);
   3398     int ipmc_table_size = soc_mem_index_count(unit, L3_IPMCm);
   3399 
   3400     if (mc_size > ipmc_table_size) {
   3401         return SOC_E_PARAM;
   3402     }
   3403 
   3404     SOC_IF_ERROR_RETURN(READ_MC_CONTROL_5r(unit, &mc_ctrl));
   3405     soc_reg_field_set(unit, MC_CONTROL_5r, &mc_ctrl,
   3406                       SHARED_TABLE_IPMC_SIZEf, mc_size);
   3407     SOC_IF_ERROR_RETURN(WRITE_MC_CONTROL_5r(unit, mc_ctrl));
   3408 
   3409     soc->ipmc_size = mc_size;
   3410 
   3411     return SOC_E_NONE;
   3412 }
   3413 
   3414 STATIC int
   3415 _soc_tomahawk3_ipep_default_init (int unit)
   3416 {
   3417     uint32 rval;
   3418     int index, port;
   3419     int count, sub_sel, offset;
   3420     uint32 entry[SOC_MAX_MEM_WORDS];
   3421     int ecmp_mode = 0;
   3422     soc_pbmp_t pbmp;
   3423     uint64 rval64;
   3424     static int rtag7_field_width[] = { 16, 16, 4, 16, 8, 8, 16, 16 };
   3425 
   3426     
   3427     SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, &rval64));
   3428     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   3429                           L3SRC_HIT_ENABLEf, 1);
   3430     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   3431                           L2DST_HIT_ENABLEf, 1);
   3432     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   3433                           APPLY_EGR_MASK_ON_L2f, 1);
   3434     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   3435                           APPLY_EGR_MASK_ON_L3f, 1);
   3436     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   3437                           ARP_RARP_TO_FPf, 0x3); /* enable both ARP & RARP */
   3438     soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   3439                           ARP_VALIDATION_ENf, 1);
   3440     if (soc_feature(unit, soc_feature_port_lag_failover)) {
   3441         soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   3442                               IGNORE_HG_HDR_LAG_FAILOVERf, 0);
   3443     } else {
   3444         soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64,
   3445                               IGNORE_HG_HDR_LAG_FAILOVERf, 1);
   3446     }
   3447     SOC_IF_ERROR_RETURN(WRITE_ING_CONFIG_64r(unit, rval64));
   3448 
   3449     rval = 0;
   3450     /* Enable pri/cfi remarking on egress ports. */
   3451     soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, REMARK_OUTER_DOT1Pf,
   3452                       1);
   3453     PBMP_ALL_ITER(unit, port) {
   3454         SOC_IF_ERROR_RETURN(WRITE_EGR_VLAN_CONTROL_1r(unit, port, rval));
   3455     }
   3456 
   3457     SOC_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   3458     SOC_PBMP_REMOVE(pbmp, PBMP_LB(unit));
   3459     SOC_IF_ERROR_RETURN(soc_mem_read(unit, ING_EN_EFILTER_BITMAPm,
   3460                                      MEM_BLOCK_ANY, 0, &entry));
   3461     soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm, &entry, BITMAPf,
   3462                            &pbmp);
   3463     SOC_IF_ERROR_RETURN(soc_mem_write(unit, ING_EN_EFILTER_BITMAPm,
   3464                                       MEM_BLOCK_ANY, 0, &entry));
   3465 
   3466     
   3467     /* Multicast range initialization */
   3468     SOC_IF_ERROR_RETURN
   3469         (_soc_tomahawk3_l2mcast_size_set(unit, soc_property_get(unit,
   3470              spn_MULTICAST_L2_RANGE, soc_mem_index_count(unit, L2MCm))));
   3471     SOC_IF_ERROR_RETURN
   3472         (_soc_tomahawk3_ipmc_size_set(unit, soc_property_get(unit,
   3473              spn_MULTICAST_L3_RANGE, soc_mem_index_count(unit, L3_IPMCm))));
   3474 
   3475     /* Check if Hierarchical ECMP mode is set */
   3476     rval = 0;
   3477     SOC_IF_ERROR_RETURN(READ_ECMP_CONFIGr(unit, &rval));
   3478 
   3479     if (soc_property_get(unit, spn_L3_ECMP_LEVELS, 1) == 2) {
   3480         /* HW encoding for Hierarchical ECMP mode is 1.*/
   3481         ecmp_mode = 1;
   3482         soc_reg_field_set(unit, ECMP_CONFIGr, &rval, ECMP_MODEf, ecmp_mode);
   3483         SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIGr(unit, rval));
   3484     }
   3485     /* Populate and enable RTAG7 Macro flow offset table */
   3486     if (soc_mem_is_valid(unit, RTAG7_FLOW_BASED_HASHm)) {
   3487         count = soc_mem_index_max(unit, RTAG7_FLOW_BASED_HASHm);
   3488         sal_memset(entry, 0, sizeof(rtag7_flow_based_hash_entry_t));
   3489         for (index = 0; index < count; ) {
   3490             for (sub_sel = 0; sub_sel < 8 && index < count; sub_sel++) {
   3491                 for (offset = 0;
   3492                      offset < rtag7_field_width[sub_sel] && index < count;
   3493                      offset++) {
   3494                     if (ecmp_mode == 1) {
   3495                         soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry,
   3496                                             SUB_SEL_ECMP_LEVEL2f, sub_sel);
   3497                         soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry,
   3498                                             OFFSET_ECMP_LEVEL2f, offset);
   3499                     }
   3500                     soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry,
   3501                                         SUB_SEL_ECMPf, sub_sel);
   3502                     soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry,
   3503                                         OFFSET_ECMPf, offset);
   3504                     SOC_IF_ERROR_RETURN
   3505                         (soc_mem_write(unit, RTAG7_FLOW_BASED_HASHm,
   3506                                        MEM_BLOCK_ANY, index, &entry));
   3507                     index++;
   3508                 }
   3509             }
   3510         }
   3511         rval = 0;
   3512         soc_reg_field_set(unit, RTAG7_HASH_SELr, &rval, USE_FLOW_SEL_ECMPf, 1);
   3513 
   3514         SOC_IF_ERROR_RETURN(WRITE_RTAG7_HASH_SELr(unit, rval));
   3515     }
   3516     return SOC_E_NONE;
   3517 }
   3518 
   3519 STATIC int 
   3520 _soc_tomahawk3_cpu_lb_portbitmap_set (int unit)
   3521 {
   3522     uint32 entry[SOC_MAX_MEM_WORDS];
   3523 
   3524     sal_memset(entry, 0, sizeof(cpu_pbm_entry_t));
   3525     soc_mem_pbmp_field_set(unit, CPU_PBMm, entry, BITMAPf, &PBMP_CMIC(unit));
   3526     SOC_IF_ERROR_RETURN
   3527         (soc_mem_write(unit, CPU_PBMm, MEM_BLOCK_ALL, 0, entry));
   3528 
   3529     return SOC_E_NONE;
   3530 }
   3531 
   3532 int
   3533 soc_tomahawk3_clear_mmu_counters(int unit) {
   3534 /* Refer to SBus BASE TYPE info structure in REGSFILE */
   3535 #define SOC_MMU_BASE_TYPE_IPORT 0
   3536 #define SOC_MMU_BASE_TYPE_EPORT 1
   3537 #define SOC_MMU_BASE_TYPE_IPIPE 2
   3538 #define SOC_MMU_BASE_TYPE_EPIPE 3
   3539 #define SOC_MMU_BASE_TYPE_CHIP  4
   3540 #define SOC_MMU_BASE_TYPE_ITM   5
   3541     soc_info_t *si;
   3542     int i, j, use_base_type_views, base_type, index, num_views;
   3543     uint32 entry[SOC_MAX_MEM_WORDS], valid_views_bmp = 0;
   3544     soc_mem_t mem;
   3545     static const struct {
   3546         soc_mem_t mem; /* base view */
   3547         int use_base_type_views; /* 1 means use itm/sc/etc views */
   3548         int index; /* -1 means clear entire mem */
   3549         int val; /* clear with assigned value */
   3550     } mem_list[] = {
   3551         { MMU_THDO_QUEUE_DROP_COUNTm, 1, -1, 0 },
   3552         { MMU_THDO_PORT_DROP_COUNT_MCm, 1, -1, 0 },
   3553         { MMU_THDO_PORT_DROP_COUNT_UCm, 1, -1, 0 },
   3554         { MMU_THDO_COUNTER_QUEUEm, 1, -1, 0 },
   3555         { MMU_THDI_PORT_PG_MIN_COUNTERm, 1, -1, 0 },
   3556         { MMU_THDI_PORT_PG_SHARED_COUNTERm, 1, -1, 0 },
   3557         { MMU_THDI_PORT_PG_HDRM_COUNTERm, 1, -1, 0 },
   3558         { MMU_THDI_PORTSP_COUNTERm, 1, -1, 0 },
   3559         { MMU_THDO_SRC_PORT_DROP_COUNTm, 1, -1, 0 },
   3560         { INVALIDm, 0, -1, 0}
   3561     };
   3562 
   3563     si = &SOC_INFO(unit);
   3564 
   3565     /* clear memories */
   3566     for (i = 0; mem_list[i].mem != INVALIDm; i++) {
   3567         mem = mem_list[i].mem;
   3568         index = mem_list[i].index;
   3569         use_base_type_views = mem_list[i].use_base_type_views;
   3570         if (use_base_type_views) {
   3571             base_type = soc_tomahawk3_mem_basetype_get(unit, mem);
   3572             switch (base_type) {
   3573             case SOC_MMU_BASE_TYPE_ITM:
   3574                 num_views = NUM_ITM(unit);
   3575                 valid_views_bmp = si->itm_map;
   3576                 break;
   3577             case SOC_MMU_BASE_TYPE_IPIPE:
   3578             case SOC_MMU_BASE_TYPE_EPIPE:
   3579                 num_views = NUM_PIPE(unit);
   3580                 soc_tomahawk3_pipe_map_get(unit, &valid_views_bmp);
   3581                 break;
   3582             default:
   3583                 num_views = -1; /* not supported */
   3584                 break;
   3585             }
   3586             if (num_views < 0) {
   3587                 LOG_ERROR(BSL_LS_SOC_COMMON,
   3588                           (BSL_META_U(unit,
   3589                                       "mmu_mem %s, base_type %d will not be"
   3590                                       "cleared \n"),
   3591                            SOC_MEM_NAME(unit,mem), base_type));
   3592                 continue;
   3593             }
   3594         } else {
   3595             num_views = 0; /* dont_care */
   3596         }
   3597 
   3598         sal_memset(entry, mem_list[i].val,
   3599                    soc_mem_entry_words(unit, mem) * sizeof(uint32));
   3600         if (use_base_type_views) {
   3601             for (j = 0; j < num_views; j++) {
   3602                 if((valid_views_bmp & (1 << j)) == 0) {
   3603                     continue;
   3604                 }
   3605                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3606                             (BSL_META_U(unit,
   3607                                         "mmu_mem %s, index %d will be "
   3608                                         "cleared \n"),
   3609                             SOC_MEM_NAME(unit, SOC_MEM_UNIQUE_ACC(unit, mem)[j]),
   3610                             index));
   3611                 if (index >= 0) {
   3612                     SOC_IF_ERROR_RETURN
   3613                         (soc_mem_write(unit,
   3614                                        SOC_MEM_UNIQUE_ACC(unit, mem)[j],
   3615                                        MEM_BLOCK_ALL, index, entry));
   3616                 } else {
   3617                     SOC_IF_ERROR_RETURN
   3618                         (soc_mem_clear(unit,
   3619                                        SOC_MEM_UNIQUE_ACC(unit, mem)[j],
   3620                                        COPYNO_ALL, TRUE));
   3621                 }
   3622             }
   3623         } else {
   3624             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3625                         (BSL_META_U(unit,
   3626                                     "mmu_mem %s, index %d will be "
   3627                                     "cleared \n"),
   3628                         SOC_MEM_NAME(unit, mem), index));
   3629             if (index >= 0) {
   3630                 SOC_IF_ERROR_RETURN
   3631                     (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index,
   3632                                    entry));
   3633             } else {
   3634                 SOC_IF_ERROR_RETURN
   3635                     (soc_mem_clear(unit, mem, COPYNO_ALL, TRUE));
   3636             }
   3637         }
   3638     }
   3639     return SOC_E_NONE;
   3640 }
   3641 
   3642 STATIC int 
   3643 _soc_tomahawk3_port_mib_reset (int unit) 
   3644 {
   3645     uint32 rval=0;
   3646     int lane, lport, port, phy_port_base, block_info_idx;
   3647 
   3648     soc_info_t *si = &SOC_INFO(unit);
   3649 
   3650     /* Reset CDMIB counters */
   3651     rval = 0;
   3652     soc_reg_field_set(unit, CDMAC_MIB_COUNTER_CTRLr, &rval, CNT_CLEARf, 1);
   3653     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CDPORT) {
   3654         port = SOC_BLOCK_PORT(unit, block_info_idx);
   3655         phy_port_base = SOC_TH3_PORT_BLOCK_BASE_PORT(port);
   3656         for (lane = 0; lane < _TH3_PORTS_PER_PBLK; lane++) {
   3657             lport = si->port_p2l_mapping[phy_port_base + lane];
   3658             if (lport != -1) {
   3659                 SOC_IF_ERROR_RETURN(WRITE_CDMAC_MIB_COUNTER_CTRLr(unit, lport, rval));
   3660             }
   3661         }
   3662     }
   3663     sal_usleep(1);
   3664     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CDPORT) {
   3665         port = SOC_BLOCK_PORT(unit, block_info_idx);
   3666         phy_port_base = SOC_TH3_PORT_BLOCK_BASE_PORT(port);
   3667         for (lane = 0; lane < _TH3_PORTS_PER_PBLK; lane++) {
   3668             lport = si->port_p2l_mapping[phy_port_base + lane];
   3669             if (lport != -1) {
   3670                 SOC_IF_ERROR_RETURN(WRITE_CDMAC_MIB_COUNTER_CTRLr(unit, lport, 0));
   3671             }
   3672         }
   3673     }
   3674 
   3675     /* Reset XLMIB counters */
   3676     rval = 0;
   3677     SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_XLPORT) {
   3678         port = SOC_BLOCK_PORT(unit, block_info_idx);
   3679         soc_reg_field_set(unit, XLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf);
   3680         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, rval));
   3681         SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, 0));
   3682     }
   3683     return SOC_E_NONE;
   3684 }
   3685 
   3686 STATIC int
   3687 _soc_tomahawk3_hg_lb_port_type_set (int unit)
   3688 {
   3689     uint32 entry[SOC_MAX_MEM_WORDS];
   3690     soc_info_t *si = &SOC_INFO(unit);
   3691     int port;
   3692 
   3693     sal_memset(entry, 0, sizeof(egr_ing_port_entry_t));
   3694     soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 1);
   3695     PBMP_HG_ITER(unit, port) {
   3696         SOC_IF_ERROR_RETURN
   3697             (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry));
   3698     }
   3699     SOC_IF_ERROR_RETURN
   3700         (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, si->cpu_hg_index,
   3701                        entry));
   3702     soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 2);
   3703     PBMP_LB_ITER(unit, port) {
   3704         SOC_IF_ERROR_RETURN
   3705             (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry));
   3706     }
   3707     return SOC_E_NONE;
   3708 }
   3709 
   3710 STATIC int
   3711 _soc_tomahawk3_cmic_mdio_freq_config (int unit)
   3712 {
   3713     int int_divisor, ext_divisor, delay;
   3714     /* spn_RATE_EXT_MDIO_DIVIDEND and spn_RATE_INT_MDIO_DIVIDEND are
   3715      * NOT applicable to TH3.
   3716      */
   3717 
   3718     /* MDIO Clock Frquency for TH3 is 250 MHz
   3719      * Set external MDIO freq to around 5 MHz
   3720      * Hence divisor is set to 50
   3721      */
   3722 
   3723     ext_divisor = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVISOR, 50);
   3724 
   3725     /*
   3726      * Set internal MDIO freq to around 10 MHz
   3727      * Valid range is from 2.5MHz to 20MHz
   3728      * Hence divisor is set to 25
   3729      */
   3730     int_divisor = soc_property_get(unit, spn_RATE_INT_MDIO_DIVISOR, 25);
   3731 
   3732     delay = soc_property_get(unit, spn_MDIO_OUTPUT_DELAY, -1);
   3733     if (delay < 0  || delay > 255) {
   3734         /* valid range for delay is 0-255
   3735          * if outside this range, skip configuring delay
   3736          */
   3737         delay = -1;
   3738     }
   3739 
   3740     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3741               (BSL_META_U(unit,
   3742               "Config MIIM rings with int divisor %d, ext divisor %d, delay %d\n"),
   3743               int_divisor, ext_divisor, delay));
   3744 
   3745     soc_cmicx_miim_divider_set_all(unit, int_divisor, ext_divisor, delay);
   3746 
   3747     return SOC_E_NONE;
   3748 }
   3749 
   3750 /*
   3751  * Function:
   3752  *      soc_th3_speed_class_validate
   3753  * Purpose:
   3754  *      Check speed classes and ensure 4 speed max for device
   3755  * Parameters:
   3756  *      unit        - (IN) Unit number.
   3757  * Returns:
   3758  *      SOC_E_XXX
   3759  * Note:
   3760  *      This function is called at early stage of initialization for
   3761  *      port configuration check.
   3762  */
   3763 int
   3764 soc_th3_speed_class_validate(int unit)
   3765 {
   3766     soc_info_t *si = &SOC_INFO(unit);
   3767     int port, speed;
   3768     uint32 speed_mask, count;
   3769     int speed_400 = 0, speed_200 = 0;
   3770 
   3771     speed_mask = 0;
   3772     PBMP_PORT_ITER(unit, port) {
   3773         if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port) ||
   3774             IS_MANAGEMENT_PORT(unit, port) || IS_CPU_PORT(unit, port) ||
   3775             IS_LB_PORT(unit, port)) {
   3776             continue;
   3777         }
   3778 
   3779         /* No HG, so just take speed rather than converting from HG to eth */
   3780         speed = si->port_speed_max[port];
   3781 
   3782         /* 400G and 200G aren't part of SOC_PA_SPEED, so need to be counted
   3783          * differently */
   3784         if (speed == 400000) {
   3785             speed_400 = 1;
   3786         } else if (speed == 200000) {
   3787             speed_200 = 1;
   3788         } else {
   3789             speed_mask |= SOC_PA_SPEED(speed);
   3790         }
   3791     }
   3792 
   3793     count = _shr_popcount(speed_mask);
   3794 
   3795     /* Add 400G and 200G if they exist */
   3796     count += speed_400;
   3797     count += speed_200;
   3798 
   3799     if (count > 7) {
   3800         LOG_ERROR(BSL_LS_BCM_COMMON,
   3801                   (BSL_META_U(unit,
   3802                               "No port configurations with more than 7 port "
   3803                               "speed classes are supported.\n")));
   3804         return SOC_E_CONFIG;
   3805     }
   3806 
   3807     return SOC_E_NONE;
   3808 }
   3809 
   3810 STATIC void
   3811 _soc_tomahawk3_ser_hw_clear(int unit)
   3812 {
   3813     int i;
   3814     uint32 entry[SOC_MAX_MEM_WORDS];
   3815     uint32 data = 0;
   3816     soc_reg_t ep_ser_fifo[] = {
   3817         EGR_SER_FIFO_CTRL_PIPE0r,
   3818         EGR_SER_FIFO_CTRL_PIPE1r,
   3819         EGR_SER_FIFO_CTRL_PIPE2r,
   3820         EGR_SER_FIFO_CTRL_PIPE3r,
   3821         EGR_SER_FIFO_CTRL_PIPE4r,
   3822         EGR_SER_FIFO_CTRL_PIPE5r,
   3823         EGR_SER_FIFO_CTRL_PIPE6r,
   3824         EGR_SER_FIFO_CTRL_PIPE7r
   3825     };
   3826     soc_reg_t ep_ser_fifo_2[] = {
   3827         EGR_SER_FIFO_CTRL_2_PIPE0r,
   3828         EGR_SER_FIFO_CTRL_2_PIPE1r,
   3829         EGR_SER_FIFO_CTRL_2_PIPE2r,
   3830         EGR_SER_FIFO_CTRL_2_PIPE3r,
   3831         EGR_SER_FIFO_CTRL_2_PIPE4r,
   3832         EGR_SER_FIFO_CTRL_2_PIPE5r,
   3833         EGR_SER_FIFO_CTRL_2_PIPE6r,
   3834         EGR_SER_FIFO_CTRL_2_PIPE7r
   3835     };
   3836     soc_mem_t mmu_eb_fifo[] = {
   3837         MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE0m,
   3838         MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE1m,
   3839         MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE2m,
   3840         MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE3m,
   3841         MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE4m,
   3842         MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE5m,
   3843         MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE6m,
   3844         MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE7m
   3845     };
   3846     uint32 pipe_map;
   3847 
   3848     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   3849     /* clear mmu eb ser fifo */
   3850     for (i = 0; i < NUM_EB(unit); i++) {
   3851         (void)soc_mem_pop(unit, mmu_eb_fifo[i], MEM_BLOCK_ANY, entry);
   3852     }
   3853 
   3854     /* clear EP ser fifo */
   3855     for (i = 0; i < NUM_PIPE(unit); i++) {
   3856         if (!(pipe_map & (1 << i))) {
   3857             continue;
   3858         }
   3859         (void)soc_reg_field32_modify(unit, ep_ser_fifo[i], REG_PORT_ANY,
   3860                                FIFO_RESETf, 1);
   3861         (void)soc_reg_field32_modify(unit, ep_ser_fifo_2[i], REG_PORT_ANY,
   3862                                FIFO_RESETf, 1);
   3863         (void)soc_reg_field32_modify(unit, ep_ser_fifo[i], REG_PORT_ANY,
   3864                                FIFO_RESETf, 0);
   3865         (void)soc_reg_field32_modify(unit, ep_ser_fifo_2[i], REG_PORT_ANY,
   3866                                FIFO_RESETf, 0);
   3867     }
   3868 
   3869     /* clear MEM_PAR_ERR_INT_STAT bit in mmu EB interrupt status register,
   3870      * write 1 to clear
   3871      */
   3872     for (i = 0; i < NUM_PIPE(unit); i ++) {
   3873         if (!(pipe_map & (1 << i))) {
   3874             continue;
   3875         }
   3876         (void)soc_tomahawk3_eb_reg32_get(unit, MMU_EBCFG_CPU_INT_STATr, i, i, 0, &data);
   3877         if(soc_reg_field_get(unit, MMU_EBCFG_CPU_INT_STATr, data, MEM_PAR_ERR_INT_STATf)) {
   3878             soc_tomahawk3_eb_reg32_set(unit, MMU_EBCFG_CPU_INT_STATr, i, i, 0, 0x1);
   3879         }
   3880         soc_tomahawk3_eb_reg32_set(unit, MMU_EBCFG_MEM_FAIL_INT_CTRr, i, i, 0, 0x0);
   3881     }
   3882     /* clear EBCFGx_INT_STAT bit in GLB interrupt status register, write 1 to clear */
   3883     (void)soc_reg32_set(unit, MMU_GLBCFG_CPU_INT_STATr, REG_PORT_ANY, 0, 0x1fe);
   3884 
   3885 }
   3886 
   3887 /*
   3888  * Function:
   3889  *      soc_th3_process_pm_intr
   3890  * Description:
   3891  *      Tomahawk3 specific DPC function to service PM interrupts
   3892  * Parameters:
   3893  *      unit_vp       - Device number
   3894  *      d1            - IRQ4 mask
   3895  *      d2            - IRQ4 number (to distinguish between
   3896  *                      different types of interrupts).
   3897  */
   3898 static void
   3899 soc_th3_process_pm_intr(void *unit_vp, void *d1,
   3900                              void *d2, void *d3, void *d4)
   3901 {
   3902 
   3903     int unit = PTR_TO_INT(unit_vp);
   3904     int cmic_bit_num = PTR_TO_INT(d1);
   3905     int cmic_reg_type = PTR_TO_INT(d2);
   3906     int pm_id = -1; /* invalid id */
   3907     int rv = SOC_E_NONE;
   3908     portmod_ecc_intr_info_t ecc_intr_info;
   3909 
   3910     /*
   3911      * Get the SW Port Macro Id from the hw
   3912      * Port Macro Id(mapped to core num)
   3913      */
   3914     rv = portmod_core_pm_id_get(unit, cmic_bit_num - 1, &pm_id);
   3915 
   3916     if (rv != SOC_E_NONE) {
   3917         LOG_ERROR(BSL_LS_SOC_COMMON,
   3918                   (BSL_META_U(unit, "soc_th3_process_pm_intr sw PM id for "
   3919                                     "hw PM Id - %d not found!!\n"
   3920                                     "Disabling unhandled interrupt(s)"),
   3921                                     (cmic_bit_num - 1)));
   3922         /* Disable the specific PM interrupt */
   3923         (void) soc_ser_top_intr_reg_enable(unit, cmic_reg_type,
   3924                                            (cmic_bit_num - 1), 0);
   3925         return;
   3926     }
   3927 
   3928     sal_memset(&ecc_intr_info, 0, sizeof(portmod_ecc_intr_info_t));
   3929 
   3930     /* Process interrupts for the specific port Macro */
   3931     rv = portmod_pm_interrupt_process(unit, pm_id, &ecc_intr_info);
   3932 
   3933     if (rv != SOC_E_NONE) {
   3934         LOG_ERROR(BSL_LS_SOC_COMMON,
   3935                   (BSL_META_U(unit, "soc_th3_process_pm_intr - pm_id(%d)"
   3936                                     "Disabling unhandled interrupt(s)"), pm_id));
   3937         /* Disable the specific PM interrupt */
   3938         (void) soc_ser_top_intr_reg_enable(unit, cmic_reg_type,
   3939                                            (cmic_bit_num - 1), 0);
   3940         return;
   3941     }
   3942 
   3943     /* Report ECC errors */
   3944     if (ecc_intr_info.ecc_num_bits_err != PORTMOD_PM_ECC_NO_ERR) {
   3945 
   3946         soc_event_generate(unit, SOC_SWITCH_EVENT_DATA_ERROR_PARITY,
   3947                            SOC_SWITCH_EVENT_DATA_ERROR_ECC, 0, 0);
   3948 
   3949         if (ecc_intr_info.ecc_num_bits_err & PORTMOD_PM_ECC_1B_ERR) {
   3950 
   3951             soc_event_generate(unit, SOC_SWITCH_EVENT_DATA_ERROR_PARITY,
   3952                            SOC_SWITCH_EVENT_DATA_ERROR_AUTO_CORRECTED, 0, 0);
   3953 
   3954             LOG_ERROR(BSL_LS_SOC_COMMON,
   3955                       (BSL_META_U(unit,
   3956                                  "\n%s - \n\r"
   3957                                  "single-bit ECC error on port %s\n"),
   3958                                  ecc_intr_info.mem_str,
   3959                                  SOC_PORT_NAME(unit, ecc_intr_info.port)));
   3960 
   3961         } else if (ecc_intr_info.ecc_num_bits_err & PORTMOD_PM_ECC_2B_ERR) {
   3962 
   3963             soc_event_generate(unit, SOC_SWITCH_EVENT_DATA_ERROR_PARITY,
   3964                            SOC_SWITCH_EVENT_DATA_ERROR_UNCORRECTABLE, 0, 0);
   3965 
   3966             LOG_ERROR(BSL_LS_SOC_COMMON,
   3967                       (BSL_META_U(unit,
   3968                                  "\n%s - \n\r"
   3969                                  "double-bit ECC error on port %s\n"),
   3970                                  ecc_intr_info.mem_str,
   3971                                  SOC_PORT_NAME(unit, ecc_intr_info.port)));
   3972 
   3973         } else if (ecc_intr_info.ecc_num_bits_err & PORTMOD_PM_ECC_MULTIB_ERR) {
   3974 
   3975             soc_event_generate(unit, SOC_SWITCH_EVENT_DATA_ERROR_PARITY,
   3976                            SOC_SWITCH_EVENT_DATA_ERROR_UNCORRECTABLE, 0, 0);
   3977 
   3978             LOG_ERROR(BSL_LS_SOC_COMMON,
   3979                       (BSL_META_U(unit,
   3980                                  "\n%s - \n\r"
   3981                                  "multi-bit ECC error on port %s\n"),
   3982                                  ecc_intr_info.mem_str,
   3983                                  SOC_PORT_NAME(unit, ecc_intr_info.port)));
   3984 
   3985         } else {
   3986             LOG_ERROR(BSL_LS_SOC_COMMON,
   3987                        (BSL_META_U(unit, "ECC interrupt info\n"
   3988                      "m - %s, ecc_num_bits - %d, addr %x - error - %s\n"),
   3989                      SOC_MEM_NAME(unit, ecc_intr_info.err_mem_info),
   3990                      ecc_intr_info.ecc_num_bits_err,
   3991                      ecc_intr_info.err_addr, ecc_intr_info.mem_str));
   3992        }
   3993     }
   3994 
   3995     /* Enable the specific PM interrupt */
   3996     (void) soc_ser_top_intr_reg_enable(unit, cmic_reg_type,
   3997                                        (cmic_bit_num - 1), 1);
   3998 
   3999     /*soc_th3_ser_intr_handler(unit, PTR_TO_INT(d1), cmic_reg_type);*/
   4000     return;
   4001 }
   4002 
   4003 /*
   4004  * Function:
   4005  *      soc_th3_process_pm_intr
   4006  * Description:
   4007  *      Tomahawk3 specific DPC function to service PM interrupts
   4008  * Parameters:
   4009  *      unit_vp       - Device number
   4010  *      d1            - IRQ4 mask
   4011  *      d2            - IRQ4 number (to distinguish between
   4012  *                      different types of interrupts).
   4013  */
   4014 static void
   4015 soc_th3_pm_intr_handler(int unit, uint32 cmic_val, int reg_num)
   4016 {
   4017     uint32 cmic_bit = cmic_val;
   4018     uint32 cmic_bit_num = 0;
   4019 
   4020     /* Get the bit num or the hw port macro id */
   4021     while(cmic_bit != 0) {
   4022         cmic_bit >>= 1;
   4023         cmic_bit_num++;
   4024     }
   4025 
   4026     /* Disable the specific PM interrupt */
   4027     (void) soc_ser_top_intr_reg_enable(unit, reg_num,
   4028                                        (cmic_bit_num - 1), 0);
   4029 
   4030     sal_dpc(soc_th3_process_pm_intr, INT_TO_PTR(unit),
   4031             INT_TO_PTR(cmic_bit_num), INT_TO_PTR(reg_num), 0, 0);
   4032 
   4033     return;
   4034 }
   4035 
   4036 /*
   4037  * Function:
   4038  *      soc_th3_lp_intr_handler
   4039  * Purpose:
   4040  *      This function is the main low priority interrupt handler. L2 learn cache
   4041  *      SER and other low priority interrupts should be handled by this
   4042  *      function.
   4043  * Parameters:
   4044  *      unit  - SOC unit #
   4045  * Returns:
   4046  *     Nothing
   4047  */
   4048 STATIC
   4049 void soc_th3_lp_intr_handler(int unit, void *data)
   4050 {
   4051     int parity_enable = 0;
   4052     uint32 regval = 0;
   4053     soc_reg_t reg[] = { ICFG_CHIP_LP_INTR_RAW_STATUS_REG0r,
   4054                         ICFG_CHIP_LP_INTR_RAW_STATUS_REG1r,
   4055                         ICFG_CHIP_LP_INTR_RAW_STATUS_REG2r,
   4056                         ICFG_CHIP_LP_INTR_RAW_STATUS_REG3r,
   4057                         ICFG_CHIP_LP_INTR_STATUS_REG0r,
   4058                         ICFG_CHIP_LP_INTR_STATUS_REG1r,
   4059                         ICFG_CHIP_LP_INTR_STATUS_REG2r,
   4060                         ICFG_CHIP_LP_INTR_STATUS_REG3r
   4061                       };
   4062 
   4063     /* Note CHIP_INTR_LOW_PRIORITY is disabled in the calling handler function
   4064      * (from CMICx layer)
   4065      */
   4066     /* SER and any other modules should check the interrupt bits they will
   4067      * handle, add their handlers here
   4068      */
   4069     /* Check interrupts in reg[4] */
   4070     (void)soc_iproc_getreg(unit, soc_reg_addr(unit, reg[4], REG_PORT_ANY, 0),
   4071                            &regval);
   4072 
   4073     /* Check for the temperature interrupt and call handler */
   4074     if (regval & 0x4) { /* PVTMON_INTR , bit 2 */
   4075         /* soc_tomahawk3_temperature_intr(INT_TO_PTR(unit), NULL, NULL, NULL, NULL); */
   4076         sal_dpc(soc_tomahawk3_temperature_intr, INT_TO_PTR(unit), 0, 0, 0, 0);
   4077     }
   4078 
   4079     parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE);
   4080     /* Check interrupts in reg[0] */
   4081     (void)soc_iproc_getreg(unit, soc_reg_addr(unit, reg[0], REG_PORT_ANY, 0),
   4082                            &regval);
   4083     if ((regval & SOC_TH3_SER_REG0_INTR_MASK) && parity_enable) {
   4084         soc_th3_ser_intr_handler(unit, regval, 0);
   4085     }
   4086 
   4087     regval = 0;
   4088     (void)soc_iproc_getreg(unit, soc_reg_addr(unit, reg[2], REG_PORT_ANY, 0),
   4089                            &regval);
   4090     if ((regval & SOC_TH3_SER_REG2_INTR_MASK) && parity_enable) {
   4091         soc_th3_pm_intr_handler(unit, regval, 2);
   4092         /*sal_dpc(soc_th3_process_pm_intr, INT_TO_PTR(unit),
   4093                 INT_TO_PTR(regval), INT_TO_PTR(2), 0, 0);*/
   4094     }
   4095 
   4096     regval = 0;
   4097     (void)soc_iproc_getreg(unit, soc_reg_addr(unit, reg[3], REG_PORT_ANY, 0),
   4098                            &regval);
   4099     if ((regval & SOC_TH3_SER_REG3_INTR_MASK) && parity_enable) {
   4100         soc_th3_ser_intr_handler(unit, regval, 3);
   4101     }
   4102 
   4103     regval = 0;
   4104     (void)soc_iproc_getreg(unit, soc_reg_addr(unit, reg[1], REG_PORT_ANY, 0),
   4105                            &regval);
   4106     if ((regval & SOC_TH3_SER_REG1_INTR_MASK) && parity_enable) {
   4107         soc_th3_ser_intr_handler(unit, regval, 1);
   4108     }
   4109     /* Atleast one L2 learn cache interrupt set, call learn handler */
   4110     if (regval & SOC_TH3_L2_LEARN_CACHE_INTR_MASK) {
   4111         soc_th3_lrn_cache_intr_handler(unit, data);
   4112     }
   4113 
   4114    /* Re-enable main CMICx interrupt */
   4115    soc_cmic_intr_enable(unit, CHIP_INTR_LOW_PRIORITY);
   4116 }
   4117 
   4118 
   4119 /*
   4120  * Function:
   4121  *      soc_th3_lp_intr_register
   4122  * Purpose:
   4123  *      This function registers a low priority interrupt handler for all low
   4124  *      priority interrupts. L2 learn cache, SER and other low priority
   4125  *      interrupts are handled by the handler function registered in this
   4126  *      function
   4127  * Parameters:
   4128  *      unit  - SOC unit #
   4129  * Returns:
   4130  *     Nothing
   4131  */
   4132 STATIC void
   4133 soc_th3_lp_intr_register(int unit)
   4134 {
   4135     soc_cmic_intr_handler_t handle;
   4136 
   4137     handle.num = CHIP_INTR_LOW_PRIORITY;
   4138     handle.intr_fn = soc_th3_lp_intr_handler;
   4139     handle.intr_data = NULL;
   4140     soc_cmic_intr_register(unit, &handle, 1);
   4141 
   4142    /* Enable main CMICx interrupt */
   4143    soc_cmic_intr_enable(unit, CHIP_INTR_LOW_PRIORITY);
   4144 }
   4145 
   4146 STATIC int
   4147 _soc_tomahawk3_misc_init(int unit)
   4148 {
   4149     /*soc_mem_t mem;*/
   4150     int rv, i;
   4151     uint8 bypass_valid = 0;
   4152     uint8 rev_id;
   4153     uint16 dev_id;
   4154     int port_chk, num_port = 160;
   4155     /* _soc_tomahawk_tdm_t *tdm; */
   4156     int  parity_enable;
   4157     /*int clport, lane, mode, class, index;*/
   4158     soc_info_t *si = &SOC_INFO(unit);
   4159     /*static soc_field_t port_fields[_TH_PORTS_PER_PBLK] = {
   4160         PORT0f, PORT1f, PORT2f, PORT3f
   4161     };
   4162     */
   4163     uint64 fval_64;
   4164     uint64 rval_64;
   4165     int port, cnt;
   4166     const static soc_reg_t cnt_reg_list[] =
   4167     {
   4168         RUC_64r,    RPORTD_64r, RDBGC0_64r,  RDBGC1_64r,
   4169         RDBGC2_64r, RDBGC3_64r, RDBGC4_64r,  RDBGC5_64r,
   4170         RDBGC6_64r, RDBGC7_64r, RDBGC8_64r,  ING_ECN_COUNTER_64r,
   4171         TDBGC0_64r, TDBGC1_64r, TDBGC2_64r,  TDBGC3_64r,
   4172         TDBGC4_64r, TDBGC5_64r, TDBGC6_64r,  TDBGC7_64r,
   4173         TDBGC8_64r, TDBGC9_64r, TDBGC10_64r, TDBGC11_64r
   4174     };
   4175     void *null_entry = NULL;
   4176     int copyno;
   4177     uint32 index = 0;
   4178     soc_mem_t mem = INVALIDm;
   4179 
   4180     uint32 pipe_map;
   4181     uint8 used_pm_map[_TH3_PBLKS_PER_DEV + 1];
   4182     uint8 *buf;
   4183     int phy_port, pm_num, pipe_num, size, pm;
   4184     const soc_mem_t idb_obm_list[_TH3_PIPES_PER_DEV][_TH3_PBLKS_PER_PIPE] = {
   4185         {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE0m,
   4186          IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE0m,
   4187          IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE0m,
   4188          IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE0m},
   4189         {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE1m,
   4190          IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE1m,
   4191          IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE1m,
   4192          IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE1m},
   4193         {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE2m,
   4194          IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE2m,
   4195          IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE2m,
   4196          IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE2m},
   4197         {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE3m,
   4198          IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE3m,
   4199          IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE3m,
   4200          IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE3m},
   4201         {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE4m,
   4202          IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE4m,
   4203          IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE4m,
   4204          IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE4m},
   4205         {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE5m,
   4206          IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE5m,
   4207          IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE5m,
   4208          IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE5m},
   4209         {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE6m,
   4210          IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE6m,
   4211          IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE6m,
   4212          IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE6m},
   4213         {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE7m,
   4214          IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE7m,
   4215          IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE7m,
   4216          IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE7m},
   4217     };
   4218 
   4219     sal_memset(used_pm_map, 0, sizeof(used_pm_map));
   4220     for (phy_port = 1; phy_port <= _TH3_PORTS_PER_DEV; phy_port++) {
   4221         port = si->port_p2l_mapping[phy_port];
   4222         if (port > 0) {
   4223             pm = si->port_serdes[port];
   4224             if ((-1 != pm) && (0 == used_pm_map[pm])) {
   4225                 used_pm_map[pm] = 1;
   4226             }
   4227         }
   4228     }
   4229 
   4230 
   4231     soc_cm_get_id(unit, &dev_id, &rev_id);
   4232 
   4233     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   4234     /* Stop the mem scan task before all of the parity init takes place */
   4235     SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_stop(unit));
   4236     SOC_IF_ERROR_RETURN(soc_generic_sram_mem_scan_stop(unit));
   4237 
   4238     SOC_IF_ERROR_RETURN(soc_reg_field32_modify
   4239             (unit, AUX_ARB_CONTROLr, REG_PORT_ANY, FP_REFRESH_ENABLEf, 1));
   4240 
   4241     parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE);
   4242 #if 0
   4243      /*Slot pipeline config*/
   4244      SOC_IF_ERROR_RETURN(soc_tomahawk3_slot_pipeline_config(unit));
   4245 #endif
   4246 
   4247     /* Reset counts on debug tx/rx debug counters */
   4248     if (SAL_BOOT_SIMULATION && !SAL_BOOT_QUICKTURN) {
   4249         COMPILER_64_ZERO(fval_64);
   4250         PBMP_ALL_ITER(unit, port) {
   4251             for (cnt=0; cnt<COUNTOF(cnt_reg_list) ; cnt++) {
   4252                 COMPILER_64_ZERO(rval_64);
   4253                 SOC_IF_ERROR_RETURN(
   4254                     soc_reg_get(unit, cnt_reg_list[cnt], port, 0, &rval_64));
   4255                 soc_reg64_field_set(
   4256                     unit, cnt_reg_list[cnt], &rval_64, COUNTf, fval_64);
   4257                 SOC_IF_ERROR_RETURN(
   4258                     soc_reg_set(unit, cnt_reg_list[cnt], port, 0, rval_64));
   4259            }
   4260         }
   4261     }
   4262     COMPILER_64_ZERO(rval_64);
   4263     /* For TH3-5414, we need to make sure the below register
   4264        is cleared even for invalid ports 
   4265      */
   4266     for (i = 0; i < 160 ; i++) {
   4267         SOC_IF_ERROR_RETURN(WRITE_EGR_1588_LINK_DELAY_64r(unit, i, rval_64));
   4268     }
   4269   
   4270     if (!SOC_IS_RELOADING(unit) && !SOC_WARM_BOOT(unit)) {
   4271 
   4272         SOC_IF_ERROR_RETURN(_soc_tomahawk3_port_mib_reset(unit));
   4273 
   4274         /* Dummy call to clear garbage h/w values */
   4275         SOC_IF_ERROR_RETURN
   4276             (soc_tomahawk3_temperature_monitor_get(unit, COUNTOF(pvtmon_result_reg_th3),
   4277                                                   NULL, NULL));
   4278 
   4279         SOC_IF_ERROR_RETURN(soc_tomahawk3_clear_mmu_counters(unit));
   4280         SOC_IF_ERROR_RETURN(soc_tomahawk3_init_tm_memory(unit));
   4281         mem = EDB_XMIT_START_COUNTm;
   4282         null_entry = soc_mem_entry_null(unit, mem);
   4283         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   4284         for (index = soc_mem_index_min(unit, mem);
   4285              index <= soc_mem_index_max(unit, mem); index++) {
   4286             rv = soc_mem_write(unit, mem, copyno, index, null_entry);
   4287         }
   4288 
   4289         size = SOC_MEM_TABLE_BYTES(unit, idb_obm_list[0][0]);
   4290         buf = soc_cm_salloc(unit, size, "IDB OBM MEMORY");
   4291         sal_memset(buf, 0, size);
   4292         PBMP_PORT_ITER(unit, port) {
   4293             if (SOC_PBMP_MEMBER(si->management_pbm, port)) {
   4294                 continue;
   4295             }
   4296             phy_port = si->port_l2p_mapping[port];
   4297             pipe_num = soc_tomahawk3_get_pipe_from_phy_port(phy_port);
   4298             pm_num = soc_tomahawk3_get_pipe_pm_from_phy_port(phy_port);
   4299             if (!(pipe_map & (1 << pipe_num))) {
   4300                 continue;
   4301             }
   4302             if (used_pm_map[pm_num] == 0) {
   4303                 continue;
   4304             }
   4305             mem = idb_obm_list[pipe_num][pm_num];
   4306             copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   4307             rv = soc_mem_write_range(unit, mem, copyno, soc_mem_index_min(unit, mem),
   4308                                      soc_mem_index_max(unit, mem), buf);
   4309             if (rv != SOC_E_NONE) {
   4310                 soc_cm_sfree(unit, buf);
   4311                 return rv;
   4312             }
   4313         }
   4314         soc_cm_sfree(unit, buf);
   4315     }
   4316 
   4317     if (parity_enable) {
   4318         if ((!SAL_BOOT_SIMULATION || SAL_BOOT_QUICKTURN) &&
   4319             !SOC_WARM_BOOT(unit)) {
   4320 
   4321             /* Certain mems/regs need to be cleared before enabling SER */
   4322             
   4323         }
   4324 
   4325         /* Enable logging of SER events */
   4326         soc_ser_log_init(unit, NULL, 0);
   4327 
   4328         
   4329         /* Enable l2_mgmt interrupt */
   4330         /* SOC_IF_ERROR_RETURN
   4331             (soc_reg_field32_modify(unit, L2_MGMT_INTR_MASKr, REG_PORT_ANY,
   4332                                     SER_FIFO_NOT_EMPTYf, 1));*/
   4333 #ifdef BCM_CMICX_SUPPORT
   4334         if (soc_feature(unit, soc_feature_cmicx)) {
   4335             
   4336             /*soc_cmicm_intr3_enable(unit, 0x2); L2_MGMT_TO_CMIC_INTR bit 1 */
   4337         }
   4338 #endif
   4339         
   4340         /* SOC_IF_ERROR_RETURN(soc_tomahawk_tcam_ser_init(unit)); */
   4341         SOC_IF_ERROR_RETURN(soc_tomahawk_ser_enable_all(unit, TRUE));
   4342         SOC_IF_ERROR_RETURN(soc_tomahawk3_ser_enable_parity_table_all(unit, TRUE));
   4343         soc_tomahawk_ser_register(unit);
   4344 #if defined(SER_TR_TEST_SUPPORT)
   4345         /*Initialize chip-specific functions for SER testing*/
   4346         soc_th_ser_test_register(unit);
   4347 #endif /*defined(SER_TR_TEST_SUPPORT*/
   4348     }
   4349 
   4350         /* Clear SER related fifo before enabling low priority interrupt */
   4351         if (!SAL_BOOT_SIMULATION) {
   4352         _soc_tomahawk3_ser_hw_clear(unit);
   4353     }
   4354 
   4355     /* Turn on low priority interrupts for actual h/w and emulation */
   4356     /* Note the individual modules should check if they will be working in
   4357      * interrupt mode, and enable/disable module level interrupts accordingly
   4358      */
   4359     if ((!SAL_BOOT_SIMULATION) || (SAL_BOOT_QUICKTURN)) {
   4360         if (soc_feature(unit, soc_feature_cmicx)) {
   4361             soc_th3_lp_intr_register(unit);
   4362         }
   4363     }
   4364 
   4365     /* Configure Switch Latency Bypass Mode */
   4366     bypass_valid = soc_property_get(unit, spn_SWITCH_BYPASS_MODE,
   4367                                         SOC_SWITCH_BYPASS_MODE_NONE);
   4368     if ((SOC_SWITCH_BYPASS_MODE_NONE != bypass_valid) &&
   4369         (SOC_SWITCH_BYPASS_MODE_EFP != bypass_valid)) {
   4370         LOG_ERROR(BSL_LS_SOC_COMMON,
   4371                     (BSL_META_U(unit,
   4372                                 "Low latency and Balanced latency modes not"
   4373                                 "supported on BCM5698x \n")));
   4374         return SOC_E_CONFIG;
   4375     }
   4376     SOC_IF_ERROR_RETURN(soc_th_latency_init(unit));
   4377 
   4378     /*Dev_port, Phyport, MMU port, IDB port mappings*/
   4379     SOC_IF_ERROR_RETURN(_soc_tomahawk3_port_mapping_init(unit));
   4380 
   4381     /* No HG port support */
   4382     SOC_CONTROL_LOCK(unit);
   4383     si->fabric_port_enable = 0;
   4384     SOC_CONTROL_UNLOCK(unit);
   4385 
   4386     for(port_chk = 0; port_chk < num_port; port_chk++) {
   4387         if (si->port_speed_max[port_chk] > 0) {
   4388             rv = soc_th3_port_speed_supported(unit, port_chk,
   4389                                              si->port_speed_max[port_chk]);
   4390             if (SOC_FAILURE(rv)) {
   4391                 LOG_ERROR(BSL_LS_SOC_COMMON,
   4392                             (BSL_META_U(unit,
   4393                                         "Unsupported port speed : port - %d, "
   4394                                         "speed - %d\n"), port_chk,
   4395                                         si->port_speed_max[port_chk]));
   4396                 return rv;
   4397             }
   4398         }
   4399     }
   4400 
   4401     /* Check the speed classes, make sure only 4 speeds in the device */
   4402     SOC_IF_ERROR_RETURN(soc_th3_speed_class_validate(unit));
   4403 
   4404     /*DV: TDM Code*/
   4405     SOC_IF_ERROR_RETURN(soc_tomahawk3_tdm_update(unit));
   4406 
   4407         /* Initialize IDB */
   4408         /*DV: Integrate IDB init from DV*/
   4409         rv = soc_tomahawk3_idb_init_update(unit);
   4410         if (SOC_FAILURE(rv)){
   4411             LOG_ERROR(BSL_LS_SOC_COMMON,
   4412                       (BSL_META_U(unit,
   4413                                   "FAILED in"
   4414                                   "soc_tomahawk3_idb_init_update\n")));
   4415             return rv;
   4416         }
   4417 
   4418     /*Setup CPU_PBM and Loopback port bitmap*/
   4419     SOC_IF_ERROR_RETURN(_soc_tomahawk3_cpu_lb_portbitmap_set(unit));
   4420 
   4421     /*Setup port_type for HG/LB ports*/
   4422     SOC_IF_ERROR_RETURN(_soc_tomahawk3_hg_lb_port_type_set(unit));
   4423 
   4424 #ifdef PLISIM
   4425     if (SAL_BOOT_PLISIM) {
   4426         /* done later, after port mapping is configured by ep_top. */
   4427     } else
   4428 #endif
   4429     {
   4430         /*XLPORT init*/
   4431         SOC_IF_ERROR_RETURN(_soc_tomahawk3_management_port_init(unit));
   4432     }
   4433     
   4434     /*Enable refresh in MMU*/
   4435      SOC_IF_ERROR_RETURN(soc_tomahawk3_en_mmu_refresh(unit));
   4436 
   4437     /* Enable dual hash tables */
   4438     SOC_IF_ERROR_RETURN(soc_tomahawk3_hash_init(unit));
   4439 
   4440     /*DV: integrate EP credit int and port enable from DV*/
   4441     SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_top_init(unit));
   4442 
   4443 #if defined(PLISIM)
   4444     if (SAL_BOOT_PLISIM) {
   4445         /*XLPORT init*/
   4446         SOC_IF_ERROR_RETURN(_soc_tomahawk3_management_port_init(unit));
   4447     }
   4448 #endif /* PLISIM */
   4449 
   4450     /*Enable MAC after EP enable*/
   4451     SOC_IF_ERROR_RETURN(soc_tomahawk3_cdport_init(unit));
   4452 
   4453     /*DV: Enable ingress forwarding */
   4454     SOC_IF_ERROR_RETURN(soc_tomahawk3_enable_ingress_forwarding(unit));
   4455 
   4456 
   4457     /*Default programming required in IPEP*/
   4458     SOC_IF_ERROR_RETURN(_soc_tomahawk3_ipep_default_init(unit));
   4459 
   4460 
   4461 
   4462 #if 0
   4463     
   4464     if (SAL_BOOT_QUICKTURN) {
   4465         PBMP_PORT_ITER(unit, port) {
   4466             if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) {
   4467                 continue;
   4468             }
   4469             SOC_IF_ERROR_RETURN
   4470                 (soc_tomahawk3_port_speed_update(unit, port,
   4471                                                 si->port_speed_max[port]));
   4472         }
   4473     }
   4474 #endif
   4475 
   4476     /*external,internal MDIO freq config*/
   4477     SOC_IF_ERROR_RETURN(_soc_tomahawk3_cmic_mdio_freq_config(unit));
   4478 
   4479     
   4480     _phy_tsce_firmware_set_helper[unit] = _soc_tomahawk3_tscx_firmware_set;
   4481     _phy_tscf_firmware_set_helper[unit] = _soc_tomahawk3_tscx_firmware_set;
   4482 
   4483 
   4484     SOC_IF_ERROR_RETURN
   4485         (soc_counter_tomahawk_status_enable(unit, TRUE));
   4486 
   4487     /* Mem Scan thread start should be the last step in Misc init */
   4488     if (parity_enable) {
   4489         if ((!SAL_BOOT_SIMULATION || SAL_BOOT_QUICKTURN) &&
   4490             !SOC_WARM_BOOT(unit)) {
   4491             SOC_IF_ERROR_RETURN(soc_generic_sram_mem_scan_start(unit));
   4492         }
   4493     }
   4494 
   4495     /* Create a mutex for s/w re-ordering */
   4496     SOC_IF_ERROR_RETURN(soc_tomahawk3_hash_mutex_init(unit));
   4497 
   4498 #ifdef BCM_CMICX_SUPPORT
   4499     if (soc_feature(unit, soc_feature_cmicx) &&
   4500         !(SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM))
   4501     {
   4502         SOC_IF_ERROR_RETURN(_soc_th3_ledup_init(unit));
   4503     }
   4504 #endif /* BCM_CMICX_SUPPORT */
   4505 
   4506 #ifdef INCLUDE_AVS
   4507     SOC_IF_ERROR_RETURN(soc_tomahawk3_avs_init(unit));
   4508 #endif /* INCLUDE_AVS  */
   4509 
   4510     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   4511                 (BSL_META_U(unit,
   4512                             "MISC Init completed (u=%d)\n"), unit));
   4513     return SOC_E_NONE;
   4514 }
   4515 
   4516 
   4517 
   4518 /* Function to get the number of ports present in a given Port Macro */
   4519 int
   4520 soc_th3_ports_per_pm_get(int unit, int pm_id)
   4521 {
   4522     soc_info_t *si;
   4523     int phy_port_base, num_ports = 0;
   4524 
   4525     si = &SOC_INFO(unit);
   4526     if (pm_id >= _TH3_PBLKS_PER_DEV) {
   4527        return SOC_E_PARAM;
   4528     }
   4529     phy_port_base = 1 + (pm_id * _TH3_PORTS_PER_PBLK);
   4530 
   4531     if (si->port_p2l_mapping[phy_port_base] != -1) {
   4532         num_ports = 1;
   4533         if ((si->port_num_lanes[phy_port_base] == 2) &&
   4534             (si->port_p2l_mapping[phy_port_base + 2] != -1)) {
   4535             /* for cases when num_lanes is given in the config (40g).
   4536              */
   4537             num_ports = 2;
   4538         }
   4539 
   4540         /* When phy_port_base + 1 is valid,
   4541          *      All 4 ports of the PM(port macro) are valid.
   4542          * When phy_port_base + 2 is valid,
   4543          *      The PM is operating in Dual lane mode
   4544          */
   4545         if (si->port_p2l_mapping[phy_port_base + 1] != -1) {
   4546             num_ports = 4;
   4547             if (si->port_p2l_mapping[phy_port_base + 2] == -1) {
   4548                 num_ports = 2;
   4549             }
   4550         } else if (si->port_p2l_mapping[phy_port_base + 2] != -1) {
   4551             num_ports = 2;
   4552         }
   4553     }
   4554     return num_ports;
   4555 }
   4556 
   4557 void
   4558 _soc_th3_lpm_view_set(int unit, int index, soc_mem_t view, int pair_lpm)
   4559 {
   4560     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
   4561 
   4562     if (!_soc_th3_lpm_view_map[unit]) {
   4563         return;
   4564     }
   4565 
   4566     if (pair_lpm) {
   4567         index = (index % tcam_depth) +
   4568                 (index / tcam_depth) * 2 * tcam_depth;
   4569         _soc_th3_lpm_view_map[unit][index] = view;
   4570         _soc_th3_lpm_view_map[unit][index + tcam_depth] = view;
   4571     } else {
   4572         _soc_th3_lpm_view_map[unit][index] = view;
   4573     }
   4574 }
   4575 
   4576 soc_mem_t
   4577 _soc_th3_lpm_view_get(int unit, int index, int pair_lpm)
   4578 {
   4579     soc_mem_t view;
   4580     int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
   4581 
   4582     if (!_soc_th3_lpm_view_map[unit]) {
   4583         return INVALIDm;
   4584     }
   4585 
   4586     if (pair_lpm) {
   4587         index = (index % tcam_depth) +
   4588                 (index / tcam_depth) * 2 * tcam_depth;
   4589         view = _soc_th3_lpm_view_map[unit][index];
   4590         if (view == INVALIDm) {
   4591             view = _soc_th3_lpm_view_map[unit][index + tcam_depth];
   4592         }
   4593     } else {
   4594         view = _soc_th3_lpm_view_map[unit][index];
   4595     }
   4596     return view;
   4597 }
   4598 
   4599 STATIC int
   4600 soc_tomahawk3_rqe_threshold_init(int unit) {
   4601 
   4602 #define TH3_MMU_RQE_QUEUE_NUM 9
   4603 #define TH3_THDR_QE_CONFIG1_VALUE 0x7
   4604 #define TH3_THDR_QE_CONIFG_PRI_LIMIT 8
   4605 #define TH3_THDR_QE_LIMIT_MIN 7
   4606 #define TH3_MMU_THDR_QE_RESET_OFFSET 0xe
   4607 #define TH3_THDR_QE_SP_SHARED_LIMIT 0xaa9
   4608 #define TH3_THDR_QE_SP_RESUME_LIMIT 0xa9b
   4609 
   4610     soc_reg_t reg = INVALIDr;
   4611     uint32 idx, rval;
   4612     for(idx = 0; idx < TH3_MMU_RQE_QUEUE_NUM; idx++) {
   4613         reg = MMU_THDR_QE_CONFIG1_PRIQr;
   4614         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   4615                                    idx, TH3_THDR_QE_CONFIG1_VALUE));
   4616 
   4617         reg = MMU_THDR_QE_CONFIG_PRIQr;
   4618         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
   4619         soc_reg_field_set(unit, reg, &rval, RESET_OFFSETf,
   4620                                         TH3_MMU_THDR_QE_RESET_OFFSET);
   4621         soc_reg_field_set(unit, reg, &rval, SHARED_LIMITf,
   4622                                         TH3_THDR_QE_CONIFG_PRI_LIMIT);
   4623         soc_reg_field_set(unit, reg, &rval, SHARED_ALPHAf,
   4624                                         TH3_THDR_QE_CONIFG_PRI_LIMIT);
   4625         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   4626                                    idx, rval));
   4627 
   4628         reg = MMU_THDR_QE_LIMIT_MIN_PRIQr;
   4629         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
   4630         soc_reg_field_set(unit, reg, &rval, MIN_LIMITf, TH3_THDR_QE_LIMIT_MIN);
   4631         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   4632                                    idx, rval));
   4633 
   4634         reg = MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr;
   4635         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
   4636         soc_reg_field_set(unit, reg, &rval, RESET_OFFSET_YELLOWf,
   4637                                            TH3_MMU_THDR_QE_RESET_OFFSET);
   4638         soc_reg_field_set(unit, reg, &rval, RESET_OFFSET_REDf,
   4639                                            TH3_MMU_THDR_QE_RESET_OFFSET);
   4640         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   4641                                    idx, rval));
   4642     }
   4643 
   4644     reg = MMU_THDR_QE_CONFIGr;
   4645     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
   4646     soc_reg_field_set(unit, reg, &rval, LAST_PKT_ACCEPT_MODEf, 1);
   4647     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   4648                                    idx, rval));
   4649 
   4650     reg = MMU_THDR_QE_CONFIG_SPr;
   4651     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
   4652     soc_reg_field_set(unit, reg, &rval, SHARED_LIMITf,
   4653                                     TH3_THDR_QE_SP_SHARED_LIMIT);
   4654     soc_reg_field_set(unit, reg, &rval, RESUME_LIMITf,
   4655                                     TH3_THDR_QE_SP_RESUME_LIMIT);
   4656     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   4657                                    idx, rval));
   4658 
   4659     reg = MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr;
   4660     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
   4661     soc_reg_field_set(unit, reg, &rval, SHARED_LIMIT_YELLOWf,
   4662                                     TH3_THDR_QE_SP_SHARED_LIMIT);
   4663     soc_reg_field_set(unit, reg, &rval, SHARED_LIMIT_REDf,
   4664                                     TH3_THDR_QE_SP_SHARED_LIMIT);
   4665     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   4666                                    idx, rval));
   4667 
   4668     reg = MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr;
   4669     soc_reg_field_set(unit, reg, &rval, RESUME_LIMIT_YELLOWf,
   4670                                           TH3_THDR_QE_SP_RESUME_LIMIT);
   4671     soc_reg_field_set(unit, reg, &rval, RESUME_LIMIT_REDf,
   4672                                           TH3_THDR_QE_SP_RESUME_LIMIT);
   4673     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   4674                                    idx, rval));
   4675 
   4676 
   4677     return SOC_E_NONE;
   4678 }
   4679 
   4680 STATIC int
   4681 soc_tomahawk3_rqe_sched_shaper_init(int unit) {
   4682     soc_reg_t reg = INVALIDr;
   4683     uint32 idx, rval;
   4684     uint64 rval_64;
   4685 
   4686     for(idx = 0; idx < TH3_MMU_RQE_QUEUE_NUM; idx++) {
   4687         reg = MMU_RQE_MAX_SHAPER_ENr;
   4688         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
   4689         soc_reg_field_set(unit, reg, &rval, VALUEf, 0);
   4690         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   4691                                    idx, rval));
   4692 
   4693         reg = MMU_RQE_PRIORITY_WERR_WEIGHTr;
   4694         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval));
   4695         soc_reg_field_set(unit, reg, &rval, COUNTf, 1);
   4696         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY,
   4697                                    idx, rval));
   4698     }
   4699     COMPILER_64_ZERO(rval_64);
   4700     reg = MMU_RQE_SCH_INACTIVE_CONTROLr;
   4701     SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval_64));
   4702     soc_reg64_field32_set(unit, reg, &rval_64, INTERVALf, 20);
   4703     SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval_64));
   4704 
   4705 
   4706     return SOC_E_NONE;
   4707 }
   4708 
   4709 STATIC int
   4710 _soc_tomahawk3_mmu_init(int unit)
   4711 {
   4712     int test_only, parity_en;
   4713     SOC_INFO(unit).mmu_lossless = soc_property_get(unit, spn_MMU_LOSSLESS,
   4714                                         SOC_TH3_MMU_LOSSLESS_DEFAULT_DISABLE);
   4715 
   4716     test_only = (SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) ? TRUE : FALSE;
   4717     parity_en = soc_property_get(unit, spn_PARITY_ENABLE, TRUE);
   4718 
   4719     SOC_IF_ERROR_RETURN(_soc_th3_post_mmu_init_update(unit));
   4720     SOC_IF_ERROR_RETURN(soc_tomahawk3_rqe_threshold_init(unit));
   4721     SOC_IF_ERROR_RETURN(soc_tomahawk3_rqe_sched_shaper_init(unit));
   4722     /*Port speed encodings to be setup in MMU diuring init*/
   4723     /*Can be re-used for port speed update as well*/
   4724     SOC_IF_ERROR_RETURN(soc_tomahawk3_tm_port_speed_encoding(unit));
   4725     SOC_IF_ERROR_RETURN(soc_tomahawk3_cell_pointer_init(unit));
   4726     SOC_IF_ERROR_RETURN(soc_tomahawk3_mmu_port_rx_enables(unit));
   4727     SOC_IF_ERROR_RETURN(soc_tomahawk3_scheduler_init(unit));
   4728     SOC_IF_ERROR_RETURN(soc_th3_mmu_config_init_thresholds(unit, test_only));
   4729     SOC_IF_ERROR_RETURN(soc_th3_mmu_rqe_queue_number_init(unit));
   4730     SOC_IF_ERROR_RETURN(soc_tomahawk3_wred_init(unit));
   4731     SOC_IF_ERROR_RETURN(soc_tomahawk3_scb_init(unit));
   4732     SOC_IF_ERROR_RETURN(soc_tomahawk3_rl_init(unit));
   4733 #ifdef INCLUDE_PSTATS
   4734     soc_tomahawk3_mmu_pstats_tbl_config(unit);
   4735 #endif
   4736 
   4737     SOC_IF_ERROR_RETURN(soc_th3_pfc_rx_init_from_cfg(unit));
   4738     SOC_IF_ERROR_RETURN(soc_th3_pfc_priority_to_pg_map_init_from_cfg(unit));
   4739     if (parity_en) {
   4740         SOC_IF_ERROR_RETURN(soc_th3_mmu_enable_non_func_intr(unit));
   4741     }
   4742     return SOC_E_NONE;
   4743 }
   4744 
   4745 STATIC int
   4746 _soc_tomahawk3_age_timer_get(int unit, int *age_seconds, int *enabled)
   4747 {
   4748     soc_control_t *soc = SOC_CONTROL(unit);
   4749 
   4750     *enabled = soc->l2x_age_pid != SAL_THREAD_ERROR &&
   4751                soc->l2x_age_enable ?
   4752                1 : 0;
   4753     *age_seconds = soc->l2x_age_pid != SAL_THREAD_ERROR &&
   4754                    soc->l2x_age_enable ?
   4755                    soc->l2x_age_interval : 0;
   4756 
   4757     return SOC_E_NONE;
   4758 }
   4759 
   4760 STATIC int
   4761 _soc_tomahawk3_age_timer_max_get(int unit, int *max_seconds)
   4762 {
   4763     *max_seconds = 0x7fffffff;
   4764     return SOC_E_NONE;
   4765 }
   4766 
   4767 STATIC int
   4768 _soc_tomahawk3_age_timer_set(int unit, int age_seconds, int enable)
   4769 {
   4770     soc_control_t *soc = SOC_CONTROL(unit);
   4771     sal_usecs_t interval = soc->l2x_age_interval;
   4772 
   4773     if (soc->l2x_age_interval) {
   4774         if (!enable) {
   4775             soc->l2x_age_enable = 0;
   4776         } else {
   4777             if (age_seconds) {
   4778                 SOC_CONTROL_LOCK(unit);
   4779                 soc->l2x_age_interval = age_seconds;
   4780                 SOC_CONTROL_UNLOCK(unit);
   4781             }
   4782             soc->l2x_age_enable = 1;
   4783             if (interval != age_seconds) {
   4784                 sal_sem_give(soc->l2x_age_notify);
   4785             }
   4786         }
   4787     } else {
   4788         if (enable) {
   4789             soc->l2x_age_enable = 1;
   4790             SOC_IF_ERROR_RETURN
   4791                 (soc_th3_l2_age_start(unit, age_seconds));
   4792         }
   4793     }
   4794 
   4795     return SOC_E_NONE;
   4796 }
   4797 
   4798 soc_error_t
   4799 soc_th3_port_speed_supported(int unit, soc_port_t port, int speed)
   4800 {
   4801     uint8 rev_id;
   4802     uint16 dev_id;
   4803     int num_lanes;
   4804     soc_info_t *si = &SOC_INFO(unit);
   4805 
   4806     /*
   4807      * If Universal calendar was not selected at init time then
   4808      * disallow speed change to HG2 speeds.
   4809      */
   4810     if (FALSE == si->fabric_port_enable) {
   4811         if (IS_HG2_SPEED(speed)) {
   4812             /*
   4813              * Intentionally returning SOC_E_CONFIG as this is a case
   4814              * of incorrect configuration
   4815              */
   4816             return SOC_E_CONFIG;
   4817         }
   4818     }
   4819 
   4820     /*
   4821      * Management ports only support 1G, 2.5G and 10G. Flexport
   4822      * on management ports is not supported. Management ports
   4823      * are guaranteed 10G bandwidth.
   4824      */
   4825     if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) {
   4826         if ((1000 == speed) || (2500 == speed) || (10000 == speed)) {
   4827             return SOC_E_NONE;
   4828         } else {
   4829             return SOC_E_PARAM;
   4830         }
   4831     }
   4832 
   4833     soc_cm_get_id(unit, &dev_id, &rev_id);
   4834     num_lanes = si->port_num_lanes[port];
   4835     
   4836     /*
   4837      * Check if Core Clock Frequency supports Port Speed
   4838      */
   4839 
   4840     switch (speed) {
   4841     /* 10G, 40G */
   4842     case 10000:
   4843     case 40000:
   4844         break;
   4845 
   4846     /* 25G, 50G, 100G, 200G, 400G */
   4847     case 25000:
   4848     case 50000:
   4849         if (si->frequency < 300) {
   4850             return SOC_E_PARAM;
   4851         }
   4852         break;
   4853     case 100000:
   4854         if (si->frequency < 600) {
   4855             return SOC_E_PARAM;
   4856         }
   4857         break;
   4858     case 200000:
   4859         if (si->frequency < 600) {
   4860             return SOC_E_PARAM;
   4861         }
   4862         break;
   4863     case 400000:
   4864         if (si->frequency < 1200) {
   4865             return SOC_E_PARAM;
   4866         }
   4867         break;
   4868 
   4869     default:
   4870        return SOC_E_PARAM; 
   4871     }
   4872 
   4873     /*
   4874      * Laying down the framework to handle SKU differences. This is
   4875      * needed because some SKUs have speed caps on certain PMs.
   4876      */
   4877     switch (dev_id) {
   4878     case BCM56961_DEVICE_ID:
   4879         /* SERDES VCO capped at 21.875Ghz */
   4880         if ((25000 == speed) || (27000 == speed) || (speed >= 50000)) {
   4881             return SOC_E_PARAM;
   4882         }
   4883         /* Fall through to default case */
   4884 
   4885     default:
   4886         if (speed >= 400000) { /* 400G */
   4887             if (8 != num_lanes) {
   4888                 return SOC_E_PARAM;
   4889             }
   4890         } else if (speed >= 200000) { /* 200G */
   4891             if (4 != num_lanes) {
   4892                 return SOC_E_PARAM;
   4893             }
   4894         }else if (speed >= 100000) { /* 100G.  Account for 2x50G or 4x25G*/
   4895             if ((4 != num_lanes) && (2 != num_lanes)) {
   4896                 return SOC_E_PARAM;
   4897             }
   4898         } else if (speed >= 50000) { /* 50G.  Account for 1 x 50G or 2 x 25G */
   4899             if ((1 != num_lanes) && (2 != num_lanes)) {
   4900                 return SOC_E_PARAM;
   4901             }
   4902         } else if (speed >= 40000) { /* 40G 4 x 10G */
   4903             if (4 != num_lanes && (2 != num_lanes)) {
   4904                 return SOC_E_PARAM;
   4905             }
   4906         } else if (speed >= 25000) { /* 25G */
   4907             if (1 != num_lanes) {
   4908                 return SOC_E_PARAM;
   4909             }
   4910         } else { /* 10G */
   4911             if (1 != num_lanes) {
   4912                 return SOC_E_PARAM;
   4913             }
   4914         }
   4915     }
   4916     return SOC_E_NONE;
   4917 }
   4918 
   4919 
   4920 soc_error_t
   4921 soc_th3_speed_set_init_ctrl(int unit, soc_th_port_lanes_t *lanes_ctrl)
   4922 {
   4923 #if 0
   4924     soc_info_t *si = &SOC_INFO(unit);
   4925     soc_port_t port_base = lanes_ctrl->port_base;
   4926 
   4927     lanes_ctrl->oversub = SOC_PBMP_MEMBER(si->oversub_pbm, port_base);
   4928 
   4929     if (lanes_ctrl->oversub) {
   4930         SOC_IF_ERROR_RETURN(soc_tomahawk3_oversub_group_find(unit, lanes_ctrl));
   4931     }
   4932 #endif
   4933 
   4934     return SOC_E_NONE;
   4935 }
   4936 
   4937 void
   4938 soc_tomahawk3_temperature_intr(void *unit_vp, void *d1, void *d2,
   4939                               void *d3, void *d4)
   4940 {
   4941     uint32 rval, trval;
   4942     int i, rv, unit = PTR_TO_INT(unit_vp);
   4943     
   4944     if ((rv = READ_TOP_PVTMON_INTR_STATUS_0r(unit, &rval)) != SOC_E_NONE) {
   4945         LOG_ERROR(BSL_LS_SOC_COMMON,
   4946                   (BSL_META_U(unit,
   4947                               "TH3 Temp Intr, Reg access error.\n")));
   4948     }
   4949     LOG_ERROR(BSL_LS_SOC_COMMON,
   4950               (BSL_META_U(unit,
   4951                           "High temp interrupt: 0x%08x\n"), rval));
   4952     /* Raise event to app for it to take further graceful actions, ignore AVS */
   4953     for (i = 0; i < COUNTOF(pvtmon_result_reg_th3)-1; i++) {
   4954         if ((0x1 << i)  & _soc_th_temp_mon_mask[unit]) {
   4955             if ((rv = soc_reg32_get(unit, pvtmon_result_reg_th3[i], REG_PORT_ANY, 0,
   4956                                     &trval)) != SOC_E_NONE) {
   4957                 LOG_ERROR(BSL_LS_SOC_COMMON,
   4958                           (BSL_META_U(unit,
   4959                                       "TH3 Temp Intr, Reg access error.\n")));
   4960             }
   4961             trval = soc_reg_field_get(unit, pvtmon_result_reg_th3[i], trval,
   4962                                       PVT_DATAf);
   4963             /* Convert data to temperature.
   4964              * temp = 434.1-(data*0.5350) = (4341000-(trval*5350))/1000;
   4965              * Note: Since this is a high temp interrupt we can safely assume
   4966              * that this will end up being a +ive value.
   4967              */            
   4968             trval = (4341000-(trval*5350))/10000;
   4969 
   4970             LOG_ERROR(BSL_LS_SOC_COMMON,
   4971                       (BSL_META_U(unit,
   4972                                   "TempMon %d: %d deg C.\n"), i, trval));
   4973             (void)soc_event_generate(unit, SOC_SWITCH_EVENT_ALARM,
   4974                                      SOC_SWITCH_EVENT_ALARM_HIGH_TEMP, i, trval);
   4975         }
   4976     }
   4977 
   4978     /* Acknowledge the interrupt */
   4979     if ((rv = WRITE_TOP_PVTMON_INTR_STATUS_0r(unit, 0xFFFFFFFF)) != SOC_E_NONE) {
   4980         LOG_ERROR(BSL_LS_SOC_COMMON,
   4981                   (BSL_META_U(unit,
   4982                               "TH3 Temp Intr, Reg access error.\n")));
   4983     }
   4984 
   4985     /* TH3 has HW overtemp protection. So no need to shutdown here. */
   4986 
   4987 }
   4988 
   4989 int
   4990 soc_tomahawk3_temperature_monitor_get(int unit, int temperature_max,
   4991     soc_switch_temperature_monitor_t *temperature_array, int *temperature_count)
   4992 {
   4993     soc_reg_t reg;
   4994     int index, i;
   4995     uint32 rval;
   4996     int cur, peak, fval, cur_fval, peak_fval;
   4997     int num_entries_out;
   4998 
   4999     if (temperature_count) {
   5000         *temperature_count = 0;
   5001     }
   5002     if (COUNTOF(pvtmon_result_reg_th3) > temperature_max) {
   5003         num_entries_out = temperature_max;
   5004     } else {
   5005         num_entries_out = COUNTOF(pvtmon_result_reg_th3) - 1; 
   5006     }
   5007 
   5008     for (index = 0; index < num_entries_out; index++) {
   5009         reg = pvtmon_result_reg_th3[index];
   5010 
   5011         cur_fval = 0;
   5012         peak_fval = 0;
   5013 
   5014         for(i = 0; i < NUM_READS; i++) {
   5015             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   5016 
   5017             cur_fval += soc_reg_field_get(unit, reg, rval, PVT_DATAf);
   5018             peak_fval += soc_reg_field_get(unit, reg, rval, MIN_PVT_DATAf);
   5019         }
   5020         cur_fval /= NUM_READS;
   5021         peak_fval /= NUM_READS;
   5022 
   5023         cur = (4341000-(cur_fval*5350))/1000;
   5024         peak = (4341000-(peak_fval*5350))/1000;
   5025 
   5026         if (temperature_array) {
   5027             (temperature_array + index)->curr = cur;
   5028             (temperature_array + index)->peak = peak;
   5029         }
   5030     }
   5031     SOC_IF_ERROR_RETURN(READ_AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr(unit, &rval));
   5032     if (soc_reg_field_get(unit, AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr, rval, VALID_DATAf)) {
   5033         fval = soc_reg_field_get(unit, AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr, rval, DATAf);
   5034         cur = peak = (4341000-(fval*5350))/1000;
   5035         if (temperature_array) {
   5036             (temperature_array + num_entries_out)->curr = cur;
   5037             (temperature_array + num_entries_out)->peak = cur;
   5038         }
   5039     }
   5040 
   5041     /* TOP_PVT_MON_MIN corresponds to MAX temp. */ 
   5042 
   5043     for (index = 0; index < COUNTOF(pvtmon_ctrl_1_reg_th3); index++) {
   5044         reg =  pvtmon_ctrl_1_reg_th3[index];
   5045         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   5046         soc_reg_field_set(unit, reg, &rval, TOP_PVT_MON_MIN_RST_Lf, 0);
   5047         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   5048         soc_reg_field_set(unit, reg, &rval, TOP_PVT_MON_MIN_RST_Lf, 1);
   5049         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   5050     } 
   5051 
   5052     SOC_IF_ERROR_RETURN(READ_TOP_TMON_CTRL_1r(unit, &rval));
   5053     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_5_TOP_PVT_MON_MIN_RST_Lf, 0);
   5054     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_6_TOP_PVT_MON_MIN_RST_Lf, 0);
   5055     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_7_TOP_PVT_MON_MIN_RST_Lf, 0);
   5056     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_8_TOP_PVT_MON_MIN_RST_Lf, 0);
   5057     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_9_TOP_PVT_MON_MIN_RST_Lf, 0);
   5058     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_10_TOP_PVT_MON_MIN_RST_Lf, 0);
   5059     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_11_TOP_PVT_MON_MIN_RST_Lf, 0);
   5060     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_12_TOP_PVT_MON_MIN_RST_Lf, 0);
   5061     SOC_IF_ERROR_RETURN(WRITE_TOP_TMON_CTRL_1r(unit, rval));
   5062     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_5_TOP_PVT_MON_MIN_RST_Lf, 1);
   5063     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_6_TOP_PVT_MON_MIN_RST_Lf, 1);
   5064     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_7_TOP_PVT_MON_MIN_RST_Lf, 1);
   5065     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_8_TOP_PVT_MON_MIN_RST_Lf, 1);
   5066     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_9_TOP_PVT_MON_MIN_RST_Lf, 1);
   5067     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_10_TOP_PVT_MON_MIN_RST_Lf, 1);
   5068     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_11_TOP_PVT_MON_MIN_RST_Lf, 1);
   5069     soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_12_TOP_PVT_MON_MIN_RST_Lf, 1);
   5070     SOC_IF_ERROR_RETURN(WRITE_TOP_TMON_CTRL_1r(unit, rval));
   5071 
   5072     SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_13_17_CTRL_1r(unit, &rval));
   5073     soc_reg_field_set(unit, TOP_PVTMON_13_17_CTRL_1r, &rval, PVTMON13_TOP_PVT_MON_MIN_RST_Lf, 0);
   5074     soc_reg_field_set(unit, TOP_PVTMON_13_17_CTRL_1r, &rval, PVTMON14_TOP_PVT_MON_MIN_RST_Lf, 0);
   5075     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_13_17_CTRL_1r(unit, rval));
   5076     soc_reg_field_set(unit, TOP_PVTMON_13_17_CTRL_1r, &rval, PVTMON13_TOP_PVT_MON_MIN_RST_Lf, 1);
   5077     soc_reg_field_set(unit, TOP_PVTMON_13_17_CTRL_1r, &rval, PVTMON14_TOP_PVT_MON_MIN_RST_Lf, 1);
   5078     SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_13_17_CTRL_1r(unit, rval));
   5079 
   5080     if (temperature_count) {
   5081         /* *temperature_count = num_entries_out + 1; */
   5082         *temperature_count = num_entries_out; /* Avoid displaying AVS for now */
   5083     }
   5084     return SOC_E_NONE;
   5085 }
   5086 
   5087 int
   5088 soc_tomahawk3_show_ring_osc(int unit)
   5089 {
   5090     static const struct {
   5091         int osc_sel;
   5092         soc_field_t field0;
   5093         int value0;
   5094         soc_field_t field1;
   5095         int value1;
   5096         char *name;
   5097     } osc_tbl[] = {
   5098         { 2, IROSC_SELf, 0, INVALIDf, -1, "Core ring 0 five stages" },
   5099         { 2, IROSC_SELf, 1, INVALIDf, -1, "Core ring 0 nine stages" },
   5100         { 3, IROSC_SELf, 0, INVALIDf, -1, "Core ring 1 five stages" },
   5101         { 3, IROSC_SELf, 1, INVALIDf, -1, "Core ring 1 nine stages" },
   5102         { 4, SRAM_OSC_0_PENf, 0, SRAM_OSC_0_NENf, 1, "SRAM ring 0 NMOS" },
   5103         { 5, SRAM_OSC_0_PENf, 1, SRAM_OSC_0_NENf, 0, "SRAM ring 0 PMOS" },
   5104         { 6, SRAM_OSC_1_PENf, 0, SRAM_OSC_1_NENf, 1, "SRAM ring 1 NMOS" },
   5105         { 7, SRAM_OSC_1_PENf, 1, SRAM_OSC_1_NENf, 0, "SRAM ring 1 PMOS" },
   5106         { 8, SRAM_OSC_2_PENf, 0, SRAM_OSC_2_NENf, 1, "SRAM ring 2 NMOS" },
   5107         { 9, SRAM_OSC_2_PENf, 1, SRAM_OSC_2_NENf, 0, "SRAM ring 2 PMOS" },
   5108         { 10, SRAM_OSC_3_PENf, 0, SRAM_OSC_3_NENf, 1, "SRAM ring 3 NMOS" },
   5109         { 11, SRAM_OSC_3_PENf, 1, SRAM_OSC_3_NENf, 0, "SRAM ring 3 PMOS" }
   5110     };
   5111     soc_reg_t ctrl_reg, stat_reg;
   5112     uint32 rval, fval;
   5113     int index, core_clk, quo, rem, frac, retry;
   5114 
   5115     core_clk = SOC_INFO(unit).frequency * 1024;
   5116     ctrl_reg = TOP_RING_OSC_CTRLr;
   5117     stat_reg = TOP_OSC_COUNT_STATr;
   5118 
   5119     for (index = 0; index < COUNTOF(osc_tbl); index++) {
   5120         rval = 0;
   5121         /*
   5122          * set OSC_CNT_RSTBf to 0 to do softreset
   5123          * set OSC_CNT_START to 0 to hold the counter until it selects
   5124          * the input signal
   5125          */
   5126         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
   5127         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_ENABLEf, 1);
   5128         soc_reg_field_set(unit, ctrl_reg, &rval, IROSC_ENf, 1);
   5129         soc_reg_field_set(unit, ctrl_reg, &rval, osc_tbl[index].field0,
   5130                           osc_tbl[index].value0);
   5131         if (osc_tbl[index].field1 != INVALIDf) {
   5132             soc_reg_field_set(unit, ctrl_reg, &rval, osc_tbl[index].field1,
   5133                               osc_tbl[index].value1);
   5134         }
   5135         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_SELf,
   5136                           osc_tbl[index].osc_sel);
   5137         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
   5138         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_CNT_RSTBf, 1);
   5139         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
   5140         soc_reg_field_set(unit, ctrl_reg, &rval, OSC_CNT_STARTf, 1);
   5141         SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval));
   5142 
   5143         for (retry = 0; retry < 10; retry++) {
   5144             sal_usleep(1000);
   5145             SOC_IF_ERROR_RETURN(READ_TOP_OSC_COUNT_STATr(unit, &rval));
   5146             if (!soc_reg_field_get(unit, stat_reg, rval, OSC_CNT_DONEf)) {
   5147                 continue;
   5148             }
   5149 
   5150             fval = soc_reg_field_get(unit, stat_reg, rval, OSC_CNT_VALUEf);
   5151             quo = core_clk / fval;
   5152             rem = core_clk - quo * fval;
   5153             frac = (rem * 10000) / fval;
   5154             LOG_CLI((BSL_META_U(unit,
   5155                                 "%s: %d.%04d Mhz\n"),
   5156                      osc_tbl[index].name, quo, frac));
   5157             break;
   5158         }
   5159     }
   5160 
   5161     return SOC_E_NONE;
   5162 }
   5163 
   5164 STATIC _soc_th3_bst_hw_cb th3_bst_cb;
   5165 
   5166 int
   5167 soc_th3_process_mmu_bst(int unit, int itm, soc_field_t field)
   5168 {
   5169     int rv = SOC_E_NONE;
   5170     if (th3_bst_cb != NULL) {
   5171         rv = th3_bst_cb(unit);
   5172     }
   5173     return rv;
   5174 }
   5175 
   5176 int soc_th3_set_bst_callback(int unit, _soc_th_bst_hw_cb cb)
   5177 {
   5178     th3_bst_cb = cb;
   5179     return SOC_E_NONE;
   5180 }
   5181 void
   5182 soc_tomahawk3_process_func_intr(void *unit_vp, void *d1, void *d2, void *d3, void *d4)
   5183 {
   5184     int rv = SOC_E_NONE;
   5185     int unit = PTR_TO_INT(unit_vp);
   5186     uint32 rval;
   5187     char       prefix_str[10];
   5188     sal_sprintf(prefix_str, "Unit: %d \n", unit);
   5189 
   5190     rv = READ_L2_MGMT_INTRr(unit, &rval);
   5191     if (SOC_FAILURE(rv)) {
   5192         LOG_ERROR(BSL_LS_SOC_COMMON,
   5193                   (BSL_META_U(unit, "Error reading %s reg !!\n"),
   5194                               SOC_REG_NAME(unit, L2_MGMT_INTRr)));
   5195         return;
   5196     }
   5197 
   5198     if (soc_reg_field_get(unit, L2_MGMT_INTRr, rval, SER_FIFO_NOT_EMPTYf)) {
   5199         (void) soc_tomahawk_process_ser_fifo(unit, SOC_BLK_IPIPE,
   5200                                              0, /* pipe */
   5201                                              prefix_str,
   5202                                              1, 0, 0); /* l2_mgmt_ser_fifo */
   5203     }
   5204 
   5205     if (soc_feature(unit, soc_feature_l2_overflow)) {
   5206         if (soc_reg_field_get(unit, L2_MGMT_INTRr, rval, L2_LEARN_INSERT_FAILUREf)) {
   5207             soc_td2_l2_overflow_interrupt_handler(unit);
   5208         }
   5209     }
   5210 
   5211     sal_usleep(SAL_BOOT_QUICKTURN ? 100000 : 1000); /* Don't reenable too soon */
   5212     if (d1 != NULL) {
   5213 #ifdef BCM_CMICM_SUPPORT
   5214         if (soc_feature(unit, soc_feature_cmicm)) {
   5215             (void) soc_cmicm_intr3_enable(unit, PTR_TO_INT(d1));
   5216         }
   5217 #endif
   5218 #ifdef BCM_CMICX_SUPPORT
   5219         if (soc_feature(unit, soc_feature_cmicx)) {
   5220             
   5221         }
   5222 #endif
   5223     }
   5224 }
   5225 
   5226 soc_pstats_tbl_desc_t
   5227 _soc_th3_pstats_tbl_desc_all = {SOC_BLK_NONE, INVALIDm, FALSE, FALSE};
   5228 soc_pstats_tbl_desc_t _soc_th3_pstats_tbl_desc[] = {
   5229     /* List all the potential memories */
   5230     {
   5231         SOC_BLK_MMU_ITM,
   5232         MMU_THDO_BST_TOTAL_QUEUE_PKTSTATm, /* MMU_THDO_BST_TOTAL_QUEUEm,*/
   5233         FALSE, TRUE
   5234     }
   5235 };
   5236 
   5237 void
   5238 soc_tomahawk3_mmu_pstats_tbl_config_all(int unit)
   5239 {
   5240     soc_control_t *soc = SOC_CONTROL(unit);
   5241     soc_pstats_mem_desc_t *desc, *desc_all;
   5242     int ti, mi, di = 0;
   5243 
   5244     desc_all = _soc_th3_pstats_tbl_desc_all.desc;
   5245     /* Check and strip invalid memories */
   5246     for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) {
   5247         mi = 0;
   5248         desc = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].desc;
   5249         while (desc[mi].mem != INVALIDm) {
   5250             desc_all[di] = desc[mi];
   5251             di++;
   5252             mi++;
   5253         }
   5254     }
   5255     desc_all[di].mem = INVALIDm;
   5256 
   5257     soc->pstats_tbl_desc = &_soc_th3_pstats_tbl_desc_all;
   5258     soc->pstats_tbl_desc_count = 1;
   5259 }
   5260 
   5261 void
   5262 soc_tomahawk3_mmu_pstats_tbl_config(int unit)
   5263 {
   5264     soc_control_t *soc = SOC_CONTROL(unit);
   5265     soc_info_t *si = &SOC_INFO(unit);
   5266     soc_pstats_mem_desc_t *desc;
   5267     soc_mem_t bmem;
   5268     int pe, mor_dma;
   5269     int ti, mi, itm, pipe;
   5270     uint32 itm_map;
   5271     uint32 pipe_map;
   5272 
   5273     soc->pstats_tbl_desc = _soc_th3_pstats_tbl_desc;
   5274     soc->pstats_tbl_desc_count = COUNTOF(_soc_th3_pstats_tbl_desc);
   5275     soc->pstats_mode = PSTATS_MODE_NULL;
   5276 
   5277     itm_map = si->itm_map;
   5278     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   5279     /* Check and strip invalid memories */
   5280     for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) {
   5281         mi = 0;
   5282         desc = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].desc;
   5283         bmem = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].bmem;
   5284         if (bmem == INVALIDm) {
   5285             while (desc[mi].mem != INVALIDm) {
   5286                 desc[mi].width = soc_mem_entry_words(unit, desc[mi].mem);
   5287                 desc[mi].entries = soc_mem_index_count(unit, desc[mi].mem);
   5288                 mi++;
   5289             }
   5290             continue;
   5291         }
   5292         pe = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].pipe_enum;
   5293         mor_dma = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].mor_dma;
   5294         for (itm = 0; itm < NUM_ITM(unit); itm++) {
   5295             if (!(itm_map & (1U << itm))) {
   5296                 continue;
   5297             }
   5298             for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   5299                 if (!(pipe_map & (1 << pipe))) {
   5300                     continue;
   5301                 }
   5302                 desc[mi].mem = pe ? SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit, bmem, itm, pipe) :
   5303                                     SOC_MEM_UNIQUE_ACC(unit, bmem)[itm];
   5304                 if (desc[mi].mem == INVALIDm) {
   5305                     continue;
   5306                 }
   5307                 desc[mi].width = soc_mem_entry_words(unit, desc[mi].mem);
   5308                 desc[mi].entries = soc_mem_index_count(unit, desc[mi].mem);
   5309                 if (mor_dma) {
   5310                     desc[mi].mor_dma = TRUE;
   5311                 }
   5312                 mi++;
   5313                 if (!pe) {
   5314                     break;
   5315                 }
   5316             }
   5317         }
   5318         desc[mi].mem = INVALIDm;
   5319     }
   5320 
   5321     if (soc_property_get(unit, "pstats_desc_all", 1)) {
   5322         /* Use single desc chain */
   5323         soc_tomahawk3_mmu_pstats_tbl_config_all(unit);
   5324     }
   5325 }
   5326 
   5327 int
   5328 soc_tomahawk3_mmu_pstats_mode_set(int unit, uint32 flags)
   5329 {
   5330 #define _SOC_MMU_PSTATS_BLK 2
   5331     soc_control_t *soc = SOC_CONTROL(unit);
   5332     int i, hwm_mode, cor_en;
   5333     int pf = 0;
   5334     uint32 rval;
   5335     soc_reg_t reg = INVALIDr;
   5336     soc_reg_t blk_regs[_SOC_MMU_PSTATS_BLK] =
   5337                 {MMU_THDO_BST_CONFIGr, MMU_THDI_BSTCONFIGr};
   5338     soc_field_t cor_fields[] = {HWM_CORf, HW_CORf};
   5339     soc_field_t mode_fields[] = {TRACKING_MODEf, TRACKING_MODEf};
   5340     soc_field_t track_fields[] = {BST_TRACK_EN_THDO0f, BST_TRACK_EN_THDO1f,
   5341                                 BST_TRACK_EN_THDI0f, BST_TRACK_EN_THDI1f};
   5342     SOC_PSTATS_LOCK(unit);
   5343 
   5344     hwm_mode = cor_en = 0;
   5345     if (flags & _TH3_MMU_PSTATS_HWM_MOD) {
   5346         hwm_mode = 1;
   5347         pf |= _TH3_MMU_PSTATS_HWM_MOD;
   5348         if (flags & _TH3_MMU_PSTATS_RESET_ON_READ) {
   5349             cor_en = 1;
   5350             pf |= _TH3_MMU_PSTATS_RESET_ON_READ;
   5351         }
   5352     }
   5353     for (i = 0; i < _SOC_MMU_PSTATS_BLK; i++) {
   5354         reg = blk_regs[i];
   5355         rval = 0;
   5356         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   5357         soc_reg_field_set(unit, reg, &rval, mode_fields[i], hwm_mode);
   5358         soc_reg_field_set(unit, reg, &rval, cor_fields[i], cor_en);
   5359         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   5360     }
   5361     if (flags & _TH3_MMU_PSTATS_ENABLE) {
   5362         pf |= _TH3_MMU_PSTATS_ENABLE;
   5363         if ((flags & _TH3_MMU_PSTATS_SYNC) ||
   5364                 (flags & _TH3_MMU_PSTATS_HWM_MOD &&
   5365                  flags & _TH3_MMU_PSTATS_RESET_ON_READ)) {
   5366             soc->pstats_mode = PSTATS_MODE_PKT_SYNC;
   5367             pf |= _TH3_MMU_PSTATS_SYNC;
   5368         }
   5369         /* enable BST tracking */
   5370         rval = 0;
   5371         reg = MMU_GLBCFG_BST_TRACKING_ENABLEr;
   5372         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   5373         for (i = 0; i < _SOC_MMU_PSTATS_BLK; i++) {
   5374             soc_reg_field_set(unit, reg, &rval, track_fields[2 * i], 1);
   5375             soc_reg_field_set(unit, reg, &rval, track_fields[2 * i + 1], 1);
   5376         }
   5377         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   5378         /* disable snapshot */
   5379         rval = 0;
   5380         reg = MMU_GLBCFG_BST_SNAPSHOT_ACTION_ENr;
   5381         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   5382 
   5383     } else {
   5384        soc->pstats_mode = PSTATS_MODE_NULL;
   5385     }
   5386     soc->pstats_flags = pf;
   5387     SOC_PSTATS_UNLOCK(unit);
   5388 #undef _SOC_MMU_PSTATS_BLK
   5389     return SOC_E_NONE;
   5390 }
   5391 
   5392 int
   5393 soc_tomahawk3_mmu_pstats_mode_get(int unit, uint32 *flags)
   5394 {
   5395     int pf = 0;
   5396     uint32 rval = 0;
   5397     int rv;
   5398     soc_reg_t reg = INVALIDr;
   5399     soc_field_t track_fields[] = {BST_TRACK_EN_THDO0f, BST_TRACK_EN_THDO1f,
   5400                                 BST_TRACK_EN_THDI0f, BST_TRACK_EN_THDI1f};
   5401 
   5402     SOC_PSTATS_LOCK(unit);
   5403 
   5404     rv = READ_MMU_GLBCFG_BST_TRACKING_ENABLEr(unit, &rval);
   5405 
   5406     if (SOC_FAILURE(rv)) {
   5407         SOC_PSTATS_UNLOCK(unit);
   5408         return rv;
   5409     }
   5410 
   5411     /* If one of the BST thresholds is enabled then PSTATS
   5412        is enabled */
   5413     reg = MMU_GLBCFG_BST_TRACKING_ENABLEr;
   5414     if (soc_reg_field_get(unit, reg, rval, track_fields[0]) ||
   5415         soc_reg_field_get(unit, reg, rval, track_fields[1]) ||
   5416         soc_reg_field_get(unit, reg, rval, track_fields[2]) ||
   5417         soc_reg_field_get(unit, reg, rval, track_fields[3])) {
   5418         pf |= _TH3_MMU_PSTATS_ENABLE;
   5419     }
   5420 
   5421     reg = MMU_THDI_BSTCONFIGr;
   5422     rval = 0;
   5423     SOC_IF_ERROR_RETURN(
   5424         soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   5425 
   5426     if (soc_reg_field_get(unit, reg, rval, TRACKING_MODEf)) {
   5427         pf |= _TH3_MMU_PSTATS_HWM_MOD;
   5428         if (soc_reg_field_get(unit, reg, rval, HW_CORf)) {
   5429             pf |= _TH3_MMU_PSTATS_RESET_ON_READ;
   5430         }
   5431     }
   5432 
   5433     reg = MMU_THDO_BST_CONFIGr;
   5434     rval = 0;
   5435     SOC_IF_ERROR_RETURN(
   5436         soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   5437 
   5438     if (soc_reg_field_get(unit, reg, rval, TRACKING_MODEf)) {
   5439         pf |= _TH3_MMU_PSTATS_HWM_MOD_EGR;
   5440         if (soc_reg_field_get(unit, reg, rval, HWM_CORf)) {
   5441             pf |= _TH3_MMU_PSTATS_RESET_ON_READ_EGR;
   5442         }
   5443     }
   5444 
   5445     SOC_PSTATS_UNLOCK(unit);
   5446     *flags = pf;
   5447 
   5448     return SOC_E_NONE;
   5449 }
   5450 
   5451 int
   5452 soc_tomahawk3_mmu_splitter_reset(int unit)
   5453 {
   5454     uint32 rval;
   5455 
   5456     SOC_IF_ERROR_RETURN(READ_MMU_GLBCFG_SPLITTERr(unit, &rval));
   5457     soc_reg_field_set(unit, MMU_GLBCFG_SPLITTERr, &rval, RESET_SBUSf, 1);
   5458     SOC_IF_ERROR_RETURN(WRITE_MMU_GLBCFG_SPLITTERr(unit, rval));
   5459 
   5460     return SOC_E_NONE;
   5461 }
   5462 
   5463 int
   5464 soc_th3_mmu_non_ser_intr_handler(int unit, soc_block_t blocktype,
   5465                                  int mmu_base_index,
   5466                                  uint32 rval_intr_status_reg)
   5467 {
   5468     int i;
   5469     soc_reg_t intr_stat_reg/*, intr_clr_reg*/;
   5470     static soc_field_t itm_intr_field_list[] = {
   5471         CRB_INT_STATf,
   5472         THDI_INT_STATf,
   5473         THDR_INT_STATf,
   5474         CFAP_INT_STATf,
   5475         RQE_INT_STATf,
   5476         THDO_INT_STATf,
   5477         INVALIDf
   5478     };
   5479     static soc_field_t eb_intr_field_list[] = {
   5480         EBCTM_INT_STATf,
   5481         EBCFP_INT_STATf,
   5482         MTRO_INT_STATf,
   5483         INVALIDf
   5484     };
   5485 
   5486     if (blocktype == SOC_BLK_MMU_ITM) {
   5487         intr_stat_reg = MMU_ITMCFG_CPU_INT_STATr;
   5488         /* SW is allowed to clear an interrupt by writing 1'b1 to that status bit. */
   5489         /*intr_clr_reg = MMU_ITMCFG_CPU_INT_STATr;*/
   5490         for (i = 0; itm_intr_field_list[i] != INVALIDf; i++) {
   5491             if (!soc_reg_field_get(unit, intr_stat_reg,
   5492                                    rval_intr_status_reg,
   5493                                    itm_intr_field_list[i])) {
   5494                 continue;
   5495             }
   5496             switch (itm_intr_field_list[i]) {
   5497             case CFAP_INT_STATf:
   5498                 SOC_IF_ERROR_RETURN(soc_th3_process_itm_cfap_int(unit,
   5499                             mmu_base_index, itm_intr_field_list[i]));
   5500                 break;
   5501             case THDI_INT_STATf:
   5502                 SOC_IF_ERROR_RETURN(soc_th3_process_itm_thdi_int(unit,
   5503                             mmu_base_index, itm_intr_field_list[i]));
   5504                 break;
   5505             case THDO_INT_STATf:
   5506                 SOC_IF_ERROR_RETURN(soc_th3_process_itm_thdo_int(unit,
   5507                             mmu_base_index, itm_intr_field_list[i]));
   5508                 break;
   5509             case THDR_INT_STATf:
   5510                 SOC_IF_ERROR_RETURN(soc_th3_process_itm_thdr_int(unit,
   5511                             mmu_base_index, itm_intr_field_list[i]));
   5512                 break;
   5513             case RQE_INT_STATf:
   5514                 SOC_IF_ERROR_RETURN(soc_th3_process_itm_rqe_int(unit,
   5515                             mmu_base_index, itm_intr_field_list[i]));
   5516                 break;
   5517             case CRB_INT_STATf:
   5518                 SOC_IF_ERROR_RETURN(soc_th3_process_itm_crb_int(unit,
   5519                             mmu_base_index, itm_intr_field_list[i]));
   5520                 break;
   5521             default:
   5522                 LOG_ERROR(BSL_LS_SOC_COMMON,
   5523                           (BSL_META_U(unit, "Unit: %0d -- Could not service %s "
   5524                                             "intr from itm = %0d \n"),
   5525                            unit, SOC_FIELD_NAME(unit, itm_intr_field_list[i]),
   5526                            mmu_base_index));
   5527                 break;
   5528             }
   5529         }
   5530         return SOC_E_NONE;
   5531     }
   5532 
   5533     if (blocktype == SOC_BLK_MMU_EB) {
   5534         intr_stat_reg = MMU_EBCFG_CPU_INT_STATr;
   5535         /* SW is allowed to clear an interrupt by writing 1'b1 to that status bit. */
   5536         /*intr_clr_reg = MMU_EBCFG_CPU_INT_STATr;*/
   5537         for (i = 0; eb_intr_field_list[i] != INVALIDf; i++) {
   5538             if (!soc_reg_field_get(unit, intr_stat_reg,
   5539                                    rval_intr_status_reg,
   5540                                    eb_intr_field_list[i])) {
   5541                 continue;
   5542             }
   5543             switch (eb_intr_field_list[i]) {
   5544                 case EBCTM_INT_STATf:
   5545                     SOC_IF_ERROR_RETURN(
   5546                         soc_th3_process_eb_ebctm_int(unit, mmu_base_index,
   5547                             eb_intr_field_list[i]));
   5548                     break;
   5549                 case EBCFP_INT_STATf:
   5550                     SOC_IF_ERROR_RETURN(
   5551                         soc_th3_process_eb_ebcfp_int(unit, mmu_base_index,
   5552                             eb_intr_field_list[i]));
   5553                     break;
   5554                 case MTRO_INT_STATf:
   5555                     SOC_IF_ERROR_RETURN(
   5556                         soc_th3_process_eb_mtro_int(unit, mmu_base_index,
   5557                             eb_intr_field_list[i]));
   5558                     break;
   5559                 default:
   5560                     LOG_ERROR(BSL_LS_SOC_COMMON,
   5561                               (BSL_META_U(unit, "Unit: %0d -- Could not service %s "
   5562                                                 "intr from sc = %0d \n"),
   5563                                unit, SOC_FIELD_NAME(unit, eb_intr_field_list[i]),
   5564                                mmu_base_index));
   5565                     break;
   5566             }
   5567         }
   5568         return SOC_E_NONE;
   5569     }
   5570 
   5571     /* cannot be here for any other blocktype */
   5572     return SOC_E_FAIL;
   5573 }
   5574 
   5575 /*
   5576  * Function:
   5577  *      soc_th3_skip_obm_mem_if_pm_down
   5578  * Purpose:
   5579  *      Checks the passed memory. If it's of type
   5580  *      IDB_OBM*_IOM_STATS_WINDOW_RESULTS*, check to see if the PM it is
   5581  *      associated with is disabled.  If the PM is disabled, tell the calling
   5582  *      function to skip reading the memory
   5583  * Parameters:
   5584  *      unit        - (IN) Unit number.
   5585  *      mem         - (IN) The mem to check
   5586  *      skip        - (OUT) Pointer to tell whether the memory should be
   5587  *                          skipped
   5588  * Returns:
   5589  *      SOC_E_XXX
   5590  * Note:
   5591  */
   5592 int
   5593 soc_th3_skip_obm_mem_if_pm_down(int unit, soc_mem_t mem, int *skip)
   5594 {
   5595     int i, j, pm_num;
   5596     uint32 rval;
   5597     soc_reg_t reg = TOP_TSC_ENABLEr;
   5598     soc_field_t reg_field[_TH3_PBLKS_PER_DEV] = {
   5599         TSC_0_ENABLEf, TSC_1_ENABLEf, TSC_2_ENABLEf, TSC_3_ENABLEf,
   5600         TSC_4_ENABLEf, TSC_5_ENABLEf, TSC_6_ENABLEf, TSC_7_ENABLEf,
   5601         TSC_8_ENABLEf, TSC_9_ENABLEf, TSC_10_ENABLEf, TSC_11_ENABLEf,
   5602         TSC_12_ENABLEf, TSC_13_ENABLEf, TSC_14_ENABLEf, TSC_15_ENABLEf,
   5603         TSC_16_ENABLEf, TSC_17_ENABLEf, TSC_18_ENABLEf, TSC_19_ENABLEf,
   5604         TSC_20_ENABLEf, TSC_21_ENABLEf, TSC_22_ENABLEf, TSC_23_ENABLEf,
   5605         TSC_24_ENABLEf, TSC_25_ENABLEf, TSC_26_ENABLEf, TSC_27_ENABLEf,
   5606         TSC_28_ENABLEf, TSC_29_ENABLEf, TSC_30_ENABLEf, TSC_31_ENABLEf
   5607     };
   5608 
   5609     soc_mem_t mem_it, mem_it_unique;
   5610     soc_mem_t iom_stats_window_results[] =
   5611                     { IDB_OBM0_IOM_STATS_WINDOW_RESULTSm,
   5612                       IDB_OBM1_IOM_STATS_WINDOW_RESULTSm,
   5613                       IDB_OBM2_IOM_STATS_WINDOW_RESULTSm,
   5614                       IDB_OBM3_IOM_STATS_WINDOW_RESULTSm };
   5615 
   5616 
   5617     if (NULL == skip) {
   5618         return SOC_E_PARAM;
   5619     }
   5620     /* start with skip == 0 */
   5621     *skip = 0;
   5622 
   5623     /* Check if the memory passed is one that we want to check */
   5624     for (i = 0; i < COUNTOF(iom_stats_window_results); i++) {
   5625         /* Must be in the range of the starting memory, plus all the
   5626          * individual ones for each pipe */
   5627         if (mem >= iom_stats_window_results[i] &&
   5628             mem <= iom_stats_window_results[i] + _TH3_PIPES_PER_DEV) {
   5629             break;
   5630         }
   5631     }
   5632 
   5633     /* return if not in range */
   5634     if (i == COUNTOF(iom_stats_window_results)) {
   5635         return SOC_E_NONE;
   5636     }
   5637 
   5638     for (i = 0; i < _TH3_PIPES_PER_DEV; i++) {
   5639         for (j = 0; j < _TH3_PBLKS_PER_PIPE; j++) {
   5640             /* Get the current port block index */
   5641             mem_it = iom_stats_window_results[j];
   5642 
   5643             /* Get the port block index for the pipe */
   5644             mem_it_unique = SOC_MEM_UNIQUE_ACC(unit, mem_it)[i];
   5645 
   5646 
   5647             /* if the memory is the passed one, check if the port
   5648              * macro is disabled */
   5649             if (mem_it == mem || mem_it_unique == mem) {
   5650                 /* get the pm number associated with this mem */
   5651                 pm_num = (i * _TH3_PBLKS_PER_PIPE) + j;
   5652 
   5653                 SOC_IF_ERROR_RETURN(
   5654                         soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   5655 
   5656                 /* check if the PM is disabled */
   5657                 if (!soc_reg_field_get(unit, reg, rval, reg_field[pm_num])) {
   5658                     /* if disabled, skip this memory */
   5659                     *skip = 1;
   5660                     return SOC_E_NONE;
   5661                 }
   5662             }
   5663         }
   5664     }
   5665     return SOC_E_NONE;
   5666 }
   5667 
   5668 /*
   5669  * Tomahawk chip driver functions.
   5670  * Pls keep at the end of this file for easy access.
   5671  */
   5672 soc_functions_t soc_tomahawk3_drv_funs = {
   5673     _soc_tomahawk3_misc_init,
   5674     _soc_tomahawk3_mmu_init,
   5675     _soc_tomahawk3_age_timer_get,
   5676     _soc_tomahawk3_age_timer_max_get,
   5677     _soc_tomahawk3_age_timer_set,
   5678     _soc_tomahawk3_tscx_firmware_set,
   5679     _soc_tomahawk3_tscx_reg_read,
   5680     _soc_tomahawk3_tscx_reg_write,
   5681     soc_tomahawk3_bond_info_init
   5682 };
   5683 #endif /* BCM_TOMAHAWK3_SUPPORT */
   5684